Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented a function for smarter debug formatting. #606

Merged
merged 31 commits into from
Apr 26, 2019
Merged
Changes from 2 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
fe4365c
Implemented a function for smarter debug formatting.
Mar 24, 2019
2450f50
Fixed existing tests
Mar 24, 2019
3474d3f
Some fixes:
Mar 26, 2019
2a8a7c7
Implemented axis shrinking for n-dim arrays
Mar 26, 2019
1b5da67
All the PR issues are fixed. Tests are needed.
Mar 27, 2019
fbf8cac
Fixed the tests
Mar 27, 2019
51c4e11
Added tests for 1- and 2-dimensional array with overflow
Mar 27, 2019
0d11708
Try to fix 1.31 build failing
Mar 27, 2019
18c868a
PRINT_ELEMENTS_LIMIT is now private
Mar 28, 2019
3aa8abe
Remove dead code
LukeMathWalker Apr 16, 2019
17f86bb
Rename format_array_v2 to format_array
LukeMathWalker Apr 16, 2019
d48c5a9
Simplify code using ndim
LukeMathWalker Apr 16, 2019
6c636dc
Access last element directly
LukeMathWalker Apr 16, 2019
88d53e3
Add a test to specify behaviour for zero-dimensional arrays
LukeMathWalker Apr 16, 2019
b962a7b
Add a test for empty arrays
LukeMathWalker Apr 16, 2019
29a8f70
Test zero-length axes
LukeMathWalker Apr 16, 2019
27c4a92
We already know that ndim > 0
LukeMathWalker Apr 16, 2019
49b4338
Merge pull request #2 from LukeMathWalker/smart-debug-formatting-review
Apr 17, 2019
b535f28
Made the formatting logic more modular
Apr 17, 2019
2a8a3b0
Simplify element access
Apr 20, 2019
5fd9b2f
Almost there
Apr 20, 2019
f60185c
Clone for the win
Apr 20, 2019
198d689
Cast to 1d array
Apr 20, 2019
c1036fb
First and last elements have to be special cased. Done for multidimen…
Apr 20, 2019
5336b10
Extract in a separate function
Apr 21, 2019
4fa8a62
Tests are passing
Apr 21, 2019
e659390
Minor improvements
Apr 21, 2019
0abff2a
Formatting
Apr 21, 2019
e049abd
Remove closure
Apr 23, 2019
83c9f08
Use custom enum
Apr 23, 2019
72e05d7
Merge pull request #3 from LukeMathWalker/refactoring-smarter-debugging
Apr 23, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 196 additions & 2 deletions src/arrayformat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,203 @@ use super::{
Data,
Dimension,
NdProducer,
Ix
};
use crate::dimension::IntoDimension;

#[derive(Debug)]
enum ArrayDisplayMode {
// Array is small enough to me printed without omitting any values.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: to me printed

Full,
// Omit central values of the nth axis. Since we print that axis horizontally, ellipses
// on each row do something like a split of the array into 2 parts vertically.
VSplit,
// Omit central values of the certain axis. Since we do it only once, ellipses on each row
// do something like a split of the array into 2 parts horizontally.
HSplit(Ix),
// Both `VSplit` and `HSplit` hold.
DoubleSplit(Ix),
}

const PRINT_ELEMENTS_LIMIT: Ix = 5;

impl ArrayDisplayMode {
fn from_array<A, S, D>(arr: &ArrayBase<S, D>, limit: usize) -> ArrayDisplayMode
LukeMathWalker marked this conversation as resolved.
Show resolved Hide resolved
where S: Data<Elem=A>,
D: Dimension
{
let last_dim = match arr.shape().len().checked_sub(1) {
Some(v) => v,
None => {
return ArrayDisplayMode::Full;
}
};

let mut overflow_axis_pair: (Option<usize>, Option<usize>) = (None, None);
for (axis, axis_size) in arr.shape().iter().enumerate().rev() {
if *axis_size >= 2 * limit + 1 {
match overflow_axis_pair.0 {
Some(_) => {
if let None = overflow_axis_pair.1 {
overflow_axis_pair.1 = Some(axis);
}
},
None => {
if axis != last_dim {
return ArrayDisplayMode::HSplit(axis);
}
overflow_axis_pair.0 = Some(axis);
}
}
}
}

match overflow_axis_pair {
(Some(_), Some(h_axis)) => ArrayDisplayMode::DoubleSplit(h_axis),
(Some(_), None) => ArrayDisplayMode::VSplit,
(None, _) => ArrayDisplayMode::Full,
}
}

fn h_split_offset(&self) -> Option<Ix> {
match self {
ArrayDisplayMode::DoubleSplit(axis) | ArrayDisplayMode::HSplit(axis) => {
Some(axis + 1usize)
},
_ => None
}
}
}

fn format_array_v2<A, S, D, F>(view: &ArrayBase<S, D>,
f: &mut fmt::Formatter,
mut format: F,
limit: usize) -> fmt::Result
where F: FnMut(&A, &mut fmt::Formatter) -> fmt::Result,
D: Dimension,
S: Data<Elem=A>,
{
let display_mode = ArrayDisplayMode::from_array(view, limit);

let ndim = view.dim().into_dimension().slice().len();
let nth_idx_max = if ndim > 0 { Some(view.shape().iter().last().unwrap()) } else { None };

// None will be an empty iter.
let mut last_index = match view.dim().into_dimension().first_index() {
None => view.dim().into_dimension().clone(),
Some(ix) => ix,
};
for _ in 0..ndim {
write!(f, "[")?;
}
let mut first = true;
// Shows if ellipses for vertical split were printed.
let mut printed_ellipses_v = false;
// Shows if ellipses for horizontal split were printed.
let mut printed_ellipses_h = false;
// Shows if the row was printed for the first time after horizontal split.
let mut no_rows_after_skip_yet = false;

// Simply use the indexed iterator, and take the index wraparounds
// as cues for when to add []'s and how many to add.
for (index, elt) in view.indexed_iter() {
let index = index.into_dimension();
let take_n = if ndim == 0 { 1 } else { ndim - 1 };
let mut update_index = false;

let mut print_row = true;
match display_mode {
ArrayDisplayMode::HSplit(axis) | ArrayDisplayMode::DoubleSplit(axis) => {
let sa_idx_max = view.shape().iter().skip(axis).next().unwrap();
let sa_idx_val = index.slice().iter().skip(axis).next().unwrap();
if sa_idx_val >= &limit && sa_idx_val < &(sa_idx_max - &limit) {
print_row = false;
no_rows_after_skip_yet = true;
}
},
_ => {}
}

for (i, (a, b)) in index.slice()
.iter()
.take(take_n)
.zip(last_index.slice().iter())
.enumerate() {
if a != b {
if print_row {
printed_ellipses_v = false;
// New row.
// # of ['s needed
let n = ndim - i - 1;
if !no_rows_after_skip_yet {
for _ in 0..n {
write!(f, "]")?;
LukeMathWalker marked this conversation as resolved.
Show resolved Hide resolved
}
write!(f, ",")?;
write!(f, "\n")?;
LukeMathWalker marked this conversation as resolved.
Show resolved Hide resolved
}
no_rows_after_skip_yet = false;
for _ in 0..ndim - n {
write!(f, " ")?;
}
for _ in 0..n {
write!(f, "[")?;
}
} else if !printed_ellipses_h {
let n = ndim - i - 1;
for _ in 0..n {
write!(f, "]")?;
}
write!(f, ",")?;
write!(f, "\n")?;
for _ in 0..display_mode.h_split_offset().unwrap() {
write!(f, " ")?;
}
write!(f, "...,\n")?;
printed_ellipses_h = true;
}
first = true;
update_index = true;
break;
}
}

if print_row {
let mut print_elt = true;
let nth_idx_op = index.slice().iter().last();
match display_mode {
ArrayDisplayMode::VSplit | ArrayDisplayMode::DoubleSplit(_) => {
let nth_idx_val = nth_idx_op.unwrap();
if nth_idx_val >= &limit && nth_idx_val < &(nth_idx_max.unwrap() - &limit) {
print_elt = false;
if !printed_ellipses_v {
write!(f, ", ...")?;
printed_ellipses_v = true;
}
}
}
_ => {}
}

if print_elt {
if !first {
write!(f, ", ")?;
}
first = false;
format(elt, f)?;
}
}

if update_index {
last_index = index;
}
}
for _ in 0..ndim {
write!(f, "]")?;
}
Ok(())
}

fn format_array<A, S, D, F>(view: &ArrayBase<S, D>, f: &mut fmt::Formatter,
mut format: F)
-> fmt::Result
Expand Down Expand Up @@ -92,7 +286,7 @@ impl<'a, A: fmt::Display, S, D: Dimension> fmt::Display for ArrayBase<S, D>
where S: Data<Elem=A>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
format_array(self, f, <_>::fmt)
format_array_v2(self, f, <_>::fmt, PRINT_ELEMENTS_LIMIT)
}
}

Expand All @@ -105,7 +299,7 @@ impl<'a, A: fmt::Debug, S, D: Dimension> fmt::Debug for ArrayBase<S, D>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Add extra information for Debug
format_array(self, f, <_>::fmt)?;
format_array_v2(self, f, <_>::fmt, PRINT_ELEMENTS_LIMIT)?;
write!(f, " shape={:?}, strides={:?}, layout={:?}",
self.shape(), self.strides(), layout=self.view().layout())?;
match D::NDIM {
Expand Down