Skip to content

Commit 2a8a7c7

Browse files
author
andrei-papou
committed
Implemented axis shrinking for n-dim arrays
1 parent 3474d3f commit 2a8a7c7

File tree

1 file changed

+51
-60
lines changed

1 file changed

+51
-60
lines changed

src/arrayformat.rs

Lines changed: 51 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88
use std::fmt;
9+
use std::slice::Iter;
910
use super::{
1011
ArrayBase,
1112
Data,
@@ -15,72 +16,61 @@ use super::{
1516
};
1617
use crate::dimension::IntoDimension;
1718

18-
#[derive(Debug)]
19+
#[derive(Debug, PartialEq)]
1920
enum ArrayDisplayMode {
2021
// Array is small enough to be printed without omitting any values.
2122
Full,
22-
// Omit central values of the nth axis. Since we print that axis horizontally, ellipses
23-
// on each row do something like a split of the array into 2 parts vertically.
24-
VSplit,
25-
// Omit central values of the certain axis. Since we do it only once, ellipses on each row
26-
// do something like a split of the array into 2 parts horizontally.
27-
HSplit(Ix),
28-
// Both `VSplit` and `HSplit` hold.
29-
DoubleSplit(Ix),
23+
// Omit central values of the nth axis.
24+
OmitV,
25+
// Omit central values of certain axes (but not the last one).
26+
// Vector is guaranteed to be non-empty.
27+
OmitH(Vec<Ix>),
28+
// Both `OmitV` and `OmitH` hold.
29+
OmitBoth(Vec<Ix>),
3030
}
3131

32-
const PRINT_ELEMENTS_LIMIT: Ix = 5;
32+
const PRINT_ELEMENTS_LIMIT: Ix = 2;
3333

3434
impl ArrayDisplayMode {
35-
fn from_shape(shape: &[Ix], limit: Ix) -> ArrayDisplayMode
36-
{
35+
36+
fn from_shape(shape: &[Ix], limit: Ix) -> ArrayDisplayMode {
3737
let last_dim = match shape.len().checked_sub(1) {
3838
Some(v) => v,
3939
None => {
4040
return ArrayDisplayMode::Full;
4141
}
4242
};
4343

44+
let last_axis_ovf = shape[last_dim] >= 2 * limit + 1;
4445
let mut overflow_axes: Vec<Ix> = Vec::with_capacity(shape.len());
4546
for (axis, axis_size) in shape.iter().enumerate().rev() {
47+
if axis == last_dim {
48+
continue;
49+
}
4650
if *axis_size >= 2 * limit + 1 {
4751
overflow_axes.push(axis);
4852
}
4953
}
5054

51-
if overflow_axes.is_empty() {
52-
return ArrayDisplayMode::Full;
53-
}
54-
55-
let min_ovf_axis = *overflow_axes.iter().min().unwrap();
56-
let max_ovf_axis = *overflow_axes.iter().max().unwrap();
57-
58-
if max_ovf_axis == last_dim {
59-
if min_ovf_axis != max_ovf_axis {
60-
ArrayDisplayMode::DoubleSplit(min_ovf_axis)
61-
} else {
62-
ArrayDisplayMode::VSplit
63-
}
55+
if !overflow_axes.is_empty() && last_axis_ovf {
56+
ArrayDisplayMode::OmitBoth(overflow_axes)
57+
} else if !overflow_axes.is_empty() {
58+
ArrayDisplayMode::OmitH(overflow_axes)
59+
} else if last_axis_ovf {
60+
ArrayDisplayMode::OmitV
6461
} else {
65-
ArrayDisplayMode::HSplit(min_ovf_axis)
62+
ArrayDisplayMode::Full
6663
}
6764
}
6865

69-
fn h_split_axis(&self) -> Option<Ix> {
66+
fn h_axes_iter(&self) -> Option<Iter<Ix>> {
7067
match self {
71-
ArrayDisplayMode::DoubleSplit(axis) | ArrayDisplayMode::HSplit(axis) => {
72-
Some(*axis)
68+
ArrayDisplayMode::OmitH(v) | ArrayDisplayMode::OmitBoth(v) => {
69+
Some(v.iter())
7370
},
7471
_ => None
7572
}
7673
}
77-
78-
fn h_split_offset(&self) -> Option<Ix> {
79-
match self.h_split_axis() {
80-
Some(axis) => Some(axis + 1usize),
81-
None => None
82-
}
83-
}
8474
}
8575

8676
fn format_array_v2<A, S, D, F>(view: &ArrayBase<S, D>,
@@ -108,7 +98,7 @@ fn format_array_v2<A, S, D, F>(view: &ArrayBase<S, D>,
10898
// Shows if ellipses for vertical split were printed.
10999
let mut printed_ellipses_v = false;
110100
// Shows if ellipses for horizontal split were printed.
111-
let mut printed_ellipses_h = false;
101+
let mut printed_ellipses_h = vec![false; ndim];
112102
// Shows if the row was printed for the first time after horizontal split.
113103
let mut no_rows_after_skip_yet = false;
114104

@@ -119,17 +109,20 @@ fn format_array_v2<A, S, D, F>(view: &ArrayBase<S, D>,
119109
let take_n = if ndim == 0 { 1 } else { ndim - 1 };
120110
let mut update_index = false;
121111

122-
let mut print_row = true;
123-
match display_mode {
124-
ArrayDisplayMode::HSplit(axis) | ArrayDisplayMode::DoubleSplit(axis) => {
125-
let sa_idx_max = view.shape().iter().skip(axis).next().unwrap();
126-
let sa_idx_val = index.slice().iter().skip(axis).next().unwrap();
127-
if sa_idx_val >= &limit && sa_idx_val < &(sa_idx_max - &limit) {
128-
print_row = false;
129-
no_rows_after_skip_yet = true;
130-
}
112+
let skip_row_for_axis = match display_mode.h_axes_iter() {
113+
Some(iter) => {
114+
iter.filter(|axis| {
115+
let sa_idx_max = view.shape().iter().skip(**axis).next().unwrap();
116+
let sa_idx_val = index.slice().iter().skip(**axis).next().unwrap();
117+
sa_idx_val >= &limit && sa_idx_val < &(sa_idx_max - &limit)
118+
})
119+
.min()
120+
.map(|v| *v)
131121
},
132-
_ => {}
122+
None => None
123+
};
124+
if let Some(_) = skip_row_for_axis {
125+
no_rows_after_skip_yet = true;
133126
}
134127

135128
for (i, (a, b)) in index.slice()
@@ -138,13 +131,9 @@ fn format_array_v2<A, S, D, F>(view: &ArrayBase<S, D>,
138131
.zip(last_index.slice().iter())
139132
.enumerate() {
140133
if a != b {
141-
if let Some(axis) = display_mode.h_split_axis() {
142-
if i < axis {
143-
printed_ellipses_h = false;
144-
}
145-
}
134+
printed_ellipses_h.iter_mut().skip(i + 1).for_each(|e| { *e = false; });
146135

147-
if print_row {
136+
if skip_row_for_axis.is_none() {
148137
printed_ellipses_v = false;
149138
// New row.
150139
// # of ['s needed
@@ -163,30 +152,31 @@ fn format_array_v2<A, S, D, F>(view: &ArrayBase<S, D>,
163152
for _ in 0..n {
164153
write!(f, "[")?;
165154
}
166-
} else if !printed_ellipses_h {
155+
} else if !printed_ellipses_h[skip_row_for_axis.unwrap()] {
156+
let ax = skip_row_for_axis.unwrap();
167157
let n = ndim - i - 1;
168158
for _ in 0..n {
169159
write!(f, "]")?;
170160
}
171161
write!(f, ",")?;
172162
write!(f, "\n")?;
173-
for _ in 0..display_mode.h_split_offset().unwrap() {
163+
for _ in 0..(ax + 1) {
174164
write!(f, " ")?;
175165
}
176166
write!(f, "...,\n")?;
177-
printed_ellipses_h = true;
167+
printed_ellipses_h[ax] = true;
178168
}
179169
first = true;
180170
update_index = true;
181171
break;
182172
}
183173
}
184174

185-
if print_row {
175+
if skip_row_for_axis.is_none() {
186176
let mut print_elt = true;
187177
let nth_idx_op = index.slice().iter().last();
188178
match display_mode {
189-
ArrayDisplayMode::VSplit | ArrayDisplayMode::DoubleSplit(_) => {
179+
ArrayDisplayMode::OmitV | ArrayDisplayMode::OmitBoth(_) => {
190180
let nth_idx_val = nth_idx_op.unwrap();
191181
if nth_idx_val >= &limit && nth_idx_val < &(nth_idx_max.unwrap() - &limit) {
192182
print_elt = false;
@@ -371,14 +361,15 @@ impl<'a, A: fmt::Binary, S, D: Dimension> fmt::Binary for ArrayBase<S, D>
371361
mod format_tests {
372362
use super::*;
373363

364+
#[test]
374365
fn test_array_display_mode_from_shape() {
375366
let mode = ArrayDisplayMode::from_shape(&[4, 4], 2);
376367
assert_eq!(mode, ArrayDisplayMode::Full);
377368

378369
let mode = ArrayDisplayMode::from_shape(&[3, 6], 2);
379-
assert_eq!(mode, ArrayDisplayMode::VSplit);
370+
assert_eq!(mode, ArrayDisplayMode::OmitV);
380371

381372
let mode = ArrayDisplayMode::from_shape(&[5, 6, 3], 2);
382-
assert_eq!(mode, ArrayDisplayMode::HSplit(1));
373+
assert_eq!(mode, ArrayDisplayMode::OmitH(vec![1, 0]));
383374
}
384375
}

0 commit comments

Comments
 (0)