/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 | | } |