@@ -9,55 +9,68 @@ use super::{ArrayBase, Axis, Data, Dimension, Ix, NdProducer};
9
9
use crate :: aliases:: Ix1 ;
10
10
use std:: fmt;
11
11
12
- const PRINT_ELEMENTS_LIMIT : Ix = 3 ;
12
+ /// Default maximum axis length before overflowing with an ellipsis.
13
+ const AXIS_LEN_LIMIT : Ix = 6 ;
13
14
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 > (
16
41
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 ,
19
47
) -> fmt:: Result
20
48
where
21
- F : FnMut ( & A , & mut fmt:: Formatter < ' _ > ) -> fmt:: Result ,
22
- S : Data < Elem = A > ,
49
+ F : FnMut ( & mut fmt:: Formatter < ' _ > , usize ) -> fmt:: Result ,
23
50
{
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
+ } ) ?;
55
59
} 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
+ } ) ?;
60
72
}
73
+ Ok ( ( ) )
61
74
}
62
75
63
76
fn format_array < A , S , D , F > (
@@ -80,54 +93,37 @@ where
80
93
}
81
94
match view. shape ( ) {
82
95
// 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
+ }
91
106
// For n-dimensional arrays, we proceed recursively
92
107
shape => {
93
108
// Cast into a dynamically dimensioned view
94
109
// This is required to be able to use `index_axis`
95
110
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 ( ) ;
101
111
102
112
let blank_lines = "\n " . repeat ( shape. len ( ) - 2 ) ;
103
113
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 ( "]" ) ?;
131
127
}
132
128
}
133
129
Ok ( ( ) )
@@ -143,7 +139,8 @@ where
143
139
S : Data < Elem = A > ,
144
140
{
145
141
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 )
147
144
}
148
145
}
149
146
@@ -156,8 +153,10 @@ where
156
153
S : Data < Elem = A > ,
157
154
{
158
155
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
+
159
159
// Add extra information for Debug
160
- format_array ( self , f, <_ >:: fmt, PRINT_ELEMENTS_LIMIT , 0 ) ?;
161
160
write ! (
162
161
f,
163
162
", shape={:?}, strides={:?}, layout={:?}" ,
@@ -182,7 +181,8 @@ where
182
181
S : Data < Elem = A > ,
183
182
{
184
183
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 )
186
186
}
187
187
}
188
188
@@ -195,7 +195,8 @@ where
195
195
S : Data < Elem = A > ,
196
196
{
197
197
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 )
199
200
}
200
201
}
201
202
/// Format the array using `LowerHex` and apply the formatting parameters used
@@ -207,7 +208,8 @@ where
207
208
S : Data < Elem = A > ,
208
209
{
209
210
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 )
211
213
}
212
214
}
213
215
@@ -220,7 +222,8 @@ where
220
222
S : Data < Elem = A > ,
221
223
{
222
224
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 )
224
227
}
225
228
}
226
229
@@ -264,57 +267,89 @@ mod formatting_with_omit {
264
267
265
268
#[ test]
266
269
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 ) ;
269
272
let actual = format ! ( "{}" , a) ;
270
273
let expected = "[1, 1, 1, ..., 1, 1, 1]" ;
271
274
assert_str_eq ( expected, & actual) ;
272
275
}
273
276
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
+
274
286
#[ test]
275
287
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 ) ;
281
290
let actual = format ! ( "{}" , a) ;
282
291
let expected = "\
283
292
[[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],
284
296
[1, 1, 1, ..., 1, 1, 1],
285
297
[1, 1, 1, ..., 1, 1, 1]]" ;
286
298
assert_str_eq ( expected, & actual) ;
287
299
}
288
300
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
+
289
316
#[ test]
290
317
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 ) ;
296
320
let actual = format ! ( "{}" , a) ;
297
321
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 ],
301
325
...,
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]]" ;
305
346
assert_str_eq ( expected, & actual) ;
306
347
}
307
348
308
349
#[ test]
309
350
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 ) ;
318
353
let actual = format ! ( "{}" , a) ;
319
354
let expected = "\
320
355
[[1, 1, 1, ..., 1, 1, 1],
@@ -327,6 +362,23 @@ mod formatting_with_omit {
327
362
assert_str_eq ( expected, & actual) ;
328
363
}
329
364
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
+
330
382
#[ test]
331
383
fn dim_3_overflow_all ( ) {
332
384
let a = Array3 :: from_shape_fn ( ( 20 , 10 , 7 ) , |( i, j, k) | {
0 commit comments