@@ -9,55 +9,68 @@ use super::{ArrayBase, Axis, Data, Dimension, Ix, NdProducer};
99use crate :: aliases:: Ix1 ;
1010use std:: fmt;
1111
12- const PRINT_ELEMENTS_LIMIT : Ix = 3 ;
12+ /// Default maximum axis length before overflowing with an ellipsis.
13+ const AXIS_LEN_LIMIT : Ix = 6 ;
1314
14- fn format_1d_array < A , S , F > (
15- view : & ArrayBase < S , Ix1 > ,
15+ /// The string used as an ellipsis.
16+ const ELLIPSIS : & str = "..." ;
17+
18+ /// Returns the axis length limit based on whether or not the alternate (`#`)
19+ /// flag was specified on the formatter.
20+ fn axis_len_limit ( f : & mut fmt:: Formatter < ' _ > ) -> usize {
21+ if f. alternate ( ) {
22+ std:: usize:: MAX
23+ } else {
24+ AXIS_LEN_LIMIT
25+ }
26+ }
27+
28+ /// Formats the contents of a list of items, using an ellipsis to indicate when
29+ /// the `length` of the list is greater than `limit`.
30+ ///
31+ /// # Parameters
32+ ///
33+ /// * `f`: The formatter.
34+ /// * `length`: The length of the list.
35+ /// * `limit`: The maximum number of items before overflow.
36+ /// * `separator`: Separator to write between items.
37+ /// * `ellipsis`: Ellipsis for indicating overflow.
38+ /// * `fmt_elem`: A function that formats an element in the list, given the
39+ /// formatter and the index of the item in the list.
40+ fn format_with_overflow < F > (
1641 f : & mut fmt:: Formatter < ' _ > ,
17- mut format : F ,
18- limit : Ix ,
42+ length : usize ,
43+ limit : usize ,
44+ separator : & str ,
45+ ellipsis : & str ,
46+ mut fmt_elem : F ,
1947) -> fmt:: Result
2048where
21- F : FnMut ( & A , & mut fmt:: Formatter < ' _ > ) -> fmt:: Result ,
22- S : Data < Elem = A > ,
49+ F : FnMut ( & mut fmt:: Formatter < ' _ > , usize ) -> fmt:: Result ,
2350{
24- let to_be_printed = to_be_printed ( view. len ( ) , limit) ;
25-
26- let n_to_be_printed = to_be_printed. len ( ) ;
27-
28- write ! ( f, "[" ) ?;
29- for ( j, index) in to_be_printed. into_iter ( ) . enumerate ( ) {
30- match index {
31- PrintableCell :: ElementIndex ( i) => {
32- format ( & view[ i] , f) ?;
33- if j != n_to_be_printed - 1 {
34- write ! ( f, ", " ) ?;
35- }
36- }
37- PrintableCell :: Ellipses => write ! ( f, "..., " ) ?,
38- }
39- }
40- write ! ( f, "]" ) ?;
41- Ok ( ( ) )
42- }
43-
44- enum PrintableCell {
45- ElementIndex ( usize ) ,
46- Ellipses ,
47- }
48-
49- // Returns what indexes should be printed for a certain axis.
50- // If the axis is longer than 2 * limit, a `Ellipses` is inserted
51- // where indexes are being omitted.
52- fn to_be_printed ( length : usize , limit : usize ) -> Vec < PrintableCell > {
53- if length <= 2 * limit {
54- ( 0 ..length) . map ( PrintableCell :: ElementIndex ) . collect ( )
51+ if length == 0 {
52+ // no-op
53+ } else if length <= limit {
54+ fmt_elem ( f, 0 ) ?;
55+ ( 1 ..length) . try_for_each ( |i| {
56+ f. write_str ( separator) ?;
57+ fmt_elem ( f, i)
58+ } ) ?;
5559 } else {
56- let mut v: Vec < PrintableCell > = ( 0 ..limit) . map ( PrintableCell :: ElementIndex ) . collect ( ) ;
57- v. push ( PrintableCell :: Ellipses ) ;
58- v. extend ( ( length - limit..length) . map ( PrintableCell :: ElementIndex ) ) ;
59- v
60+ let edge = limit / 2 ;
61+ fmt_elem ( f, 0 ) ?;
62+ ( 1 ..edge) . try_for_each ( |i| {
63+ f. write_str ( separator) ?;
64+ fmt_elem ( f, i)
65+ } ) ?;
66+ f. write_str ( separator) ?;
67+ f. write_str ( ellipsis) ?;
68+ ( length - edge..length) . try_for_each ( |i| {
69+ f. write_str ( separator) ?;
70+ fmt_elem ( f, i)
71+ } ) ?;
6072 }
73+ Ok ( ( ) )
6174}
6275
6376fn format_array < A , S , D , F > (
@@ -80,54 +93,37 @@ where
8093 }
8194 match view. shape ( ) {
8295 // If it's 0 dimensional, we just print out the scalar
83- [ ] => format ( view. iter ( ) . next ( ) . unwrap ( ) , f) ?,
84- // We delegate 1-dimensional arrays to a specialized function
85- [ _] => format_1d_array (
86- & view. view ( ) . into_dimensionality :: < Ix1 > ( ) . unwrap ( ) ,
87- f,
88- format,
89- limit,
90- ) ?,
96+ & [ ] => format ( view. iter ( ) . next ( ) . unwrap ( ) , f) ?,
97+ // We handle 1-D arrays as a special case
98+ & [ len] => {
99+ let view = view. view ( ) . into_dimensionality :: < Ix1 > ( ) . unwrap ( ) ;
100+ f. write_str ( "[" ) ?;
101+ format_with_overflow ( f, len, limit, ", " , ELLIPSIS , |f, index| {
102+ format ( & view[ index] , f)
103+ } ) ?;
104+ f. write_str ( "]" ) ?;
105+ }
91106 // For n-dimensional arrays, we proceed recursively
92107 shape => {
93108 // Cast into a dynamically dimensioned view
94109 // This is required to be able to use `index_axis`
95110 let view = view. view ( ) . into_dyn ( ) ;
96- // We start by checking what indexes from the first axis should be printed
97- // We put a `None` in the middle if we are omitting elements
98- let to_be_printed = to_be_printed ( shape[ 0 ] , limit) ;
99-
100- let n_to_be_printed = to_be_printed. len ( ) ;
101111
102112 let blank_lines = "\n " . repeat ( shape. len ( ) - 2 ) ;
103113 let indent = " " . repeat ( depth + 1 ) ;
104-
105- write ! ( f, "[" ) ?;
106- for ( j, index) in to_be_printed. into_iter ( ) . enumerate ( ) {
107- match index {
108- PrintableCell :: ElementIndex ( i) => {
109- // Indent all but the first line.
110- if j != 0 {
111- write ! ( f, "{}" , indent) ?;
112- }
113- // Proceed recursively with the (n-1)-dimensional slice
114- format_array (
115- & view. index_axis ( Axis ( 0 ) , i) ,
116- f,
117- format. clone ( ) ,
118- limit,
119- depth + 1 ,
120- ) ?;
121- // We need to add a separator after each slice,
122- // apart from the last one
123- if j != n_to_be_printed - 1 {
124- write ! ( f, ",\n {}" , blank_lines) ?
125- }
126- }
127- PrintableCell :: Ellipses => write ! ( f, "{}...,\n {}" , indent, blank_lines) ?,
128- }
129- }
130- write ! ( f, "]" ) ?;
114+ let separator = format ! ( ",\n {}{}" , blank_lines, indent) ;
115+
116+ f. write_str ( "[" ) ?;
117+ format_with_overflow ( f, shape[ 0 ] , limit, & separator, ELLIPSIS , |f, index| {
118+ format_array (
119+ & view. index_axis ( Axis ( 0 ) , index) ,
120+ f,
121+ format. clone ( ) ,
122+ limit,
123+ depth + 1 ,
124+ )
125+ } ) ?;
126+ f. write_str ( "]" ) ?;
131127 }
132128 }
133129 Ok ( ( ) )
@@ -143,7 +139,8 @@ where
143139 S : Data < Elem = A > ,
144140{
145141 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
146- format_array ( self , f, <_ >:: fmt, PRINT_ELEMENTS_LIMIT , 0 )
142+ let limit = axis_len_limit ( f) ;
143+ format_array ( self , f, <_ >:: fmt, limit, 0 )
147144 }
148145}
149146
@@ -156,8 +153,10 @@ where
156153 S : Data < Elem = A > ,
157154{
158155 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
156+ let limit = axis_len_limit ( f) ;
157+ format_array ( self , f, <_ >:: fmt, limit, 0 ) ?;
158+
159159 // Add extra information for Debug
160- format_array ( self , f, <_ >:: fmt, PRINT_ELEMENTS_LIMIT , 0 ) ?;
161160 write ! (
162161 f,
163162 ", shape={:?}, strides={:?}, layout={:?}" ,
@@ -182,7 +181,8 @@ where
182181 S : Data < Elem = A > ,
183182{
184183 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
185- format_array ( self , f, <_ >:: fmt, PRINT_ELEMENTS_LIMIT , 0 )
184+ let limit = axis_len_limit ( f) ;
185+ format_array ( self , f, <_ >:: fmt, limit, 0 )
186186 }
187187}
188188
@@ -195,7 +195,8 @@ where
195195 S : Data < Elem = A > ,
196196{
197197 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
198- format_array ( self , f, <_ >:: fmt, PRINT_ELEMENTS_LIMIT , 0 )
198+ let limit = axis_len_limit ( f) ;
199+ format_array ( self , f, <_ >:: fmt, limit, 0 )
199200 }
200201}
201202/// Format the array using `LowerHex` and apply the formatting parameters used
@@ -207,7 +208,8 @@ where
207208 S : Data < Elem = A > ,
208209{
209210 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
210- format_array ( self , f, <_ >:: fmt, PRINT_ELEMENTS_LIMIT , 0 )
211+ let limit = axis_len_limit ( f) ;
212+ format_array ( self , f, <_ >:: fmt, limit, 0 )
211213 }
212214}
213215
@@ -220,7 +222,8 @@ where
220222 S : Data < Elem = A > ,
221223{
222224 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
223- format_array ( self , f, <_ >:: fmt, PRINT_ELEMENTS_LIMIT , 0 )
225+ let limit = axis_len_limit ( f) ;
226+ format_array ( self , f, <_ >:: fmt, limit, 0 )
224227 }
225228}
226229
@@ -264,57 +267,89 @@ mod formatting_with_omit {
264267
265268 #[ test]
266269 fn dim_1 ( ) {
267- let overflow: usize = 5 ;
268- let a = Array1 :: from_elem ( ( PRINT_ELEMENTS_LIMIT * 2 + overflow, ) , 1 ) ;
270+ let overflow: usize = 2 ;
271+ let a = Array1 :: from_elem ( AXIS_LEN_LIMIT + overflow, 1 ) ;
269272 let actual = format ! ( "{}" , a) ;
270273 let expected = "[1, 1, 1, ..., 1, 1, 1]" ;
271274 assert_str_eq ( expected, & actual) ;
272275 }
273276
277+ #[ test]
278+ fn dim_1_alternate ( ) {
279+ let overflow: usize = 2 ;
280+ let a = Array1 :: from_elem ( AXIS_LEN_LIMIT + overflow, 1 ) ;
281+ let actual = format ! ( "{:#}" , a) ;
282+ let expected = "[1, 1, 1, 1, 1, 1, 1, 1]" ;
283+ assert_str_eq ( expected, & actual) ;
284+ }
285+
274286 #[ test]
275287 fn dim_2_last_axis_overflow ( ) {
276- let overflow: usize = 3 ;
277- let a = Array2 :: from_elem (
278- ( PRINT_ELEMENTS_LIMIT , PRINT_ELEMENTS_LIMIT * 2 + overflow) ,
279- 1 ,
280- ) ;
288+ let overflow: usize = 2 ;
289+ let a = Array2 :: from_elem ( ( AXIS_LEN_LIMIT , AXIS_LEN_LIMIT + overflow) , 1 ) ;
281290 let actual = format ! ( "{}" , a) ;
282291 let expected = "\
283292 [[1, 1, 1, ..., 1, 1, 1],
293+ [1, 1, 1, ..., 1, 1, 1],
294+ [1, 1, 1, ..., 1, 1, 1],
295+ [1, 1, 1, ..., 1, 1, 1],
284296 [1, 1, 1, ..., 1, 1, 1],
285297 [1, 1, 1, ..., 1, 1, 1]]" ;
286298 assert_str_eq ( expected, & actual) ;
287299 }
288300
301+ #[ test]
302+ fn dim_2_last_axis_overflow_alternate ( ) {
303+ let overflow: usize = 2 ;
304+ let a = Array2 :: from_elem ( ( AXIS_LEN_LIMIT , AXIS_LEN_LIMIT + overflow) , 1 ) ;
305+ let actual = format ! ( "{:#}" , a) ;
306+ let expected = "\
307+ [[1, 1, 1, 1, 1, 1, 1, 1],
308+ [1, 1, 1, 1, 1, 1, 1, 1],
309+ [1, 1, 1, 1, 1, 1, 1, 1],
310+ [1, 1, 1, 1, 1, 1, 1, 1],
311+ [1, 1, 1, 1, 1, 1, 1, 1],
312+ [1, 1, 1, 1, 1, 1, 1, 1]]" ;
313+ assert_str_eq ( expected, & actual) ;
314+ }
315+
289316 #[ test]
290317 fn dim_2_non_last_axis_overflow ( ) {
291- let overflow: usize = 5 ;
292- let a = Array2 :: from_elem (
293- ( PRINT_ELEMENTS_LIMIT * 2 + overflow, PRINT_ELEMENTS_LIMIT ) ,
294- 1 ,
295- ) ;
318+ let overflow: usize = 2 ;
319+ let a = Array2 :: from_elem ( ( AXIS_LEN_LIMIT + overflow, AXIS_LEN_LIMIT ) , 1 ) ;
296320 let actual = format ! ( "{}" , a) ;
297321 let expected = "\
298- [[1, 1, 1],
299- [1, 1, 1],
300- [1, 1, 1],
322+ [[1, 1, 1, 1, 1, 1 ],
323+ [1, 1, 1, 1, 1, 1 ],
324+ [1, 1, 1, 1, 1, 1 ],
301325 ...,
302- [1, 1, 1],
303- [1, 1, 1],
304- [1, 1, 1]]" ;
326+ [1, 1, 1, 1, 1, 1],
327+ [1, 1, 1, 1, 1, 1],
328+ [1, 1, 1, 1, 1, 1]]" ;
329+ assert_str_eq ( expected, & actual) ;
330+ }
331+
332+ #[ test]
333+ fn dim_2_non_last_axis_overflow_alternate ( ) {
334+ let overflow: usize = 2 ;
335+ let a = Array2 :: from_elem ( ( AXIS_LEN_LIMIT + overflow, AXIS_LEN_LIMIT ) , 1 ) ;
336+ let actual = format ! ( "{:#}" , a) ;
337+ let expected = "\
338+ [[1, 1, 1, 1, 1, 1],
339+ [1, 1, 1, 1, 1, 1],
340+ [1, 1, 1, 1, 1, 1],
341+ [1, 1, 1, 1, 1, 1],
342+ [1, 1, 1, 1, 1, 1],
343+ [1, 1, 1, 1, 1, 1],
344+ [1, 1, 1, 1, 1, 1],
345+ [1, 1, 1, 1, 1, 1]]" ;
305346 assert_str_eq ( expected, & actual) ;
306347 }
307348
308349 #[ test]
309350 fn dim_2_multi_directional_overflow ( ) {
310- let overflow: usize = 5 ;
311- let a = Array2 :: from_elem (
312- (
313- PRINT_ELEMENTS_LIMIT * 2 + overflow,
314- PRINT_ELEMENTS_LIMIT * 2 + overflow,
315- ) ,
316- 1 ,
317- ) ;
351+ let overflow: usize = 2 ;
352+ let a = Array2 :: from_elem ( ( AXIS_LEN_LIMIT + overflow, AXIS_LEN_LIMIT + overflow) , 1 ) ;
318353 let actual = format ! ( "{}" , a) ;
319354 let expected = "\
320355 [[1, 1, 1, ..., 1, 1, 1],
@@ -327,6 +362,23 @@ mod formatting_with_omit {
327362 assert_str_eq ( expected, & actual) ;
328363 }
329364
365+ #[ test]
366+ fn dim_2_multi_directional_overflow_alternate ( ) {
367+ let overflow: usize = 2 ;
368+ let a = Array2 :: from_elem ( ( AXIS_LEN_LIMIT + overflow, AXIS_LEN_LIMIT + overflow) , 1 ) ;
369+ let actual = format ! ( "{:#}" , a) ;
370+ let expected = "\
371+ [[1, 1, 1, 1, 1, 1, 1, 1],
372+ [1, 1, 1, 1, 1, 1, 1, 1],
373+ [1, 1, 1, 1, 1, 1, 1, 1],
374+ [1, 1, 1, 1, 1, 1, 1, 1],
375+ [1, 1, 1, 1, 1, 1, 1, 1],
376+ [1, 1, 1, 1, 1, 1, 1, 1],
377+ [1, 1, 1, 1, 1, 1, 1, 1],
378+ [1, 1, 1, 1, 1, 1, 1, 1]]" ;
379+ assert_str_eq ( expected, & actual) ;
380+ }
381+
330382 #[ test]
331383 fn dim_3_overflow_all ( ) {
332384 let a = Array3 :: from_shape_fn ( ( 20 , 10 , 7 ) , |( i, j, k) | {
0 commit comments