1use std::fmt;
2
3use crate::{
4 device::DeviceBase,
5 dim::{DimDyn, DimTrait},
6 index::Index0D,
7 matrix::{Matrix, Ref, Repr},
8 num::Num,
9};
10const ARRAY_MANY_ELEMENT_LIMIT: usize = 500;
12const AXIS_LIMIT_STACKED: usize = 6;
14const AXIS_LIMIT_COL: usize = 11;
17const AXIS_LIMIT_ROW: usize = 11;
20
21const ELLIPSIS: &str = "...";
23
24#[expect(clippy::struct_field_names)]
25#[derive(Clone, Debug)]
26struct FormatOptions {
27 axis_collapse_limit: usize,
28 axis_collapse_limit_next_last: usize,
29 axis_collapse_limit_last: usize,
30}
31
32impl FormatOptions {
33 pub(crate) fn default_for_array(nelem: usize, no_limit: bool) -> Self {
34 let default = Self {
35 axis_collapse_limit: AXIS_LIMIT_STACKED,
36 axis_collapse_limit_next_last: AXIS_LIMIT_COL,
37 axis_collapse_limit_last: AXIS_LIMIT_ROW,
38 };
39 default.set_no_limit(no_limit || nelem < ARRAY_MANY_ELEMENT_LIMIT)
40 }
41
42 fn set_no_limit(mut self, no_limit: bool) -> Self {
43 if no_limit {
44 self.axis_collapse_limit = usize::MAX;
45 self.axis_collapse_limit_next_last = usize::MAX;
46 self.axis_collapse_limit_last = usize::MAX;
47 }
48 self
49 }
50
51 pub(crate) fn collapse_limit(&self, axis_rindex: usize) -> usize {
54 match axis_rindex {
55 0 => self.axis_collapse_limit_last,
56 1 => self.axis_collapse_limit_next_last,
57 _ => self.axis_collapse_limit,
58 }
59 }
60}
61
62fn format_with_overflow(
75 f: &mut fmt::Formatter<'_>,
76 length: usize,
77 limit: usize,
78 separator: &str,
79 ellipsis: &str,
80 fmt_elem: &mut dyn FnMut(&mut fmt::Formatter, usize) -> fmt::Result,
81) -> fmt::Result {
82 if length == 0 {
83 } else if length <= limit {
85 fmt_elem(f, 0)?;
86 for i in 1..length {
87 f.write_str(separator)?;
88 fmt_elem(f, i)?;
89 }
90 } else {
91 let edge = limit / 2;
92 fmt_elem(f, 0)?;
93 for i in 1..edge {
94 f.write_str(separator)?;
95 fmt_elem(f, i)?;
96 }
97 f.write_str(separator)?;
98 f.write_str(ellipsis)?;
99 for i in length - edge..length {
100 f.write_str(separator)?;
101 fmt_elem(f, i)?;
102 }
103 }
104 Ok(())
105}
106
107fn format_array<A, R, S, D, F>(
108 array: &Matrix<R, S, D>,
109 f: &mut fmt::Formatter<'_>,
110 format: F,
111 fmt_opt: &FormatOptions,
112) -> fmt::Result
113where
114 A: Num,
115 F: FnMut(&A, &mut fmt::Formatter<'_>) -> fmt::Result + Clone,
116 S: DimTrait,
117 R: Repr<Item = A>,
118 D: DeviceBase,
119{
120 format_array_inner(
123 array.to_ref().into_dyn_dim(),
124 f,
125 format,
126 fmt_opt,
127 0,
128 array.shape().len(),
129 )
130}
131
132fn format_array_inner<T, F, D>(
133 view: Matrix<Ref<&T>, DimDyn, D>,
134 f: &mut fmt::Formatter<'_>,
135 mut format: F,
136 fmt_opt: &FormatOptions,
137 depth: usize,
138 full_ndim: usize,
139) -> fmt::Result
140where
141 T: Num,
142 F: FnMut(&T, &mut fmt::Formatter<'_>) -> fmt::Result + Clone,
143 D: DeviceBase,
144{
145 match view.shape().slice() {
146 &[] => format(&view.index_item(&[] as &[usize]), f)?,
148 &[len] => {
150 let view = view.into_dyn_dim();
151 f.write_str("[")?;
152 format_with_overflow(
153 f,
154 len,
155 fmt_opt.collapse_limit(0),
156 ", ",
157 ELLIPSIS,
158 &mut |f, index| format(&view.index_item([index]), f),
159 )?;
160 f.write_str("]")?;
161 }
162 shape => {
164 let blank_lines = "\n".repeat(shape.len() - 2);
165 let indent = " ".repeat(depth + 1);
166 let separator = format!(",\n{blank_lines}{indent}");
167
168 f.write_str("[")?;
169 let limit = fmt_opt.collapse_limit(full_ndim - depth - 1);
170 format_with_overflow(f, shape[0], limit, &separator, ELLIPSIS, &mut |f, index| {
171 format_array_inner(
172 view.index_axis_dyn(Index0D::new(index)),
173 f,
174 format.clone(),
175 fmt_opt,
176 depth + 1,
177 full_ndim,
178 )
179 })?;
180 f.write_str("]")?;
181 }
182 }
183 Ok(())
184}
185
186impl<A, R, S, D> fmt::Display for Matrix<R, S, D>
192where
193 A: Num + fmt::Display,
194 R: Repr<Item = A>,
195 S: DimTrait,
196 D: DeviceBase,
197{
198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 let fmt_opt = FormatOptions::default_for_array(self.shape().num_elm(), f.alternate());
200 format_array(self, f, <_>::fmt, &fmt_opt)
201 }
202}
203
204impl<A, R, S, D> fmt::Debug for Matrix<R, S, D>
209where
210 A: Num + fmt::Debug,
211 R: Repr<Item = A>,
212 S: DimTrait,
213 D: DeviceBase,
214{
215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216 let fmt_opt = FormatOptions::default_for_array(self.shape().num_elm(), f.alternate());
217 format_array(self, f, <_>::fmt, &fmt_opt)?;
218
219 write!(
221 f,
222 "\n shape={:?}, strides={:?}",
223 self.shape(),
225 self.stride(),
226 )?;
227 Ok(())
232 }
233}
234
235#[cfg(test)]
236mod matrix_format_test {
237 #![expect(clippy::uninlined_format_args)]
238 use crate::{
239 device::DeviceBase,
240 dim::{Dim2, Dim4, DimDyn},
241 matrix::{Matrix, Owned},
242 };
243
244 fn assert_str_eq(expected: &str, actual: &str) {
245 assert!(
247 expected == actual,
248 "formatting assertion failed\nexpected:\n{}\nactual:\n{}\n",
249 expected,
250 actual,
251 );
252 }
253
254 fn small_array_1d<D: DeviceBase>() {
255 let a: Matrix<Owned<f32>, DimDyn, D> = Matrix::from_vec(vec![1., 2., 3., 4., 5.], [5]);
256 assert_eq!(format!("{}", a), "[1, 2, 3, 4, 5]");
257 }
258 #[test]
259 fn small_array_1d_cpu() {
260 small_array_1d::<crate::device::cpu::Cpu>();
261 }
262 #[cfg(feature = "nvidia")]
263 #[test]
264 fn small_array_1d_nvidia() {
265 small_array_1d::<crate::device::nvidia::Nvidia>();
266 }
267
268 fn mid_array_1d<D: DeviceBase>() {
269 let a: Matrix<Owned<f32>, DimDyn, D> =
270 Matrix::from_vec(vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10.], [10]);
271 assert_eq!(format!("{}", a), "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]");
272 }
273 #[test]
274 fn mid_array_1d_cpu() {
275 mid_array_1d::<crate::device::cpu::Cpu>();
276 }
277 #[cfg(feature = "nvidia")]
278 #[test]
279 fn mid_array_1d_nvidia() {
280 mid_array_1d::<crate::device::nvidia::Nvidia>();
281 }
282
283 #[expect(clippy::cast_precision_loss)]
284 fn large_array_1d<D: DeviceBase>() {
285 let mut v = Vec::new();
286 for i in 1..=1000 {
287 v.push(i as f32);
288 }
289 let a: Matrix<Owned<f32>, DimDyn, D> = Matrix::from_vec(v, [1000]);
290 assert_eq!(
291 format!("{}", a),
292 "[1, 2, 3, 4, 5, ..., 996, 997, 998, 999, 1000]"
293 );
294 }
295 #[test]
296 fn large_array_1d_cpu() {
297 large_array_1d::<crate::device::cpu::Cpu>();
298 }
299 #[cfg(feature = "nvidia")]
300 #[test]
301 fn large_array_1d_nvidia() {
302 large_array_1d::<crate::device::nvidia::Nvidia>();
303 }
304
305 fn dim_2_last_axis_overflow<D: DeviceBase>() {
306 let a: Matrix<Owned<f32>, Dim2, D> = Matrix::ones([22, 24]);
307 let actual = format!("{}", a);
308 let expected = "\
309[[1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
310 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
311 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
312 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
313 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
314 ...,
315 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
316 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
317 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
318 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
319 [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1]]";
320 assert_str_eq(expected, &actual);
321 }
322 #[test]
323 fn dim_2_last_axis_overflow_cpu() {
324 dim_2_last_axis_overflow::<crate::device::cpu::Cpu>();
325 }
326 #[cfg(feature = "nvidia")]
327 #[test]
328 fn dim_2_last_axis_overflow_nvidia() {
329 dim_2_last_axis_overflow::<crate::device::nvidia::Nvidia>();
330 }
331
332 #[expect(clippy::cast_lossless)]
333 fn dim_3_overflow_most<D: DeviceBase>() {
334 let mut v = Vec::new();
335 for i in 0..7 {
336 for j in 0..11 {
337 for k in 0..12 {
338 v.push(
339 1000.
340 + (100. * ((i as f64).sqrt() + (j as f64).sin() + k as f64)).round()
341 / 100.,
342 );
343 }
344 }
345 }
346 let a: Matrix<Owned<f64>, DimDyn, D> = Matrix::from_vec(v, [7, 11, 12]);
353 let actual = format!("{:6.1}", a);
354 let expected = "\
355[[[1000.0, 1001.0, 1002.0, 1003.0, 1004.0, ..., 1007.0, 1008.0, 1009.0, 1010.0, 1011.0],
356 [1000.8, 1001.8, 1002.8, 1003.8, 1004.8, ..., 1007.8, 1008.8, 1009.8, 1010.8, 1011.8],
357 [1000.9, 1001.9, 1002.9, 1003.9, 1004.9, ..., 1007.9, 1008.9, 1009.9, 1010.9, 1011.9],
358 [1000.1, 1001.1, 1002.1, 1003.1, 1004.1, ..., 1007.1, 1008.1, 1009.1, 1010.1, 1011.1],
359 [ 999.2, 1000.2, 1001.2, 1002.2, 1003.2, ..., 1006.2, 1007.2, 1008.2, 1009.2, 1010.2],
360 [ 999.0, 1000.0, 1001.0, 1002.0, 1003.0, ..., 1006.0, 1007.0, 1008.0, 1009.0, 1010.0],
361 [ 999.7, 1000.7, 1001.7, 1002.7, 1003.7, ..., 1006.7, 1007.7, 1008.7, 1009.7, 1010.7],
362 [1000.7, 1001.7, 1002.7, 1003.7, 1004.7, ..., 1007.7, 1008.7, 1009.7, 1010.7, 1011.7],
363 [1001.0, 1002.0, 1003.0, 1004.0, 1005.0, ..., 1008.0, 1009.0, 1010.0, 1011.0, 1012.0],
364 [1000.4, 1001.4, 1002.4, 1003.4, 1004.4, ..., 1007.4, 1008.4, 1009.4, 1010.4, 1011.4],
365 [ 999.5, 1000.5, 1001.5, 1002.5, 1003.5, ..., 1006.5, 1007.5, 1008.5, 1009.5, 1010.5]],
366
367 [[1001.0, 1002.0, 1003.0, 1004.0, 1005.0, ..., 1008.0, 1009.0, 1010.0, 1011.0, 1012.0],
368 [1001.8, 1002.8, 1003.8, 1004.8, 1005.8, ..., 1008.8, 1009.8, 1010.8, 1011.8, 1012.8],
369 [1001.9, 1002.9, 1003.9, 1004.9, 1005.9, ..., 1008.9, 1009.9, 1010.9, 1011.9, 1012.9],
370 [1001.1, 1002.1, 1003.1, 1004.1, 1005.1, ..., 1008.1, 1009.1, 1010.1, 1011.1, 1012.1],
371 [1000.2, 1001.2, 1002.2, 1003.2, 1004.2, ..., 1007.2, 1008.2, 1009.2, 1010.2, 1011.2],
372 [1000.0, 1001.0, 1002.0, 1003.0, 1004.0, ..., 1007.0, 1008.0, 1009.0, 1010.0, 1011.0],
373 [1000.7, 1001.7, 1002.7, 1003.7, 1004.7, ..., 1007.7, 1008.7, 1009.7, 1010.7, 1011.7],
374 [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7],
375 [1002.0, 1003.0, 1004.0, 1005.0, 1006.0, ..., 1009.0, 1010.0, 1011.0, 1012.0, 1013.0],
376 [1001.4, 1002.4, 1003.4, 1004.4, 1005.4, ..., 1008.4, 1009.4, 1010.4, 1011.4, 1012.4],
377 [1000.5, 1001.5, 1002.5, 1003.5, 1004.5, ..., 1007.5, 1008.5, 1009.5, 1010.5, 1011.5]],
378
379 [[1001.4, 1002.4, 1003.4, 1004.4, 1005.4, ..., 1008.4, 1009.4, 1010.4, 1011.4, 1012.4],
380 [1002.3, 1003.3, 1004.3, 1005.3, 1006.3, ..., 1009.3, 1010.3, 1011.3, 1012.3, 1013.3],
381 [1002.3, 1003.3, 1004.3, 1005.3, 1006.3, ..., 1009.3, 1010.3, 1011.3, 1012.3, 1013.3],
382 [1001.6, 1002.6, 1003.6, 1004.6, 1005.6, ..., 1008.6, 1009.6, 1010.6, 1011.6, 1012.6],
383 [1000.7, 1001.7, 1002.7, 1003.7, 1004.7, ..., 1007.7, 1008.7, 1009.7, 1010.7, 1011.7],
384 [1000.5, 1001.5, 1002.5, 1003.5, 1004.5, ..., 1007.5, 1008.5, 1009.5, 1010.5, 1011.5],
385 [1001.1, 1002.1, 1003.1, 1004.1, 1005.1, ..., 1008.1, 1009.1, 1010.1, 1011.1, 1012.1],
386 [1002.1, 1003.1, 1004.1, 1005.1, 1006.1, ..., 1009.1, 1010.1, 1011.1, 1012.1, 1013.1],
387 [1002.4, 1003.4, 1004.4, 1005.4, 1006.4, ..., 1009.4, 1010.4, 1011.4, 1012.4, 1013.4],
388 [1001.8, 1002.8, 1003.8, 1004.8, 1005.8, ..., 1008.8, 1009.8, 1010.8, 1011.8, 1012.8],
389 [1000.9, 1001.9, 1002.9, 1003.9, 1004.9, ..., 1007.9, 1008.9, 1009.9, 1010.9, 1011.9]],
390
391 ...,
392
393 [[1002.0, 1003.0, 1004.0, 1005.0, 1006.0, ..., 1009.0, 1010.0, 1011.0, 1012.0, 1013.0],
394 [1002.8, 1003.8, 1004.8, 1005.8, 1006.8, ..., 1009.8, 1010.8, 1011.8, 1012.8, 1013.8],
395 [1002.9, 1003.9, 1004.9, 1005.9, 1006.9, ..., 1009.9, 1010.9, 1011.9, 1012.9, 1013.9],
396 [1002.1, 1003.1, 1004.1, 1005.1, 1006.1, ..., 1009.1, 1010.1, 1011.1, 1012.1, 1013.1],
397 [1001.2, 1002.2, 1003.2, 1004.2, 1005.2, ..., 1008.2, 1009.2, 1010.2, 1011.2, 1012.2],
398 [1001.0, 1002.0, 1003.0, 1004.0, 1005.0, ..., 1008.0, 1009.0, 1010.0, 1011.0, 1012.0],
399 [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7],
400 [1002.7, 1003.7, 1004.7, 1005.7, 1006.7, ..., 1009.7, 1010.7, 1011.7, 1012.7, 1013.7],
401 [1003.0, 1004.0, 1005.0, 1006.0, 1007.0, ..., 1010.0, 1011.0, 1012.0, 1013.0, 1014.0],
402 [1002.4, 1003.4, 1004.4, 1005.4, 1006.4, ..., 1009.4, 1010.4, 1011.4, 1012.4, 1013.4],
403 [1001.5, 1002.5, 1003.5, 1004.5, 1005.5, ..., 1008.5, 1009.5, 1010.5, 1011.5, 1012.5]],
404
405 [[1002.2, 1003.2, 1004.2, 1005.2, 1006.2, ..., 1009.2, 1010.2, 1011.2, 1012.2, 1013.2],
406 [1003.1, 1004.1, 1005.1, 1006.1, 1007.1, ..., 1010.1, 1011.1, 1012.1, 1013.1, 1014.1],
407 [1003.1, 1004.1, 1005.1, 1006.1, 1007.1, ..., 1010.1, 1011.1, 1012.1, 1013.1, 1014.1],
408 [1002.4, 1003.4, 1004.4, 1005.4, 1006.4, ..., 1009.4, 1010.4, 1011.4, 1012.4, 1013.4],
409 [1001.5, 1002.5, 1003.5, 1004.5, 1005.5, ..., 1008.5, 1009.5, 1010.5, 1011.5, 1012.5],
410 [1001.3, 1002.3, 1003.3, 1004.3, 1005.3, ..., 1008.3, 1009.3, 1010.3, 1011.3, 1012.3],
411 [1002.0, 1003.0, 1004.0, 1005.0, 1006.0, ..., 1009.0, 1010.0, 1011.0, 1012.0, 1013.0],
412 [1002.9, 1003.9, 1004.9, 1005.9, 1006.9, ..., 1009.9, 1010.9, 1011.9, 1012.9, 1013.9],
413 [1003.2, 1004.2, 1005.2, 1006.2, 1007.2, ..., 1010.2, 1011.2, 1012.2, 1013.2, 1014.2],
414 [1002.6, 1003.6, 1004.6, 1005.6, 1006.6, ..., 1009.6, 1010.6, 1011.6, 1012.6, 1013.6],
415 [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7]],
416
417 [[1002.5, 1003.5, 1004.5, 1005.5, 1006.5, ..., 1009.5, 1010.5, 1011.5, 1012.5, 1013.5],
418 [1003.3, 1004.3, 1005.3, 1006.3, 1007.3, ..., 1010.3, 1011.3, 1012.3, 1013.3, 1014.3],
419 [1003.4, 1004.4, 1005.4, 1006.4, 1007.4, ..., 1010.4, 1011.4, 1012.4, 1013.4, 1014.4],
420 [1002.6, 1003.6, 1004.6, 1005.6, 1006.6, ..., 1009.6, 1010.6, 1011.6, 1012.6, 1013.6],
421 [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7],
422 [1001.5, 1002.5, 1003.5, 1004.5, 1005.5, ..., 1008.5, 1009.5, 1010.5, 1011.5, 1012.5],
423 [1002.2, 1003.2, 1004.2, 1005.2, 1006.2, ..., 1009.2, 1010.2, 1011.2, 1012.2, 1013.2],
424 [1003.1, 1004.1, 1005.1, 1006.1, 1007.1, ..., 1010.1, 1011.1, 1012.1, 1013.1, 1014.1],
425 [1003.4, 1004.4, 1005.4, 1006.4, 1007.4, ..., 1010.4, 1011.4, 1012.4, 1013.4, 1014.4],
426 [1002.9, 1003.9, 1004.9, 1005.9, 1006.9, ..., 1009.9, 1010.9, 1011.9, 1012.9, 1013.9],
427 [1001.9, 1002.9, 1003.9, 1004.9, 1005.9, ..., 1008.9, 1009.9, 1010.9, 1011.9, 1012.9]]]";
428 assert_str_eq(expected, &actual);
429 }
430 #[test]
431 fn dim_3_overflow_most_cpu() {
432 dim_3_overflow_most::<crate::device::cpu::Cpu>();
433 }
434 #[cfg(feature = "nvidia")]
435 #[test]
436 fn dim_3_overflow_most_nvidia() {
437 dim_3_overflow_most::<crate::device::nvidia::Nvidia>();
438 }
439
440 #[expect(clippy::too_many_lines, clippy::cast_precision_loss)]
441 fn dim_4_overflow_outer<D: DeviceBase>() {
442 let mut v = Vec::new();
444 for i in 0..10 {
445 for j in 0..10 {
446 for k in 0..3 {
447 for l in 0..3 {
448 v.push((i + j + k + l) as f32);
449 }
450 }
451 }
452 }
453 let a: Matrix<Owned<f32>, Dim4, D> = Matrix::from_vec(v, [10, 10, 3, 3]);
454 let actual = format!("{:2}", a);
455 let expected = "\
460[[[[ 0, 1, 2],
461 [ 1, 2, 3],
462 [ 2, 3, 4]],
463
464 [[ 1, 2, 3],
465 [ 2, 3, 4],
466 [ 3, 4, 5]],
467
468 [[ 2, 3, 4],
469 [ 3, 4, 5],
470 [ 4, 5, 6]],
471
472 ...,
473
474 [[ 7, 8, 9],
475 [ 8, 9, 10],
476 [ 9, 10, 11]],
477
478 [[ 8, 9, 10],
479 [ 9, 10, 11],
480 [10, 11, 12]],
481
482 [[ 9, 10, 11],
483 [10, 11, 12],
484 [11, 12, 13]]],
485
486
487 [[[ 1, 2, 3],
488 [ 2, 3, 4],
489 [ 3, 4, 5]],
490
491 [[ 2, 3, 4],
492 [ 3, 4, 5],
493 [ 4, 5, 6]],
494
495 [[ 3, 4, 5],
496 [ 4, 5, 6],
497 [ 5, 6, 7]],
498
499 ...,
500
501 [[ 8, 9, 10],
502 [ 9, 10, 11],
503 [10, 11, 12]],
504
505 [[ 9, 10, 11],
506 [10, 11, 12],
507 [11, 12, 13]],
508
509 [[10, 11, 12],
510 [11, 12, 13],
511 [12, 13, 14]]],
512
513
514 [[[ 2, 3, 4],
515 [ 3, 4, 5],
516 [ 4, 5, 6]],
517
518 [[ 3, 4, 5],
519 [ 4, 5, 6],
520 [ 5, 6, 7]],
521
522 [[ 4, 5, 6],
523 [ 5, 6, 7],
524 [ 6, 7, 8]],
525
526 ...,
527
528 [[ 9, 10, 11],
529 [10, 11, 12],
530 [11, 12, 13]],
531
532 [[10, 11, 12],
533 [11, 12, 13],
534 [12, 13, 14]],
535
536 [[11, 12, 13],
537 [12, 13, 14],
538 [13, 14, 15]]],
539
540
541 ...,
542
543
544 [[[ 7, 8, 9],
545 [ 8, 9, 10],
546 [ 9, 10, 11]],
547
548 [[ 8, 9, 10],
549 [ 9, 10, 11],
550 [10, 11, 12]],
551
552 [[ 9, 10, 11],
553 [10, 11, 12],
554 [11, 12, 13]],
555
556 ...,
557
558 [[14, 15, 16],
559 [15, 16, 17],
560 [16, 17, 18]],
561
562 [[15, 16, 17],
563 [16, 17, 18],
564 [17, 18, 19]],
565
566 [[16, 17, 18],
567 [17, 18, 19],
568 [18, 19, 20]]],
569
570
571 [[[ 8, 9, 10],
572 [ 9, 10, 11],
573 [10, 11, 12]],
574
575 [[ 9, 10, 11],
576 [10, 11, 12],
577 [11, 12, 13]],
578
579 [[10, 11, 12],
580 [11, 12, 13],
581 [12, 13, 14]],
582
583 ...,
584
585 [[15, 16, 17],
586 [16, 17, 18],
587 [17, 18, 19]],
588
589 [[16, 17, 18],
590 [17, 18, 19],
591 [18, 19, 20]],
592
593 [[17, 18, 19],
594 [18, 19, 20],
595 [19, 20, 21]]],
596
597
598 [[[ 9, 10, 11],
599 [10, 11, 12],
600 [11, 12, 13]],
601
602 [[10, 11, 12],
603 [11, 12, 13],
604 [12, 13, 14]],
605
606 [[11, 12, 13],
607 [12, 13, 14],
608 [13, 14, 15]],
609
610 ...,
611
612 [[16, 17, 18],
613 [17, 18, 19],
614 [18, 19, 20]],
615
616 [[17, 18, 19],
617 [18, 19, 20],
618 [19, 20, 21]],
619
620 [[18, 19, 20],
621 [19, 20, 21],
622 [20, 21, 22]]]]";
623 assert_str_eq(expected, &actual);
624 }
625 #[test]
626 fn dim_4_overflow_outer_cpu() {
627 dim_4_overflow_outer::<crate::device::cpu::Cpu>();
628 }
629 #[cfg(feature = "nvidia")]
630 #[test]
631 fn dim_4_overflow_outer_nvidia() {
632 dim_4_overflow_outer::<crate::device::nvidia::Nvidia>();
633 }
634}