Coverage Report

Created: 2026-03-23 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ndarray-0.17.2/src/arrayformat.rs
Line
Count
Source
1
// Copyright 2014-2016 bluss and ndarray developers.
2
//
3
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6
// option. This file may not be copied, modified, or distributed
7
// except according to those terms.
8
use super::{ArrayBase, ArrayView, Axis, Data, Dimension, NdProducer};
9
use crate::{
10
    aliases::{Ix1, IxDyn},
11
    ArrayRef,
12
};
13
use alloc::format;
14
use std::fmt;
15
16
/// Default threshold, below this element count, we don't ellipsize
17
const ARRAY_MANY_ELEMENT_LIMIT: usize = 500;
18
/// Limit of element count for non-last axes before overflowing with an ellipsis.
19
const AXIS_LIMIT_STACKED: usize = 6;
20
/// Limit for next to last axis (printed as column)
21
/// An odd number because one element uses the same space as the ellipsis.
22
const AXIS_LIMIT_COL: usize = 11;
23
/// Limit for last axis (printed as row)
24
/// An odd number because one element uses approximately the space of the ellipsis.
25
const AXIS_LIMIT_ROW: usize = 11;
26
27
#[cfg(test)]
28
// Test value to use for size of overflowing 2D arrays
29
const AXIS_2D_OVERFLOW_LIMIT: usize = 22;
30
31
/// The string used as an ellipsis.
32
const ELLIPSIS: &str = "...";
33
34
#[derive(Clone, Debug)]
35
struct FormatOptions
36
{
37
    axis_collapse_limit: usize,
38
    axis_collapse_limit_next_last: usize,
39
    axis_collapse_limit_last: usize,
40
}
41
42
impl FormatOptions
43
{
44
0
    pub(crate) fn default_for_array(nelem: usize, no_limit: bool) -> Self
45
    {
46
0
        let default = Self {
47
0
            axis_collapse_limit: AXIS_LIMIT_STACKED,
48
0
            axis_collapse_limit_next_last: AXIS_LIMIT_COL,
49
0
            axis_collapse_limit_last: AXIS_LIMIT_ROW,
50
0
        };
51
0
        default.set_no_limit(no_limit || nelem < ARRAY_MANY_ELEMENT_LIMIT)
52
0
    }
53
54
0
    fn set_no_limit(mut self, no_limit: bool) -> Self
55
    {
56
0
        if no_limit {
57
0
            self.axis_collapse_limit = usize::MAX;
58
0
            self.axis_collapse_limit_next_last = usize::MAX;
59
0
            self.axis_collapse_limit_last = usize::MAX;
60
0
        }
61
0
        self
62
0
    }
63
64
    /// Axis length collapse limit before ellipsizing, where `axis_rindex` is
65
    /// the index of the axis from the back.
66
0
    pub(crate) fn collapse_limit(&self, axis_rindex: usize) -> usize
67
    {
68
0
        match axis_rindex {
69
0
            0 => self.axis_collapse_limit_last,
70
0
            1 => self.axis_collapse_limit_next_last,
71
0
            _ => self.axis_collapse_limit,
72
        }
73
0
    }
74
}
75
76
/// Formats the contents of a list of items, using an ellipsis to indicate when
77
/// the `length` of the list is greater than `limit`.
78
///
79
/// # Parameters
80
///
81
/// * `f`: The formatter.
82
/// * `length`: The length of the list.
83
/// * `limit`: The maximum number of items before overflow.
84
/// * `separator`: Separator to write between items.
85
/// * `ellipsis`: Ellipsis for indicating overflow.
86
/// * `fmt_elem`: A function that formats an element in the list, given the
87
///   formatter and the index of the item in the list.
88
0
fn format_with_overflow(
89
0
    f: &mut fmt::Formatter<'_>, length: usize, limit: usize, separator: &str, ellipsis: &str,
90
0
    fmt_elem: &mut dyn FnMut(&mut fmt::Formatter, usize) -> fmt::Result,
91
0
) -> fmt::Result
92
{
93
0
    if length == 0 {
94
0
        // no-op
95
0
    } else if length <= limit {
96
0
        fmt_elem(f, 0)?;
97
0
        for i in 1..length {
98
0
            f.write_str(separator)?;
99
0
            fmt_elem(f, i)?
100
        }
101
    } else {
102
0
        let edge = limit / 2;
103
0
        fmt_elem(f, 0)?;
104
0
        for i in 1..edge {
105
0
            f.write_str(separator)?;
106
0
            fmt_elem(f, i)?;
107
        }
108
0
        f.write_str(separator)?;
109
0
        f.write_str(ellipsis)?;
110
0
        for i in length - edge..length {
111
0
            f.write_str(separator)?;
112
0
            fmt_elem(f, i)?
113
        }
114
    }
115
0
    Ok(())
116
0
}
117
118
0
fn format_array<A, D, F>(
119
0
    array: &ArrayRef<A, D>, f: &mut fmt::Formatter<'_>, format: F, fmt_opt: &FormatOptions,
120
0
) -> fmt::Result
121
0
where
122
0
    F: FnMut(&A, &mut fmt::Formatter<'_>) -> fmt::Result + Clone,
123
0
    D: Dimension,
124
{
125
    // Cast into a dynamically dimensioned view
126
    // This is required to be able to use `index_axis` for the recursive case
127
0
    format_array_inner(array.view().into_dyn(), f, format, fmt_opt, 0, array.ndim())
128
0
}
Unexecuted instantiation: ndarray::arrayformat::format_array::<f64, ndarray::dimension::dim::Dim<[usize; 1]>, <f64 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array::<f32, ndarray::dimension::dim::Dim<[usize; 1]>, <f32 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array::<i32, ndarray::dimension::dim::Dim<[usize; 1]>, <i32 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array::<i16, ndarray::dimension::dim::Dim<[usize; 1]>, <i16 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array::<i64, ndarray::dimension::dim::Dim<[usize; 1]>, <i64 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array::<_, _, _>
129
130
0
fn format_array_inner<A, F>(
131
0
    view: ArrayView<A, IxDyn>, f: &mut fmt::Formatter<'_>, mut format: F, fmt_opt: &FormatOptions, depth: usize,
132
0
    full_ndim: usize,
133
0
) -> fmt::Result
134
0
where
135
0
    F: FnMut(&A, &mut fmt::Formatter<'_>) -> fmt::Result + Clone,
136
{
137
    // If any of the axes has 0 length, we return the same empty array representation
138
    // e.g. [[]] for 2-d arrays
139
0
    if view.is_empty() {
140
0
        write!(f, "{}{}", "[".repeat(view.ndim()), "]".repeat(view.ndim()))?;
141
0
        return Ok(());
142
0
    }
143
0
    match view.shape() {
144
        // If it's 0 dimensional, we just print out the scalar
145
0
        &[] => format(&view[[]], f)?,
146
        // We handle 1-D arrays as a special case
147
0
        &[len] => {
148
0
            let view = view.view().into_dimensionality::<Ix1>().unwrap();
149
0
            f.write_str("[")?;
150
0
            format_with_overflow(f, len, fmt_opt.collapse_limit(0), ", ", ELLIPSIS, &mut |f, index| {
151
0
                format(&view[index], f)
152
0
            })?;
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<f64, <f64 as core::fmt::Debug>::fmt>::{closure#0}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<f32, <f32 as core::fmt::Debug>::fmt>::{closure#0}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<i32, <i32 as core::fmt::Debug>::fmt>::{closure#0}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<i16, <i16 as core::fmt::Debug>::fmt>::{closure#0}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<i64, <i64 as core::fmt::Debug>::fmt>::{closure#0}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<_, _>::{closure#0}
153
0
            f.write_str("]")?;
154
        }
155
        // For n-dimensional arrays, we proceed recursively
156
0
        shape => {
157
0
            let blank_lines = "\n".repeat(shape.len() - 2);
158
0
            let indent = " ".repeat(depth + 1);
159
0
            let separator = format!(",\n{}{}", blank_lines, indent);
160
161
0
            f.write_str("[")?;
162
0
            let limit = fmt_opt.collapse_limit(full_ndim - depth - 1);
163
0
            format_with_overflow(f, shape[0], limit, &separator, ELLIPSIS, &mut |f, index| {
164
0
                format_array_inner(view.index_axis(Axis(0), index), f, format.clone(), fmt_opt, depth + 1, full_ndim)
165
0
            })?;
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<f64, <f64 as core::fmt::Debug>::fmt>::{closure#1}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<f32, <f32 as core::fmt::Debug>::fmt>::{closure#1}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<i32, <i32 as core::fmt::Debug>::fmt>::{closure#1}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<i16, <i16 as core::fmt::Debug>::fmt>::{closure#1}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<i64, <i64 as core::fmt::Debug>::fmt>::{closure#1}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<_, _>::{closure#1}
166
0
            f.write_str("]")?;
167
        }
168
    }
169
0
    Ok(())
170
0
}
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<f64, <f64 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<f32, <f32 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<i32, <i32 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<i16, <i16 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<i64, <i64 as core::fmt::Debug>::fmt>
Unexecuted instantiation: ndarray::arrayformat::format_array_inner::<_, _>
171
172
// NOTE: We can impl other fmt traits here
173
/// Format the array using `Display` and apply the formatting parameters used
174
/// to each element.
175
///
176
/// The array is shown in multiline style.
177
impl<A: fmt::Display, S, D: Dimension> fmt::Display for ArrayBase<S, D>
178
where S: Data<Elem = A>
179
{
180
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
181
    {
182
0
        (**self).fmt(f)
183
0
    }
184
}
185
186
/// Format the array reference using `Display` and apply the formatting parameters
187
/// used to each element.
188
///
189
/// The array is shown in multiline style.
190
impl<A: fmt::Display, D: Dimension> fmt::Display for ArrayRef<A, D>
191
{
192
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
193
    {
194
0
        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
195
0
        format_array(self, f, <_>::fmt, &fmt_opt)
196
0
    }
197
}
198
199
/// Format the array using `Debug` and apply the formatting parameters used
200
/// to each element.
201
///
202
/// The array is shown in multiline style.
203
impl<A: fmt::Debug, S, D: Dimension> fmt::Debug for ArrayBase<S, D>
204
where S: Data<Elem = A>
205
{
206
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
207
    {
208
0
        (**self).fmt(f)
209
0
    }
Unexecuted instantiation: <ndarray::ArrayBase<ndarray::data_repr::OwnedRepr<f64>, ndarray::dimension::dim::Dim<[usize; 1]>, f64> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayBase<ndarray::data_repr::OwnedRepr<f32>, ndarray::dimension::dim::Dim<[usize; 1]>, f32> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayBase<ndarray::data_repr::OwnedRepr<i32>, ndarray::dimension::dim::Dim<[usize; 1]>, i32> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayBase<ndarray::data_repr::OwnedRepr<i16>, ndarray::dimension::dim::Dim<[usize; 1]>, i16> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayBase<ndarray::data_repr::OwnedRepr<i64>, ndarray::dimension::dim::Dim<[usize; 1]>, i64> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayBase<_, _, _> as core::fmt::Debug>::fmt
210
}
211
212
/// Format the array reference using `Debug` and apply the formatting parameters used
213
/// to each element.
214
///
215
/// The array is shown in multiline style.
216
impl<A: fmt::Debug, D: Dimension> fmt::Debug for ArrayRef<A, D>
217
{
218
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
219
    {
220
0
        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
221
0
        format_array(self, f, <_>::fmt, &fmt_opt)?;
222
223
        // Add extra information for Debug
224
0
        write!(
225
0
            f,
226
            ", shape={:?}, strides={:?}, layout={:?}",
227
0
            self.shape(),
228
0
            self.strides(),
229
0
            self.view().layout(),
230
0
        )?;
231
0
        match D::NDIM {
232
0
            Some(ndim) => write!(f, ", const ndim={}", ndim)?,
233
0
            None => write!(f, ", dynamic ndim={}", self.ndim())?,
234
        }
235
0
        Ok(())
236
0
    }
Unexecuted instantiation: <ndarray::ArrayRef<f64, ndarray::dimension::dim::Dim<[usize; 1]>> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayRef<f32, ndarray::dimension::dim::Dim<[usize; 1]>> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayRef<i32, ndarray::dimension::dim::Dim<[usize; 1]>> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayRef<i16, ndarray::dimension::dim::Dim<[usize; 1]>> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayRef<i64, ndarray::dimension::dim::Dim<[usize; 1]>> as core::fmt::Debug>::fmt
Unexecuted instantiation: <ndarray::ArrayRef<_, _> as core::fmt::Debug>::fmt
237
}
238
239
/// Format the array using `LowerExp` and apply the formatting parameters used
240
/// to each element.
241
///
242
/// The array is shown in multiline style.
243
impl<A: fmt::LowerExp, S, D: Dimension> fmt::LowerExp for ArrayBase<S, D>
244
where S: Data<Elem = A>
245
{
246
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
247
    {
248
0
        (**self).fmt(f)
249
0
    }
250
}
251
252
/// Format the array reference using `LowerExp` and apply the formatting parameters used
253
/// to each element.
254
///
255
/// The array is shown in multiline style.
256
impl<A: fmt::LowerExp, D: Dimension> fmt::LowerExp for ArrayRef<A, D>
257
{
258
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
259
    {
260
0
        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
261
0
        format_array(self, f, <_>::fmt, &fmt_opt)
262
0
    }
263
}
264
265
/// Format the array using `UpperExp` and apply the formatting parameters used
266
/// to each element.
267
///
268
/// The array is shown in multiline style.
269
impl<A: fmt::UpperExp, S, D: Dimension> fmt::UpperExp for ArrayBase<S, D>
270
where S: Data<Elem = A>
271
{
272
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
273
    {
274
0
        (**self).fmt(f)
275
0
    }
276
}
277
278
/// Format the array using `UpperExp` and apply the formatting parameters used
279
/// to each element.
280
///
281
/// The array is shown in multiline style.
282
impl<A: fmt::UpperExp, D: Dimension> fmt::UpperExp for ArrayRef<A, D>
283
{
284
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
285
    {
286
0
        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
287
0
        format_array(self, f, <_>::fmt, &fmt_opt)
288
0
    }
289
}
290
291
/// Format the array using `LowerHex` and apply the formatting parameters used
292
/// to each element.
293
///
294
/// The array is shown in multiline style.
295
impl<A: fmt::LowerHex, S, D: Dimension> fmt::LowerHex for ArrayBase<S, D>
296
where S: Data<Elem = A>
297
{
298
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
299
    {
300
0
        (**self).fmt(f)
301
0
    }
302
}
303
304
/// Format the array using `LowerHex` and apply the formatting parameters used
305
/// to each element.
306
///
307
/// The array is shown in multiline style.
308
impl<A: fmt::LowerHex, D: Dimension> fmt::LowerHex for ArrayRef<A, D>
309
{
310
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
311
    {
312
0
        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
313
0
        format_array(self, f, <_>::fmt, &fmt_opt)
314
0
    }
315
}
316
317
/// Format the array using `Binary` and apply the formatting parameters used
318
/// to each element.
319
///
320
/// The array is shown in multiline style.
321
impl<A: fmt::Binary, S, D: Dimension> fmt::Binary for ArrayBase<S, D>
322
where S: Data<Elem = A>
323
{
324
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
325
    {
326
0
        (**self).fmt(f)
327
0
    }
328
}
329
330
/// Format the array using `Binary` and apply the formatting parameters used
331
/// to each element.
332
///
333
/// The array is shown in multiline style.
334
impl<A: fmt::Binary, D: Dimension> fmt::Binary for ArrayRef<A, D>
335
{
336
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
337
    {
338
0
        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
339
0
        format_array(self, f, <_>::fmt, &fmt_opt)
340
0
    }
341
}
342
343
#[cfg(test)]
344
mod formatting_with_omit
345
{
346
    #[cfg(not(feature = "std"))]
347
    use alloc::string::String;
348
    #[cfg(not(feature = "std"))]
349
    use alloc::vec::Vec;
350
    use itertools::Itertools;
351
352
    use super::*;
353
    use crate::prelude::*;
354
355
    fn assert_str_eq(expected: &str, actual: &str)
356
    {
357
        // use assert to avoid printing the strings twice on failure
358
        assert!(
359
            expected == actual,
360
            "formatting assertion failed\nexpected:\n{}\nactual:\n{}\n",
361
            expected,
362
            actual,
363
        );
364
    }
365
366
    fn ellipsize(limit: usize, sep: &str, elements: impl IntoIterator<Item = impl fmt::Display>) -> String
367
    {
368
        let elements = elements.into_iter().collect::<Vec<_>>();
369
        let edge = limit / 2;
370
        if elements.len() <= limit {
371
            format!("{}", elements.iter().format(sep))
372
        } else {
373
            format!(
374
                "{}{}{}{}{}",
375
                elements[..edge].iter().format(sep),
376
                sep,
377
                ELLIPSIS,
378
                sep,
379
                elements[elements.len() - edge..].iter().format(sep)
380
            )
381
        }
382
    }
383
384
    #[test]
385
    fn empty_arrays()
386
    {
387
        let a: Array2<u32> = arr2(&[[], []]);
388
        let actual = format!("{}", a);
389
        let expected = "[[]]";
390
        assert_str_eq(expected, &actual);
391
    }
392
393
    #[test]
394
    fn zero_length_axes()
395
    {
396
        let a = Array3::<f32>::zeros((3, 0, 4));
397
        let actual = format!("{}", a);
398
        let expected = "[[[]]]";
399
        assert_str_eq(expected, &actual);
400
    }
401
402
    #[test]
403
    fn dim_0()
404
    {
405
        let element = 12;
406
        let a = arr0(element);
407
        let actual = format!("{}", a);
408
        let expected = "12";
409
        assert_str_eq(expected, &actual);
410
    }
411
412
    #[test]
413
    fn dim_1()
414
    {
415
        let overflow: usize = 2;
416
        let a = Array1::from_elem(ARRAY_MANY_ELEMENT_LIMIT + overflow, 1);
417
        let actual = format!("{}", a);
418
        let expected = format!("[{}]", ellipsize(AXIS_LIMIT_ROW, ", ", a.iter()));
419
        assert_str_eq(&expected, &actual);
420
    }
421
422
    #[test]
423
    fn dim_1_alternate()
424
    {
425
        let overflow: usize = 2;
426
        let a = Array1::from_elem(ARRAY_MANY_ELEMENT_LIMIT + overflow, 1);
427
        let actual = format!("{:#}", a);
428
        let expected = format!("[{}]", a.iter().format(", "));
429
        assert_str_eq(&expected, &actual);
430
    }
431
432
    #[test]
433
    fn dim_2_last_axis_overflow()
434
    {
435
        let overflow: usize = 2;
436
        let a = Array2::from_elem((AXIS_2D_OVERFLOW_LIMIT, AXIS_2D_OVERFLOW_LIMIT + overflow), 1);
437
        let actual = format!("{}", a);
438
        let expected = "\
439
[[1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
440
 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
441
 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
442
 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
443
 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
444
 ...,
445
 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
446
 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
447
 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
448
 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
449
 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1]]";
450
        assert_str_eq(expected, &actual);
451
    }
452
453
    #[test]
454
    fn dim_2_non_last_axis_overflow()
455
    {
456
        let a = Array2::from_elem((ARRAY_MANY_ELEMENT_LIMIT / 10, 10), 1);
457
        let actual = format!("{}", a);
458
        let row = format!("{}", a.row(0));
459
        let expected = format!(
460
            "[{}]",
461
            ellipsize(AXIS_LIMIT_COL, ",\n ", (0..a.nrows()).map(|_| &row))
462
        );
463
        assert_str_eq(&expected, &actual);
464
    }
465
466
    #[test]
467
    fn dim_2_non_last_axis_overflow_alternate()
468
    {
469
        let a = Array2::from_elem((AXIS_LIMIT_COL * 4, 6), 1);
470
        let actual = format!("{:#}", a);
471
        let row = format!("{}", a.row(0));
472
        let expected = format!("[{}]", (0..a.nrows()).map(|_| &row).format(",\n "));
473
        assert_str_eq(&expected, &actual);
474
    }
475
476
    #[test]
477
    fn dim_2_multi_directional_overflow()
478
    {
479
        let overflow: usize = 2;
480
        let a = Array2::from_elem((AXIS_2D_OVERFLOW_LIMIT + overflow, AXIS_2D_OVERFLOW_LIMIT + overflow), 1);
481
        let actual = format!("{}", a);
482
        let row = format!("[{}]", ellipsize(AXIS_LIMIT_ROW, ", ", a.row(0)));
483
        let expected = format!(
484
            "[{}]",
485
            ellipsize(AXIS_LIMIT_COL, ",\n ", (0..a.nrows()).map(|_| &row))
486
        );
487
        assert_str_eq(&expected, &actual);
488
    }
489
490
    #[test]
491
    fn dim_2_multi_directional_overflow_alternate()
492
    {
493
        let overflow: usize = 2;
494
        let a = Array2::from_elem((AXIS_2D_OVERFLOW_LIMIT + overflow, AXIS_2D_OVERFLOW_LIMIT + overflow), 1);
495
        let actual = format!("{:#}", a);
496
        let row = format!("{}", a.row(0));
497
        let expected = format!("[{}]", (0..a.nrows()).map(|_| &row).format(",\n "));
498
        assert_str_eq(&expected, &actual);
499
    }
500
501
    #[test]
502
    fn dim_3_overflow_most()
503
    {
504
        let a = Array3::from_shape_fn((AXIS_LIMIT_STACKED + 1, AXIS_LIMIT_COL, AXIS_LIMIT_ROW + 1), |(i, j, k)| {
505
            1000. + (100. * ((i as f64).sqrt() + (j as f64).sin() + k as f64)).round() / 100.
506
        });
507
        let actual = format!("{:6.1}", a);
508
        let expected = "\
509
[[[1000.0, 1001.0, 1002.0, 1003.0, 1004.0, ..., 1007.0, 1008.0, 1009.0, 1010.0, 1011.0],
510
  [1000.8, 1001.8, 1002.8, 1003.8, 1004.8, ..., 1007.8, 1008.8, 1009.8, 1010.8, 1011.8],
511
  [1000.9, 1001.9, 1002.9, 1003.9, 1004.9, ..., 1007.9, 1008.9, 1009.9, 1010.9, 1011.9],
512
  [1000.1, 1001.1, 1002.1, 1003.1, 1004.1, ..., 1007.1, 1008.1, 1009.1, 1010.1, 1011.1],
513
  [ 999.2, 1000.2, 1001.2, 1002.2, 1003.2, ..., 1006.2, 1007.2, 1008.2, 1009.2, 1010.2],
514
  [ 999.0, 1000.0, 1001.0, 1002.0, 1003.0, ..., 1006.0, 1007.0, 1008.0, 1009.0, 1010.0],
515
  [ 999.7, 1000.7, 1001.7, 1002.7, 1003.7, ..., 1006.7, 1007.7, 1008.7, 1009.7, 1010.7],
516
  [1000.7, 1001.7, 1002.7, 1003.7, 1004.7, ..., 1007.7, 1008.7, 1009.7, 1010.7, 1011.7],
517
  [1001.0, 1002.0, 1003.0, 1004.0, 1005.0, ..., 1008.0, 1009.0, 1010.0, 1011.0, 1012.0],
518
  [1000.4, 1001.4, 1002.4, 1003.4, 1004.4, ..., 1007.4, 1008.4, 1009.4, 1010.4, 1011.4],
519
  [ 999.5, 1000.5, 1001.5, 1002.5, 1003.5, ..., 1006.5, 1007.5, 1008.5, 1009.5, 1010.5]],
520
521
 [[1001.0, 1002.0, 1003.0, 1004.0, 1005.0, ..., 1008.0, 1009.0, 1010.0, 1011.0, 1012.0],
522
  [1001.8, 1002.8, 1003.8, 1004.8, 1005.8, ..., 1008.8, 1009.8, 1010.8, 1011.8, 1012.8],
523
  [1001.9, 1002.9, 1003.9, 1004.9, 1005.9, ..., 1008.9, 1009.9, 1010.9, 1011.9, 1012.9],
524
  [1001.1, 1002.1, 1003.1, 1004.1, 1005.1, ..., 1008.1, 1009.1, 1010.1, 1011.1, 1012.1],
525
  [1000.2, 1001.2, 1002.2, 1003.2, 1004.2, ..., 1007.2, 1008.2, 1009.2, 1010.2, 1011.2],
526
  [1000.0, 1001.0, 1002.0, 1003.0, 1004.0, ..., 1007.0, 1008.0, 1009.0, 1010.0, 1011.0],
527
  [1000.7, 1001.7, 1002.7, 1003.7, 1004.7, ..., 1007.7, 1008.7, 1009.7, 1010.7, 1011.7],
528
  [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7],
529
  [1002.0, 1003.0, 1004.0, 1005.0, 1006.0, ..., 1009.0, 1010.0, 1011.0, 1012.0, 1013.0],
530
  [1001.4, 1002.4, 1003.4, 1004.4, 1005.4, ..., 1008.4, 1009.4, 1010.4, 1011.4, 1012.4],
531
  [1000.5, 1001.5, 1002.5, 1003.5, 1004.5, ..., 1007.5, 1008.5, 1009.5, 1010.5, 1011.5]],
532
533
 [[1001.4, 1002.4, 1003.4, 1004.4, 1005.4, ..., 1008.4, 1009.4, 1010.4, 1011.4, 1012.4],
534
  [1002.3, 1003.3, 1004.3, 1005.3, 1006.3, ..., 1009.3, 1010.3, 1011.3, 1012.3, 1013.3],
535
  [1002.3, 1003.3, 1004.3, 1005.3, 1006.3, ..., 1009.3, 1010.3, 1011.3, 1012.3, 1013.3],
536
  [1001.6, 1002.6, 1003.6, 1004.6, 1005.6, ..., 1008.6, 1009.6, 1010.6, 1011.6, 1012.6],
537
  [1000.7, 1001.7, 1002.7, 1003.7, 1004.7, ..., 1007.7, 1008.7, 1009.7, 1010.7, 1011.7],
538
  [1000.5, 1001.5, 1002.5, 1003.5, 1004.5, ..., 1007.5, 1008.5, 1009.5, 1010.5, 1011.5],
539
  [1001.1, 1002.1, 1003.1, 1004.1, 1005.1, ..., 1008.1, 1009.1, 1010.1, 1011.1, 1012.1],
540
  [1002.1, 1003.1, 1004.1, 1005.1, 1006.1, ..., 1009.1, 1010.1, 1011.1, 1012.1, 1013.1],
541
  [1002.4, 1003.4, 1004.4, 1005.4, 1006.4, ..., 1009.4, 1010.4, 1011.4, 1012.4, 1013.4],
542
  [1001.8, 1002.8, 1003.8, 1004.8, 1005.8, ..., 1008.8, 1009.8, 1010.8, 1011.8, 1012.8],
543
  [1000.9, 1001.9, 1002.9, 1003.9, 1004.9, ..., 1007.9, 1008.9, 1009.9, 1010.9, 1011.9]],
544
545
 ...,
546
547
 [[1002.0, 1003.0, 1004.0, 1005.0, 1006.0, ..., 1009.0, 1010.0, 1011.0, 1012.0, 1013.0],
548
  [1002.8, 1003.8, 1004.8, 1005.8, 1006.8, ..., 1009.8, 1010.8, 1011.8, 1012.8, 1013.8],
549
  [1002.9, 1003.9, 1004.9, 1005.9, 1006.9, ..., 1009.9, 1010.9, 1011.9, 1012.9, 1013.9],
550
  [1002.1, 1003.1, 1004.1, 1005.1, 1006.1, ..., 1009.1, 1010.1, 1011.1, 1012.1, 1013.1],
551
  [1001.2, 1002.2, 1003.2, 1004.2, 1005.2, ..., 1008.2, 1009.2, 1010.2, 1011.2, 1012.2],
552
  [1001.0, 1002.0, 1003.0, 1004.0, 1005.0, ..., 1008.0, 1009.0, 1010.0, 1011.0, 1012.0],
553
  [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7],
554
  [1002.7, 1003.7, 1004.7, 1005.7, 1006.7, ..., 1009.7, 1010.7, 1011.7, 1012.7, 1013.7],
555
  [1003.0, 1004.0, 1005.0, 1006.0, 1007.0, ..., 1010.0, 1011.0, 1012.0, 1013.0, 1014.0],
556
  [1002.4, 1003.4, 1004.4, 1005.4, 1006.4, ..., 1009.4, 1010.4, 1011.4, 1012.4, 1013.4],
557
  [1001.5, 1002.5, 1003.5, 1004.5, 1005.5, ..., 1008.5, 1009.5, 1010.5, 1011.5, 1012.5]],
558
559
 [[1002.2, 1003.2, 1004.2, 1005.2, 1006.2, ..., 1009.2, 1010.2, 1011.2, 1012.2, 1013.2],
560
  [1003.1, 1004.1, 1005.1, 1006.1, 1007.1, ..., 1010.1, 1011.1, 1012.1, 1013.1, 1014.1],
561
  [1003.1, 1004.1, 1005.1, 1006.1, 1007.1, ..., 1010.1, 1011.1, 1012.1, 1013.1, 1014.1],
562
  [1002.4, 1003.4, 1004.4, 1005.4, 1006.4, ..., 1009.4, 1010.4, 1011.4, 1012.4, 1013.4],
563
  [1001.5, 1002.5, 1003.5, 1004.5, 1005.5, ..., 1008.5, 1009.5, 1010.5, 1011.5, 1012.5],
564
  [1001.3, 1002.3, 1003.3, 1004.3, 1005.3, ..., 1008.3, 1009.3, 1010.3, 1011.3, 1012.3],
565
  [1002.0, 1003.0, 1004.0, 1005.0, 1006.0, ..., 1009.0, 1010.0, 1011.0, 1012.0, 1013.0],
566
  [1002.9, 1003.9, 1004.9, 1005.9, 1006.9, ..., 1009.9, 1010.9, 1011.9, 1012.9, 1013.9],
567
  [1003.2, 1004.2, 1005.2, 1006.2, 1007.2, ..., 1010.2, 1011.2, 1012.2, 1013.2, 1014.2],
568
  [1002.6, 1003.6, 1004.6, 1005.6, 1006.6, ..., 1009.6, 1010.6, 1011.6, 1012.6, 1013.6],
569
  [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7]],
570
571
 [[1002.5, 1003.5, 1004.5, 1005.5, 1006.5, ..., 1009.5, 1010.5, 1011.5, 1012.5, 1013.5],
572
  [1003.3, 1004.3, 1005.3, 1006.3, 1007.3, ..., 1010.3, 1011.3, 1012.3, 1013.3, 1014.3],
573
  [1003.4, 1004.4, 1005.4, 1006.4, 1007.4, ..., 1010.4, 1011.4, 1012.4, 1013.4, 1014.4],
574
  [1002.6, 1003.6, 1004.6, 1005.6, 1006.6, ..., 1009.6, 1010.6, 1011.6, 1012.6, 1013.6],
575
  [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7],
576
  [1001.5, 1002.5, 1003.5, 1004.5, 1005.5, ..., 1008.5, 1009.5, 1010.5, 1011.5, 1012.5],
577
  [1002.2, 1003.2, 1004.2, 1005.2, 1006.2, ..., 1009.2, 1010.2, 1011.2, 1012.2, 1013.2],
578
  [1003.1, 1004.1, 1005.1, 1006.1, 1007.1, ..., 1010.1, 1011.1, 1012.1, 1013.1, 1014.1],
579
  [1003.4, 1004.4, 1005.4, 1006.4, 1007.4, ..., 1010.4, 1011.4, 1012.4, 1013.4, 1014.4],
580
  [1002.9, 1003.9, 1004.9, 1005.9, 1006.9, ..., 1009.9, 1010.9, 1011.9, 1012.9, 1013.9],
581
  [1001.9, 1002.9, 1003.9, 1004.9, 1005.9, ..., 1008.9, 1009.9, 1010.9, 1011.9, 1012.9]]]";
582
        assert_str_eq(expected, &actual);
583
    }
584
585
    #[test]
586
    fn dim_4_overflow_outer()
587
    {
588
        let a = Array4::from_shape_fn((10, 10, 3, 3), |(i, j, k, l)| i + j + k + l);
589
        let actual = format!("{:2}", a);
590
        // Generated using NumPy with:
591
        // np.set_printoptions(threshold=500, edgeitems=3)
592
        // np.fromfunction(lambda i, j, k, l: i + j + k + l, (10, 10, 3, 3), dtype=int)
593
        //
594
        let expected = "\
595
[[[[ 0,  1,  2],
596
   [ 1,  2,  3],
597
   [ 2,  3,  4]],
598
599
  [[ 1,  2,  3],
600
   [ 2,  3,  4],
601
   [ 3,  4,  5]],
602
603
  [[ 2,  3,  4],
604
   [ 3,  4,  5],
605
   [ 4,  5,  6]],
606
607
  ...,
608
609
  [[ 7,  8,  9],
610
   [ 8,  9, 10],
611
   [ 9, 10, 11]],
612
613
  [[ 8,  9, 10],
614
   [ 9, 10, 11],
615
   [10, 11, 12]],
616
617
  [[ 9, 10, 11],
618
   [10, 11, 12],
619
   [11, 12, 13]]],
620
621
622
 [[[ 1,  2,  3],
623
   [ 2,  3,  4],
624
   [ 3,  4,  5]],
625
626
  [[ 2,  3,  4],
627
   [ 3,  4,  5],
628
   [ 4,  5,  6]],
629
630
  [[ 3,  4,  5],
631
   [ 4,  5,  6],
632
   [ 5,  6,  7]],
633
634
  ...,
635
636
  [[ 8,  9, 10],
637
   [ 9, 10, 11],
638
   [10, 11, 12]],
639
640
  [[ 9, 10, 11],
641
   [10, 11, 12],
642
   [11, 12, 13]],
643
644
  [[10, 11, 12],
645
   [11, 12, 13],
646
   [12, 13, 14]]],
647
648
649
 [[[ 2,  3,  4],
650
   [ 3,  4,  5],
651
   [ 4,  5,  6]],
652
653
  [[ 3,  4,  5],
654
   [ 4,  5,  6],
655
   [ 5,  6,  7]],
656
657
  [[ 4,  5,  6],
658
   [ 5,  6,  7],
659
   [ 6,  7,  8]],
660
661
  ...,
662
663
  [[ 9, 10, 11],
664
   [10, 11, 12],
665
   [11, 12, 13]],
666
667
  [[10, 11, 12],
668
   [11, 12, 13],
669
   [12, 13, 14]],
670
671
  [[11, 12, 13],
672
   [12, 13, 14],
673
   [13, 14, 15]]],
674
675
676
 ...,
677
678
679
 [[[ 7,  8,  9],
680
   [ 8,  9, 10],
681
   [ 9, 10, 11]],
682
683
  [[ 8,  9, 10],
684
   [ 9, 10, 11],
685
   [10, 11, 12]],
686
687
  [[ 9, 10, 11],
688
   [10, 11, 12],
689
   [11, 12, 13]],
690
691
  ...,
692
693
  [[14, 15, 16],
694
   [15, 16, 17],
695
   [16, 17, 18]],
696
697
  [[15, 16, 17],
698
   [16, 17, 18],
699
   [17, 18, 19]],
700
701
  [[16, 17, 18],
702
   [17, 18, 19],
703
   [18, 19, 20]]],
704
705
706
 [[[ 8,  9, 10],
707
   [ 9, 10, 11],
708
   [10, 11, 12]],
709
710
  [[ 9, 10, 11],
711
   [10, 11, 12],
712
   [11, 12, 13]],
713
714
  [[10, 11, 12],
715
   [11, 12, 13],
716
   [12, 13, 14]],
717
718
  ...,
719
720
  [[15, 16, 17],
721
   [16, 17, 18],
722
   [17, 18, 19]],
723
724
  [[16, 17, 18],
725
   [17, 18, 19],
726
   [18, 19, 20]],
727
728
  [[17, 18, 19],
729
   [18, 19, 20],
730
   [19, 20, 21]]],
731
732
733
 [[[ 9, 10, 11],
734
   [10, 11, 12],
735
   [11, 12, 13]],
736
737
  [[10, 11, 12],
738
   [11, 12, 13],
739
   [12, 13, 14]],
740
741
  [[11, 12, 13],
742
   [12, 13, 14],
743
   [13, 14, 15]],
744
745
  ...,
746
747
  [[16, 17, 18],
748
   [17, 18, 19],
749
   [18, 19, 20]],
750
751
  [[17, 18, 19],
752
   [18, 19, 20],
753
   [19, 20, 21]],
754
755
  [[18, 19, 20],
756
   [19, 20, 21],
757
   [20, 21, 22]]]]";
758
        assert_str_eq(expected, &actual);
759
    }
760
}