Repository: rust-ndarray/ndarray
Pull request #713 (2019-09-15 11:17:37)

Increase limits for overflow in formatting
Use a total element count limit, before abbreviating the format output.
This means "small" arrays are always printed in full.

Use separate limits for the last axis, the next to last axis and the
other axes before that.

The last two axes are printed like a matrix of elements which is why
they show more elements.

The other axes are "stacked" and printed by repeating the inner two axes
(like stacked 2D arrays). For this reason they are harder to read
already, and we use a lower limit.

Limits:

- Array is printed in full below 500 elements
- Max row length otherwise: 11
- Max column length otherwise: 11
- Max other axis length otherwise: 6.

These are further fixes on top of #705 

Future features can be added to make the limits user configurable, but it is not
a priority to do that before the next release.


Patch:
diff --git a/parallel/src/lib.rs b/parallel/src/lib.rs
index f16cec19..86b5da4c 100644
--- a/parallel/src/lib.rs
+++ b/parallel/src/lib.rs
@@ -64,29 +64,6 @@
 //! }
 //! ```
 //!
-//! ## Axis chunks iterators
-//!
-//! Use the parallel `.axis_chunks_iter()` to process your data in chunks.
-//!
-//! ```
-//! extern crate ndarray;
-//!
-//! use ndarray::Array;
-//! use ndarray::Axis;
-//! use ndarray_parallel::prelude::*;
-//!
-//! fn main() {
-//!     let a = Array::linspace(0., 63., 64).into_shape((4, 16)).unwrap();
-//!     let mut shapes = Vec::new();
-//!     a.axis_chunks_iter(Axis(0), 3)
-//!      .into_par_iter()
-//!      .map(|chunk| chunk.shape().to_owned())
-//!      .collect_into_vec(&mut shapes);
-//!
-//!     assert_eq!(shapes, [vec![3, 16], vec![1, 16]]);
-//! }
-//! ```
-//!
 //! ## Zip
 //!
 //! Use zip for lock step function application across several arrays
diff --git a/parallel/src/par.rs b/parallel/src/par.rs
index f0bc50de..04bfdd07 100644
--- a/parallel/src/par.rs
+++ b/parallel/src/par.rs
@@ -8,8 +8,6 @@ use rayon::iter::plumbing::{Consumer, UnindexedConsumer};
 use rayon::iter::IndexedParallelIterator;
 use rayon::iter::ParallelIterator;
 
-use ndarray::iter::AxisChunksIter;
-use ndarray::iter::AxisChunksIterMut;
 use ndarray::iter::AxisIter;
 use ndarray::iter::AxisIterMut;
 use ndarray::Dimension;
@@ -114,8 +112,6 @@ macro_rules! par_iter_wrapper {
 
 par_iter_wrapper!(AxisIter, [Sync]);
 par_iter_wrapper!(AxisIterMut, [Send + Sync]);
-par_iter_wrapper!(AxisChunksIter, [Sync]);
-par_iter_wrapper!(AxisChunksIterMut, [Send + Sync]);
 
 macro_rules! par_iter_view_wrapper {
     // thread_bounds are either Sync or Send + Sync
diff --git a/src/arrayformat.rs b/src/arrayformat.rs
index 42575307..d1b5ba7f 100644
--- a/src/arrayformat.rs
+++ b/src/arrayformat.rs
@@ -5,23 +5,64 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-use super::{ArrayBase, Axis, Data, Dimension, Ix, NdProducer};
-use crate::aliases::Ix1;
+use super::{ArrayBase, ArrayView, Axis, Data, Dimension, NdProducer};
+use crate::aliases::{Ix1, IxDyn};
 use std::fmt;
 
-/// Default maximum axis length before overflowing with an ellipsis.
-const AXIS_LEN_LIMIT: Ix = 6;
+/// Default threshold, below this element count, we don't ellipsize
+const ARRAY_MANY_ELEMENT_LIMIT: usize = 500;
+/// Limit of element count for non-last axes before overflowing with an ellipsis.
+const AXIS_LIMIT_STACKED: usize = 6;
+/// Limit for next to last axis (printed as column)
+/// An odd number because one element uses the same space as the ellipsis.
+const AXIS_LIMIT_COL: usize = 11;
+/// Limit for last axis (printed as row)
+/// An odd number because one element uses approximately the space of the ellipsis.
+const AXIS_LIMIT_ROW: usize = 11;
+
+#[cfg(test)]
+// Test value to use for size of overflowing 2D arrays
+const AXIS_2D_OVERFLOW_LIMIT: usize = 22;
 
 /// The string used as an ellipsis.
 const ELLIPSIS: &str = "...";
 
-/// Returns the axis length limit based on whether or not the alternate (`#`)
-/// flag was specified on the formatter.
-fn axis_len_limit(f: &mut fmt::Formatter<'_>) -> usize {
-    if f.alternate() {
-        std::usize::MAX
-    } else {
-        AXIS_LEN_LIMIT
+#[derive(Clone, Debug)]
+struct FormatOptions {
+    axis_collapse_limit: usize,
+    axis_collapse_limit_next_last: usize,
+    axis_collapse_limit_last: usize,
+}
+
+impl FormatOptions {
+    pub(crate) fn default_for_array(nelem: usize, no_limit: bool) -> Self {
+        let default = Self {
+            axis_collapse_limit: AXIS_LIMIT_STACKED,
+            axis_collapse_limit_next_last: AXIS_LIMIT_COL,
+            axis_collapse_limit_last: AXIS_LIMIT_ROW,
+        };
+        default.set_no_limit(no_limit || nelem < ARRAY_MANY_ELEMENT_LIMIT)
+    }
+
+    fn set_no_limit(mut self, no_limit: bool) -> Self {
+        if no_limit {
+            self.axis_collapse_limit = std::usize::MAX;
+            self.axis_collapse_limit_next_last = std::usize::MAX;
+            self.axis_collapse_limit_last = std::usize::MAX;
+            self
+        } else {
+            self
+        }
+    }
+
+    /// Axis length collapse limit before ellipsizing, where `axis_rindex` is
+    /// the index of the axis from the back.
+    pub(crate) fn collapse_limit(&self, axis_rindex: usize) -> usize {
+        match axis_rindex {
+            0 => self.axis_collapse_limit_last,
+            1 => self.axis_collapse_limit_next_last,
+            _ => self.axis_collapse_limit,
+        }
     }
 }
 
@@ -37,17 +78,14 @@ fn axis_len_limit(f: &mut fmt::Formatter<'_>) -> usize {
 /// * `ellipsis`: Ellipsis for indicating overflow.
 /// * `fmt_elem`: A function that formats an element in the list, given the
 ///   formatter and the index of the item in the list.
-fn format_with_overflow<F>(
+fn format_with_overflow(
     f: &mut fmt::Formatter<'_>,
     length: usize,
     limit: usize,
     separator: &str,
     ellipsis: &str,
-    mut fmt_elem: F,
-) -> fmt::Result
-where
-    F: FnMut(&mut fmt::Formatter<'_>, usize) -> fmt::Result,
-{
+    fmt_elem: &mut dyn FnMut(&mut fmt::Formatter, usize) -> fmt::Result,
+) -> fmt::Result {
     if length == 0 {
         // no-op
     } else if length <= limit {
@@ -74,53 +112,71 @@ where
 }
 
 fn format_array<A, S, D, F>(
-    view: &ArrayBase<S, D>,
+    array: &ArrayBase<S, D>,
     f: &mut fmt::Formatter<'_>,
-    mut format: F,
-    limit: Ix,
-    depth: usize,
+    format: F,
+    fmt_opt: &FormatOptions,
 ) -> fmt::Result
 where
     F: FnMut(&A, &mut fmt::Formatter<'_>) -> fmt::Result + Clone,
     D: Dimension,
     S: Data<Elem = A>,
+{
+    // Cast into a dynamically dimensioned view
+    // This is required to be able to use `index_axis` for the recursive case
+    format_array_inner(array.view().into_dyn(), f, format, fmt_opt, 0, array.ndim())
+}
+
+fn format_array_inner<A, F>(
+    view: ArrayView<A, IxDyn>,
+    f: &mut fmt::Formatter<'_>,
+    mut format: F,
+    fmt_opt: &FormatOptions,
+    depth: usize,
+    full_ndim: usize,
+) -> fmt::Result
+where
+    F: FnMut(&A, &mut fmt::Formatter<'_>) -> fmt::Result + Clone,
 {
     // If any of the axes has 0 length, we return the same empty array representation
     // e.g. [[]] for 2-d arrays
-    if view.shape().iter().any(|&x| x == 0) {
+    if view.is_empty() {
         write!(f, "{}{}", "[".repeat(view.ndim()), "]".repeat(view.ndim()))?;
         return Ok(());
     }
     match view.shape() {
         // If it's 0 dimensional, we just print out the scalar
-        &[] => format(view.iter().next().unwrap(), f)?,
+        &[] => format(&view[[]], f)?,
         // We handle 1-D arrays as a special case
         &[len] => {
             let view = view.view().into_dimensionality::<Ix1>().unwrap();
             f.write_str("[")?;
-            format_with_overflow(f, len, limit, ", ", ELLIPSIS, |f, index| {
-                format(&view[index], f)
-            })?;
+            format_with_overflow(
+                f,
+                len,
+                fmt_opt.collapse_limit(0),
+                ", ",
+                ELLIPSIS,
+                &mut |f, index| format(&view[index], f),
+            )?;
             f.write_str("]")?;
         }
         // For n-dimensional arrays, we proceed recursively
         shape => {
-            // Cast into a dynamically dimensioned view
-            // This is required to be able to use `index_axis`
-            let view = view.view().into_dyn();
-
             let blank_lines = "\n".repeat(shape.len() - 2);
             let indent = " ".repeat(depth + 1);
             let separator = format!(",\n{}{}", blank_lines, indent);
 
             f.write_str("[")?;
-            format_with_overflow(f, shape[0], limit, &separator, ELLIPSIS, |f, index| {
-                format_array(
-                    &view.index_axis(Axis(0), index),
+            let limit = fmt_opt.collapse_limit(full_ndim - depth - 1);
+            format_with_overflow(f, shape[0], limit, &separator, ELLIPSIS, &mut |f, index| {
+                format_array_inner(
+                    view.index_axis(Axis(0), index),
                     f,
                     format.clone(),
-                    limit,
+                    fmt_opt,
                     depth + 1,
+                    full_ndim,
                 )
             })?;
             f.write_str("]")?;
@@ -139,8 +195,8 @@ where
     S: Data<Elem = A>,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let limit = axis_len_limit(f);
-        format_array(self, f, <_>::fmt, limit, 0)
+        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
+        format_array(self, f, <_>::fmt, &fmt_opt)
     }
 }
 
@@ -153,8 +209,8 @@ where
     S: Data<Elem = A>,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let limit = axis_len_limit(f);
-        format_array(self, f, <_>::fmt, limit, 0)?;
+        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
+        format_array(self, f, <_>::fmt, &fmt_opt)?;
 
         // Add extra information for Debug
         write!(
@@ -181,8 +237,8 @@ where
     S: Data<Elem = A>,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let limit = axis_len_limit(f);
-        format_array(self, f, <_>::fmt, limit, 0)
+        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
+        format_array(self, f, <_>::fmt, &fmt_opt)
     }
 }
 
@@ -195,8 +251,8 @@ where
     S: Data<Elem = A>,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let limit = axis_len_limit(f);
-        format_array(self, f, <_>::fmt, limit, 0)
+        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
+        format_array(self, f, <_>::fmt, &fmt_opt)
     }
 }
 /// Format the array using `LowerHex` and apply the formatting parameters used
@@ -208,8 +264,8 @@ where
     S: Data<Elem = A>,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let limit = axis_len_limit(f);
-        format_array(self, f, <_>::fmt, limit, 0)
+        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
+        format_array(self, f, <_>::fmt, &fmt_opt)
     }
 }
 
@@ -222,24 +278,50 @@ where
     S: Data<Elem = A>,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let limit = axis_len_limit(f);
-        format_array(self, f, <_>::fmt, limit, 0)
+        let fmt_opt = FormatOptions::default_for_array(self.len(), f.alternate());
+        format_array(self, f, <_>::fmt, &fmt_opt)
     }
 }
 
 #[cfg(test)]
 mod formatting_with_omit {
+    use itertools::Itertools;
+    use std::fmt;
+
     use super::*;
     use crate::prelude::*;
 
     fn assert_str_eq(expected: &str, actual: &str) {
-        assert_eq!(
-            expected, actual,
-            "\nexpected:\n{}\nactual:\n{}\n",
-            expected, actual,
+        // use assert to avoid printing the strings twice on failure
+        assert!(
+            expected == actual,
+            "formatting assertion failed\nexpected:\n{}\nactual:\n{}\n",
+            expected,
+            actual,
         );
     }
 
+    fn ellipsize(
+        limit: usize,
+        sep: &str,
+        elements: impl IntoIterator<Item = impl fmt::Display>,
+    ) -> String {
+        let elements = elements.into_iter().collect::<Vec<_>>();
+        let edge = limit / 2;
+        if elements.len() <= limit {
+            format!("{}", elements.iter().format(sep))
+        } else {
+            format!(
+                "{}{}{}{}{}",
+                elements[..edge].iter().format(sep),
+                sep,
+                ELLIPSIS,
+                sep,
+                elements[elements.len() - edge..].iter().format(sep)
+            )
+        }
+    }
+
     #[test]
     fn empty_arrays() {
         let a: Array2<u32> = arr2(&[[], []]);
@@ -268,494 +350,358 @@ mod formatting_with_omit {
     #[test]
     fn dim_1() {
         let overflow: usize = 2;
-        let a = Array1::from_elem(AXIS_LEN_LIMIT + overflow, 1);
+        let a = Array1::from_elem(ARRAY_MANY_ELEMENT_LIMIT + overflow, 1);
         let actual = format!("{}", a);
-        let expected = "[1, 1, 1, ..., 1, 1, 1]";
-        assert_str_eq(expected, &actual);
+        let expected = format!("[{}]", ellipsize(AXIS_LIMIT_ROW, ", ", a.iter()));
+        assert_str_eq(&expected, &actual);
     }
 
     #[test]
     fn dim_1_alternate() {
         let overflow: usize = 2;
-        let a = Array1::from_elem(AXIS_LEN_LIMIT + overflow, 1);
+        let a = Array1::from_elem(ARRAY_MANY_ELEMENT_LIMIT + overflow, 1);
         let actual = format!("{:#}", a);
-        let expected = "[1, 1, 1, 1, 1, 1, 1, 1]";
-        assert_str_eq(expected, &actual);
+        let expected = format!("[{}]", a.iter().format(", "));
+        assert_str_eq(&expected, &actual);
     }
 
     #[test]
     fn dim_2_last_axis_overflow() {
         let overflow: usize = 2;
-        let a = Array2::from_elem((AXIS_LEN_LIMIT, AXIS_LEN_LIMIT + overflow), 1);
+        let a = Array2::from_elem(
+            (AXIS_2D_OVERFLOW_LIMIT, AXIS_2D_OVERFLOW_LIMIT + overflow),
+            1,
+        );
         let actual = format!("{}", a);
         let expected = "\
-[[1, 1, 1, ..., 1, 1, 1],
- [1, 1, 1, ..., 1, 1, 1],
- [1, 1, 1, ..., 1, 1, 1],
- [1, 1, 1, ..., 1, 1, 1],
- [1, 1, 1, ..., 1, 1, 1],
- [1, 1, 1, ..., 1, 1, 1]]";
-        assert_str_eq(expected, &actual);
-    }
-
-    #[test]
-    fn dim_2_last_axis_overflow_alternate() {
-        let overflow: usize = 2;
-        let a = Array2::from_elem((AXIS_LEN_LIMIT, AXIS_LEN_LIMIT + overflow), 1);
-        let actual = format!("{:#}", a);
-        let expected = "\
-[[1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1]]";
+[[1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
+ ...,
+ [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, ..., 1, 1, 1, 1, 1]]";
         assert_str_eq(expected, &actual);
     }
 
     #[test]
     fn dim_2_non_last_axis_overflow() {
-        let overflow: usize = 2;
-        let a = Array2::from_elem((AXIS_LEN_LIMIT + overflow, AXIS_LEN_LIMIT), 1);
+        let a = Array2::from_elem((ARRAY_MANY_ELEMENT_LIMIT / 10, 10), 1);
         let actual = format!("{}", a);
-        let expected = "\
-[[1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1],
- ...,
- [1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1]]";
-        assert_str_eq(expected, &actual);
+        let row = format!("{}", a.row(0));
+        let expected = format!(
+            "[{}]",
+            ellipsize(AXIS_LIMIT_COL, ",\n ", (0..a.nrows()).map(|_| &row))
+        );
+        assert_str_eq(&expected, &actual);
     }
 
     #[test]
     fn dim_2_non_last_axis_overflow_alternate() {
-        let overflow: usize = 2;
-        let a = Array2::from_elem((AXIS_LEN_LIMIT + overflow, AXIS_LEN_LIMIT), 1);
+        let a = Array2::from_elem((AXIS_LIMIT_COL * 4, 6), 1);
         let actual = format!("{:#}", a);
-        let expected = "\
-[[1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1]]";
-        assert_str_eq(expected, &actual);
+        let row = format!("{}", a.row(0));
+        let expected = format!("[{}]", (0..a.nrows()).map(|_| &row).format(",\n "));
+        assert_str_eq(&expected, &actual);
     }
 
     #[test]
     fn dim_2_multi_directional_overflow() {
         let overflow: usize = 2;
-        let a = Array2::from_elem((AXIS_LEN_LIMIT + overflow, AXIS_LEN_LIMIT + overflow), 1);
+        let a = Array2::from_elem(
+            (
+                AXIS_2D_OVERFLOW_LIMIT + overflow,
+                AXIS_2D_OVERFLOW_LIMIT + overflow,
+            ),
+            1,
+        );
         let actual = format!("{}", a);
-        let expected = "\
-[[1, 1, 1, ..., 1, 1, 1],
- [1, 1, 1, ..., 1, 1, 1],
- [1, 1, 1, ..., 1, 1, 1],
- ...,
- [1, 1, 1, ..., 1, 1, 1],
- [1, 1, 1, ..., 1, 1, 1],
- [1, 1, 1, ..., 1, 1, 1]]";
-        assert_str_eq(expected, &actual);
+        let row = format!("[{}]", ellipsize(AXIS_LIMIT_ROW, ", ", a.row(0)));
+        let expected = format!(
+            "[{}]",
+            ellipsize(AXIS_LIMIT_COL, ",\n ", (0..a.nrows()).map(|_| &row))
+        );
+        assert_str_eq(&expected, &actual);
     }
 
     #[test]
     fn dim_2_multi_directional_overflow_alternate() {
         let overflow: usize = 2;
-        let a = Array2::from_elem((AXIS_LEN_LIMIT + overflow, AXIS_LEN_LIMIT + overflow), 1);
+        let a = Array2::from_elem(
+            (
+                AXIS_2D_OVERFLOW_LIMIT + overflow,
+                AXIS_2D_OVERFLOW_LIMIT + overflow,
+            ),
+            1,
+        );
         let actual = format!("{:#}", a);
+        let row = format!("{}", a.row(0));
+        let expected = format!("[{}]", (0..a.nrows()).map(|_| &row).format(",\n "));
+        assert_str_eq(&expected, &actual);
+    }
+
+    #[test]
+    fn dim_3_overflow_most() {
+        let a = Array3::from_shape_fn(
+            (AXIS_LIMIT_STACKED + 1, AXIS_LIMIT_COL, AXIS_LIMIT_ROW + 1),
+            |(i, j, k)| {
+                1000. + (100. * ((i as f64).sqrt() + (j as f64).sin() + k as f64)).round() / 100.
+            },
+        );
+        let actual = format!("{:6.1}", a);
         let expected = "\
-[[1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1],
- [1, 1, 1, 1, 1, 1, 1, 1]]";
+[[[1000.0, 1001.0, 1002.0, 1003.0, 1004.0, ..., 1007.0, 1008.0, 1009.0, 1010.0, 1011.0],
+  [1000.8, 1001.8, 1002.8, 1003.8, 1004.8, ..., 1007.8, 1008.8, 1009.8, 1010.8, 1011.8],
+  [1000.9, 1001.9, 1002.9, 1003.9, 1004.9, ..., 1007.9, 1008.9, 1009.9, 1010.9, 1011.9],
+  [1000.1, 1001.1, 1002.1, 1003.1, 1004.1, ..., 1007.1, 1008.1, 1009.1, 1010.1, 1011.1],
+  [ 999.2, 1000.2, 1001.2, 1002.2, 1003.2, ..., 1006.2, 1007.2, 1008.2, 1009.2, 1010.2],
+  [ 999.0, 1000.0, 1001.0, 1002.0, 1003.0, ..., 1006.0, 1007.0, 1008.0, 1009.0, 1010.0],
+  [ 999.7, 1000.7, 1001.7, 1002.7, 1003.7, ..., 1006.7, 1007.7, 1008.7, 1009.7, 1010.7],
+  [1000.7, 1001.7, 1002.7, 1003.7, 1004.7, ..., 1007.7, 1008.7, 1009.7, 1010.7, 1011.7],
+  [1001.0, 1002.0, 1003.0, 1004.0, 1005.0, ..., 1008.0, 1009.0, 1010.0, 1011.0, 1012.0],
+  [1000.4, 1001.4, 1002.4, 1003.4, 1004.4, ..., 1007.4, 1008.4, 1009.4, 1010.4, 1011.4],
+  [ 999.5, 1000.5, 1001.5, 1002.5, 1003.5, ..., 1006.5, 1007.5, 1008.5, 1009.5, 1010.5]],
+
+ [[1001.0, 1002.0, 1003.0, 1004.0, 1005.0, ..., 1008.0, 1009.0, 1010.0, 1011.0, 1012.0],
+  [1001.8, 1002.8, 1003.8, 1004.8, 1005.8, ..., 1008.8, 1009.8, 1010.8, 1011.8, 1012.8],
+  [1001.9, 1002.9, 1003.9, 1004.9, 1005.9, ..., 1008.9, 1009.9, 1010.9, 1011.9, 1012.9],
+  [1001.1, 1002.1, 1003.1, 1004.1, 1005.1, ..., 1008.1, 1009.1, 1010.1, 1011.1, 1012.1],
+  [1000.2, 1001.2, 1002.2, 1003.2, 1004.2, ..., 1007.2, 1008.2, 1009.2, 1010.2, 1011.2],
+  [1000.0, 1001.0, 1002.0, 1003.0, 1004.0, ..., 1007.0, 1008.0, 1009.0, 1010.0, 1011.0],
+  [1000.7, 1001.7, 1002.7, 1003.7, 1004.7, ..., 1007.7, 1008.7, 1009.7, 1010.7, 1011.7],
+  [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7],
+  [1002.0, 1003.0, 1004.0, 1005.0, 1006.0, ..., 1009.0, 1010.0, 1011.0, 1012.0, 1013.0],
+  [1001.4, 1002.4, 1003.4, 1004.4, 1005.4, ..., 1008.4, 1009.4, 1010.4, 1011.4, 1012.4],
+  [1000.5, 1001.5, 1002.5, 1003.5, 1004.5, ..., 1007.5, 1008.5, 1009.5, 1010.5, 1011.5]],
+
+ [[1001.4, 1002.4, 1003.4, 1004.4, 1005.4, ..., 1008.4, 1009.4, 1010.4, 1011.4, 1012.4],
+  [1002.3, 1003.3, 1004.3, 1005.3, 1006.3, ..., 1009.3, 1010.3, 1011.3, 1012.3, 1013.3],
+  [1002.3, 1003.3, 1004.3, 1005.3, 1006.3, ..., 1009.3, 1010.3, 1011.3, 1012.3, 1013.3],
+  [1001.6, 1002.6, 1003.6, 1004.6, 1005.6, ..., 1008.6, 1009.6, 1010.6, 1011.6, 1012.6],
+  [1000.7, 1001.7, 1002.7, 1003.7, 1004.7, ..., 1007.7, 1008.7, 1009.7, 1010.7, 1011.7],
+  [1000.5, 1001.5, 1002.5, 1003.5, 1004.5, ..., 1007.5, 1008.5, 1009.5, 1010.5, 1011.5],
+  [1001.1, 1002.1, 1003.1, 1004.1, 1005.1, ..., 1008.1, 1009.1, 1010.1, 1011.1, 1012.1],
+  [1002.1, 1003.1, 1004.1, 1005.1, 1006.1, ..., 1009.1, 1010.1, 1011.1, 1012.1, 1013.1],
+  [1002.4, 1003.4, 1004.4, 1005.4, 1006.4, ..., 1009.4, 1010.4, 1011.4, 1012.4, 1013.4],
+  [1001.8, 1002.8, 1003.8, 1004.8, 1005.8, ..., 1008.8, 1009.8, 1010.8, 1011.8, 1012.8],
+  [1000.9, 1001.9, 1002.9, 1003.9, 1004.9, ..., 1007.9, 1008.9, 1009.9, 1010.9, 1011.9]],
+
+ ...,
+
+ [[1002.0, 1003.0, 1004.0, 1005.0, 1006.0, ..., 1009.0, 1010.0, 1011.0, 1012.0, 1013.0],
+  [1002.8, 1003.8, 1004.8, 1005.8, 1006.8, ..., 1009.8, 1010.8, 1011.8, 1012.8, 1013.8],
+  [1002.9, 1003.9, 1004.9, 1005.9, 1006.9, ..., 1009.9, 1010.9, 1011.9, 1012.9, 1013.9],
+  [1002.1, 1003.1, 1004.1, 1005.1, 1006.1, ..., 1009.1, 1010.1, 1011.1, 1012.1, 1013.1],
+  [1001.2, 1002.2, 1003.2, 1004.2, 1005.2, ..., 1008.2, 1009.2, 1010.2, 1011.2, 1012.2],
+  [1001.0, 1002.0, 1003.0, 1004.0, 1005.0, ..., 1008.0, 1009.0, 1010.0, 1011.0, 1012.0],
+  [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7],
+  [1002.7, 1003.7, 1004.7, 1005.7, 1006.7, ..., 1009.7, 1010.7, 1011.7, 1012.7, 1013.7],
+  [1003.0, 1004.0, 1005.0, 1006.0, 1007.0, ..., 1010.0, 1011.0, 1012.0, 1013.0, 1014.0],
+  [1002.4, 1003.4, 1004.4, 1005.4, 1006.4, ..., 1009.4, 1010.4, 1011.4, 1012.4, 1013.4],
+  [1001.5, 1002.5, 1003.5, 1004.5, 1005.5, ..., 1008.5, 1009.5, 1010.5, 1011.5, 1012.5]],
+
+ [[1002.2, 1003.2, 1004.2, 1005.2, 1006.2, ..., 1009.2, 1010.2, 1011.2, 1012.2, 1013.2],
+  [1003.1, 1004.1, 1005.1, 1006.1, 1007.1, ..., 1010.1, 1011.1, 1012.1, 1013.1, 1014.1],
+  [1003.1, 1004.1, 1005.1, 1006.1, 1007.1, ..., 1010.1, 1011.1, 1012.1, 1013.1, 1014.1],
+  [1002.4, 1003.4, 1004.4, 1005.4, 1006.4, ..., 1009.4, 1010.4, 1011.4, 1012.4, 1013.4],
+  [1001.5, 1002.5, 1003.5, 1004.5, 1005.5, ..., 1008.5, 1009.5, 1010.5, 1011.5, 1012.5],
+  [1001.3, 1002.3, 1003.3, 1004.3, 1005.3, ..., 1008.3, 1009.3, 1010.3, 1011.3, 1012.3],
+  [1002.0, 1003.0, 1004.0, 1005.0, 1006.0, ..., 1009.0, 1010.0, 1011.0, 1012.0, 1013.0],
+  [1002.9, 1003.9, 1004.9, 1005.9, 1006.9, ..., 1009.9, 1010.9, 1011.9, 1012.9, 1013.9],
+  [1003.2, 1004.2, 1005.2, 1006.2, 1007.2, ..., 1010.2, 1011.2, 1012.2, 1013.2, 1014.2],
+  [1002.6, 1003.6, 1004.6, 1005.6, 1006.6, ..., 1009.6, 1010.6, 1011.6, 1012.6, 1013.6],
+  [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7]],
+
+ [[1002.5, 1003.5, 1004.5, 1005.5, 1006.5, ..., 1009.5, 1010.5, 1011.5, 1012.5, 1013.5],
+  [1003.3, 1004.3, 1005.3, 1006.3, 1007.3, ..., 1010.3, 1011.3, 1012.3, 1013.3, 1014.3],
+  [1003.4, 1004.4, 1005.4, 1006.4, 1007.4, ..., 1010.4, 1011.4, 1012.4, 1013.4, 1014.4],
+  [1002.6, 1003.6, 1004.6, 1005.6, 1006.6, ..., 1009.6, 1010.6, 1011.6, 1012.6, 1013.6],
+  [1001.7, 1002.7, 1003.7, 1004.7, 1005.7, ..., 1008.7, 1009.7, 1010.7, 1011.7, 1012.7],
+  [1001.5, 1002.5, 1003.5, 1004.5, 1005.5, ..., 1008.5, 1009.5, 1010.5, 1011.5, 1012.5],
+  [1002.2, 1003.2, 1004.2, 1005.2, 1006.2, ..., 1009.2, 1010.2, 1011.2, 1012.2, 1013.2],
+  [1003.1, 1004.1, 1005.1, 1006.1, 1007.1, ..., 1010.1, 1011.1, 1012.1, 1013.1, 1014.1],
+  [1003.4, 1004.4, 1005.4, 1006.4, 1007.4, ..., 1010.4, 1011.4, 1012.4, 1013.4, 1014.4],
+  [1002.9, 1003.9, 1004.9, 1005.9, 1006.9, ..., 1009.9, 1010.9, 1011.9, 1012.9, 1013.9],
+  [1001.9, 1002.9, 1003.9, 1004.9, 1005.9, ..., 1008.9, 1009.9, 1010.9, 1011.9, 1012.9]]]";
         assert_str_eq(expected, &actual);
     }
 
     #[test]
-    fn dim_3_overflow_all() {
-        let a = Array3::from_shape_fn((20, 10, 7), |(i, j, k)| {
-            1000. + (100. * ((i as f64).sqrt() + (j as f64).sin() + k as f64)).round() / 100.
-        });
-        let actual = format!("{:.2}", a);
-        // Generated using NumPy with `np.set_printoptions(suppress=True, floatmode='maxprec_equal')`.
+    fn dim_4_overflow_outer() {
+        let a = Array4::from_shape_fn((10, 10, 3, 3), |(i, j, k, l)| i + j + k + l);
+        let actual = format!("{:2}", a);
+        // Generated using NumPy with:
+        // np.set_printoptions(threshold=500, edgeitems=3)
+        // np.fromfunction(lambda i, j, k, l: i + j + k + l, (10, 10, 3, 3), dtype=int)
+        //
         let expected = "\
-[[[1000.00, 1001.00, 1002.00, ..., 1004.00, 1005.00, 1006.00],
-  [1000.84, 1001.84, 1002.84, ..., 1004.84, 1005.84, 1006.84],
-  [1000.91, 1001.91, 1002.91, ..., 1004.91, 1005.91, 1006.91],
-  ...,
-  [1000.66, 1001.66, 1002.66, ..., 1004.66, 1005.66, 1006.66],
-  [1000.99, 1001.99, 1002.99, ..., 1004.99, 1005.99, 1006.99],
-  [1000.41, 1001.41, 1002.41, ..., 1004.41, 1005.41, 1006.41]],
+[[[[ 0,  1,  2],
+   [ 1,  2,  3],
+   [ 2,  3,  4]],
 
- [[1001.00, 1002.00, 1003.00, ..., 1005.00, 1006.00, 1007.00],
-  [1001.84, 1002.84, 1003.84, ..., 1005.84, 1006.84, 1007.84],
-  [1001.91, 1002.91, 1003.91, ..., 1005.91, 1006.91, 1007.91],
-  ...,
-  [1001.66, 1002.66, 1003.66, ..., 1005.66, 1006.66, 1007.66],
-  [1001.99, 1002.99, 1003.99, ..., 1005.99, 1006.99, 1007.99],
-  [1001.41, 1002.41, 1003.41, ..., 1005.41, 1006.41, 1007.41]],
+  [[ 1,  2,  3],
+   [ 2,  3,  4],
+   [ 3,  4,  5]],
+
+  [[ 2,  3,  4],
+   [ 3,  4,  5],
+   [ 4,  5,  6]],
 
- [[1001.41, 1002.41, 1003.41, ..., 1005.41, 1006.41, 1007.41],
-  [1002.26, 1003.26, 1004.26, ..., 1006.26, 1007.26, 1008.26],
-  [1002.32, 1003.32, 1004.32, ..., 1006.32, 1007.32, 1008.32],
   ...,
-  [1002.07, 1003.07, 1004.07, ..., 1006.07, 1007.07, 1008.07],
-  [1002.40, 1003.40, 1004.40, ..., 1006.40, 1007.40, 1008.40],
-  [1001.83, 1002.83, 1003.83, ..., 1005.83, 1006.83, 1007.83]],
 
- ...,
+  [[ 7,  8,  9],
+   [ 8,  9, 10],
+   [ 9, 10, 11]],
 
- [[1004.12, 1005.12, 1006.12, ..., 1008.12, 1009.12, 1010.12],
-  [1004.96, 1005.96, 1006.96, ..., 1008.96, 1009.96, 1010.96],
-  [1005.03, 1006.03, 1007.03, ..., 1009.03, 1010.03, 1011.03],
-  ...,
-  [1004.78, 1005.78, 1006.78, ..., 1008.78, 1009.78, 1010.78],
-  [1005.11, 1006.11, 1007.11, ..., 1009.11, 1010.11, 1011.11],
-  [1004.54, 1005.54, 1006.54, ..., 1008.54, 1009.54, 1010.54]],
+  [[ 8,  9, 10],
+   [ 9, 10, 11],
+   [10, 11, 12]],
 
- [[1004.24, 1005.24, 1006.24, ..., 1008.24, 1009.24, 1010.24],
-  [1005.08, 1006.08, 1007.08, ..., 1009.08, 1010.08, 1011.08],
-  [1005.15, 1006.15, 1007.15, ..., 1009.15, 1010.15, 1011.15],
-  ...,
-  [1004.90, 1005.90, 1006.90, ..., 1008.90, 1009.90, 1010.90],
-  [1005.23, 1006.23, 1007.23, ..., 1009.23, 1010.23, 1011.23],
-  [1004.65, 1005.65, 1006.65, ..., 1008.65, 1009.65, 1010.65]],
+  [[ 9, 10, 11],
+   [10, 11, 12],
+   [11, 12, 13]]],
 
- [[1004.36, 1005.36, 1006.36, ..., 1008.36, 1009.36, 1010.36],
-  [1005.20, 1006.20, 1007.20, ..., 1009.20, 1010.20, 1011.20],
-  [1005.27, 1006.27, 1007.27, ..., 1009.27, 1010.27, 1011.27],
-  ...,
-  [1005.02, 1006.02, 1007.02, ..., 1009.02, 1010.02, 1011.02],
-  [1005.35, 1006.35, 1007.35, ..., 1009.35, 1010.35, 1011.35],
-  [1004.77, 1005.77, 1006.77, ..., 1008.77, 1009.77, 1010.77]]]";
-        assert_str_eq(expected, &actual);
-    }
 
-    #[test]
-    fn dim_4_overflow_all() {
-        let a = Array4::from_shape_fn((20, 10, 7, 8), |(i, j, k, l)| {
-            (100. * ((i as f64).sqrt() + (j as f64).exp() + (k as f64).sin() + l as f64)).round()
-                / 100.
-                + 1000.
-        });
-        let actual = format!("{:.2}", a);
-        // Generated using NumPy with `np.set_printoptions(suppress=True, floatmode='maxprec_equal')`.
-        let expected = "\
-[[[[1001.00, 1002.00, 1003.00, ..., 1006.00, 1007.00, 1008.00],
-   [1001.84, 1002.84, 1003.84, ..., 1006.84, 1007.84, 1008.84],
-   [1001.91, 1002.91, 1003.91, ..., 1006.91, 1007.91, 1008.91],
-   ...,
-   [1000.24, 1001.24, 1002.24, ..., 1005.24, 1006.24, 1007.24],
-   [1000.04, 1001.04, 1002.04, ..., 1005.04, 1006.04, 1007.04],
-   [1000.72, 1001.72, 1002.72, ..., 1005.72, 1006.72, 1007.72]],
-
-  [[1002.72, 1003.72, 1004.72, ..., 1007.72, 1008.72, 1009.72],
-   [1003.56, 1004.56, 1005.56, ..., 1008.56, 1009.56, 1010.56],
-   [1003.63, 1004.63, 1005.63, ..., 1008.63, 1009.63, 1010.63],
-   ...,
-   [1001.96, 1002.96, 1003.96, ..., 1006.96, 1007.96, 1008.96],
-   [1001.76, 1002.76, 1003.76, ..., 1006.76, 1007.76, 1008.76],
-   [1002.44, 1003.44, 1004.44, ..., 1007.44, 1008.44, 1009.44]],
-
-  [[1007.39, 1008.39, 1009.39, ..., 1012.39, 1013.39, 1014.39],
-   [1008.23, 1009.23, 1010.23, ..., 1013.23, 1014.23, 1015.23],
-   [1008.30, 1009.30, 1010.30, ..., 1013.30, 1014.30, 1015.30],
-   ...,
-   [1006.63, 1007.63, 1008.63, ..., 1011.63, 1012.63, 1013.63],
-   [1006.43, 1007.43, 1008.43, ..., 1011.43, 1012.43, 1013.43],
-   [1007.11, 1008.11, 1009.11, ..., 1012.11, 1013.11, 1014.11]],
+ [[[ 1,  2,  3],
+   [ 2,  3,  4],
+   [ 3,  4,  5]],
 
-  ...,
+  [[ 2,  3,  4],
+   [ 3,  4,  5],
+   [ 4,  5,  6]],
 
-  [[2096.63, 2097.63, 2098.63, ..., 2101.63, 2102.63, 2103.63],
-   [2097.47, 2098.47, 2099.47, ..., 2102.47, 2103.47, 2104.47],
-   [2097.54, 2098.54, 2099.54, ..., 2102.54, 2103.54, 2104.54],
-   ...,
-   [2095.88, 2096.88, 2097.88, ..., 2100.88, 2101.88, 2102.88],
-   [2095.67, 2096.67, 2097.67, ..., 2100.67, 2101.67, 2102.67],
-   [2096.35, 2097.35, 2098.35, ..., 2101.35, 2102.35, 2103.35]],
-
-  [[3980.96, 3981.96, 3982.96, ..., 3985.96, 3986.96, 3987.96],
-   [3981.80, 3982.80, 3983.80, ..., 3986.80, 3987.80, 3988.80],
-   [3981.87, 3982.87, 3983.87, ..., 3986.87, 3987.87, 3988.87],
-   ...,
-   [3980.20, 3981.20, 3982.20, ..., 3985.20, 3986.20, 3987.20],
-   [3980.00, 3981.00, 3982.00, ..., 3985.00, 3986.00, 3987.00],
-   [3980.68, 3981.68, 3982.68, ..., 3985.68, 3986.68, 3987.68]],
-
-  [[9103.08, 9104.08, 9105.08, ..., 9108.08, 9109.08, 9110.08],
-   [9103.93, 9104.93, 9105.93, ..., 9108.93, 9109.93, 9110.93],
-   [9103.99, 9104.99, 9105.99, ..., 9108.99, 9109.99, 9110.99],
-   ...,
-   [9102.33, 9103.33, 9104.33, ..., 9107.33, 9108.33, 9109.33],
-   [9102.13, 9103.13, 9104.13, ..., 9107.13, 9108.13, 9109.13],
-   [9102.80, 9103.80, 9104.80, ..., 9107.80, 9108.80, 9109.80]]],
-
-
- [[[1002.00, 1003.00, 1004.00, ..., 1007.00, 1008.00, 1009.00],
-   [1002.84, 1003.84, 1004.84, ..., 1007.84, 1008.84, 1009.84],
-   [1002.91, 1003.91, 1004.91, ..., 1007.91, 1008.91, 1009.91],
-   ...,
-   [1001.24, 1002.24, 1003.24, ..., 1006.24, 1007.24, 1008.24],
-   [1001.04, 1002.04, 1003.04, ..., 1006.04, 1007.04, 1008.04],
-   [1001.72, 1002.72, 1003.72, ..., 1006.72, 1007.72, 1008.72]],
-
-  [[1003.72, 1004.72, 1005.72, ..., 1008.72, 1009.72, 1010.72],
-   [1004.56, 1005.56, 1006.56, ..., 1009.56, 1010.56, 1011.56],
-   [1004.63, 1005.63, 1006.63, ..., 1009.63, 1010.63, 1011.63],
-   ...,
-   [1002.96, 1003.96, 1004.96, ..., 1007.96, 1008.96, 1009.96],
-   [1002.76, 1003.76, 1004.76, ..., 1007.76, 1008.76, 1009.76],
-   [1003.44, 1004.44, 1005.44, ..., 1008.44, 1009.44, 1010.44]],
-
-  [[1008.39, 1009.39, 1010.39, ..., 1013.39, 1014.39, 1015.39],
-   [1009.23, 1010.23, 1011.23, ..., 1014.23, 1015.23, 1016.23],
-   [1009.30, 1010.30, 1011.30, ..., 1014.30, 1015.30, 1016.30],
-   ...,
-   [1007.63, 1008.63, 1009.63, ..., 1012.63, 1013.63, 1014.63],
-   [1007.43, 1008.43, 1009.43, ..., 1012.43, 1013.43, 1014.43],
-   [1008.11, 1009.11, 1010.11, ..., 1013.11, 1014.11, 1015.11]],
+  [[ 3,  4,  5],
+   [ 4,  5,  6],
+   [ 5,  6,  7]],
 
   ...,
 
-  [[2097.63, 2098.63, 2099.63, ..., 2102.63, 2103.63, 2104.63],
-   [2098.47, 2099.47, 2100.47, ..., 2103.47, 2104.47, 2105.47],
-   [2098.54, 2099.54, 2100.54, ..., 2103.54, 2104.54, 2105.54],
-   ...,
-   [2096.88, 2097.88, 2098.88, ..., 2101.88, 2102.88, 2103.88],
-   [2096.67, 2097.67, 2098.67, ..., 2101.67, 2102.67, 2103.67],
-   [2097.35, 2098.35, 2099.35, ..., 2102.35, 2103.35, 2104.35]],
-
-  [[3981.96, 3982.96, 3983.96, ..., 3986.96, 3987.96, 3988.96],
-   [3982.80, 3983.80, 3984.80, ..., 3987.80, 3988.80, 3989.80],
-   [3982.87, 3983.87, 3984.87, ..., 3987.87, 3988.87, 3989.87],
-   ...,
-   [3981.20, 3982.20, 3983.20, ..., 3986.20, 3987.20, 3988.20],
-   [3981.00, 3982.00, 3983.00, ..., 3986.00, 3987.00, 3988.00],
-   [3981.68, 3982.68, 3983.68, ..., 3986.68, 3987.68, 3988.68]],
-
-  [[9104.08, 9105.08, 9106.08, ..., 9109.08, 9110.08, 9111.08],
-   [9104.93, 9105.93, 9106.93, ..., 9109.93, 9110.93, 9111.93],
-   [9104.99, 9105.99, 9106.99, ..., 9109.99, 9110.99, 9111.99],
-   ...,
-   [9103.33, 9104.33, 9105.33, ..., 9108.33, 9109.33, 9110.33],
-   [9103.13, 9104.13, 9105.13, ..., 9108.13, 9109.13, 9110.13],
-   [9103.80, 9104.80, 9105.80, ..., 9108.80, 9109.80, 9110.80]]],
-
-
- [[[1002.41, 1003.41, 1004.41, ..., 1007.41, 1008.41, 1009.41],
-   [1003.26, 1004.26, 1005.26, ..., 1008.26, 1009.26, 1010.26],
-   [1003.32, 1004.32, 1005.32, ..., 1008.32, 1009.32, 1010.32],
-   ...,
-   [1001.66, 1002.66, 1003.66, ..., 1006.66, 1007.66, 1008.66],
-   [1001.46, 1002.46, 1003.46, ..., 1006.46, 1007.46, 1008.46],
-   [1002.13, 1003.13, 1004.13, ..., 1007.13, 1008.13, 1009.13]],
-
-  [[1004.13, 1005.13, 1006.13, ..., 1009.13, 1010.13, 1011.13],
-   [1004.97, 1005.97, 1006.97, ..., 1009.97, 1010.97, 1011.97],
-   [1005.04, 1006.04, 1007.04, ..., 1010.04, 1011.04, 1012.04],
-   ...,
-   [1003.38, 1004.38, 1005.38, ..., 1008.38, 1009.38, 1010.38],
-   [1003.17, 1004.17, 1005.17, ..., 1008.17, 1009.17, 1010.17],
-   [1003.85, 1004.85, 1005.85, ..., 1008.85, 1009.85, 1010.85]],
-
-  [[1008.80, 1009.80, 1010.80, ..., 1013.80, 1014.80, 1015.80],
-   [1009.64, 1010.64, 1011.64, ..., 1014.64, 1015.64, 1016.64],
-   [1009.71, 1010.71, 1011.71, ..., 1014.71, 1015.71, 1016.71],
-   ...,
-   [1008.05, 1009.05, 1010.05, ..., 1013.05, 1014.05, 1015.05],
-   [1007.84, 1008.84, 1009.84, ..., 1012.84, 1013.84, 1014.84],
-   [1008.52, 1009.52, 1010.52, ..., 1013.52, 1014.52, 1015.52]],
+  [[ 8,  9, 10],
+   [ 9, 10, 11],
+   [10, 11, 12]],
+
+  [[ 9, 10, 11],
+   [10, 11, 12],
+   [11, 12, 13]],
+
+  [[10, 11, 12],
+   [11, 12, 13],
+   [12, 13, 14]]],
+
+
+ [[[ 2,  3,  4],
+   [ 3,  4,  5],
+   [ 4,  5,  6]],
+
+  [[ 3,  4,  5],
+   [ 4,  5,  6],
+   [ 5,  6,  7]],
+
+  [[ 4,  5,  6],
+   [ 5,  6,  7],
+   [ 6,  7,  8]],
 
   ...,
 
-  [[2098.05, 2099.05, 2100.05, ..., 2103.05, 2104.05, 2105.05],
-   [2098.89, 2099.89, 2100.89, ..., 2103.89, 2104.89, 2105.89],
-   [2098.96, 2099.96, 2100.96, ..., 2103.96, 2104.96, 2105.96],
-   ...,
-   [2097.29, 2098.29, 2099.29, ..., 2102.29, 2103.29, 2104.29],
-   [2097.09, 2098.09, 2099.09, ..., 2102.09, 2103.09, 2104.09],
-   [2097.77, 2098.77, 2099.77, ..., 2102.77, 2103.77, 2104.77]],
-
-  [[3982.37, 3983.37, 3984.37, ..., 3987.37, 3988.37, 3989.37],
-   [3983.21, 3984.21, 3985.21, ..., 3988.21, 3989.21, 3990.21],
-   [3983.28, 3984.28, 3985.28, ..., 3988.28, 3989.28, 3990.28],
-   ...,
-   [3981.62, 3982.62, 3983.62, ..., 3986.62, 3987.62, 3988.62],
-   [3981.41, 3982.41, 3983.41, ..., 3986.41, 3987.41, 3988.41],
-   [3982.09, 3983.09, 3984.09, ..., 3987.09, 3988.09, 3989.09]],
-
-  [[9104.50, 9105.50, 9106.50, ..., 9109.50, 9110.50, 9111.50],
-   [9105.34, 9106.34, 9107.34, ..., 9110.34, 9111.34, 9112.34],
-   [9105.41, 9106.41, 9107.41, ..., 9110.41, 9111.41, 9112.41],
-   ...,
-   [9103.74, 9104.74, 9105.74, ..., 9108.74, 9109.74, 9110.74],
-   [9103.54, 9104.54, 9105.54, ..., 9108.54, 9109.54, 9110.54],
-   [9104.22, 9105.22, 9106.22, ..., 9109.22, 9110.22, 9111.22]]],
+  [[ 9, 10, 11],
+   [10, 11, 12],
+   [11, 12, 13]],
+
+  [[10, 11, 12],
+   [11, 12, 13],
+   [12, 13, 14]],
+
+  [[11, 12, 13],
+   [12, 13, 14],
+   [13, 14, 15]]],
 
 
  ...,
 
 
- [[[1005.12, 1006.12, 1007.12, ..., 1010.12, 1011.12, 1012.12],
-   [1005.96, 1006.96, 1007.96, ..., 1010.96, 1011.96, 1012.96],
-   [1006.03, 1007.03, 1008.03, ..., 1011.03, 1012.03, 1013.03],
-   ...,
-   [1004.37, 1005.37, 1006.37, ..., 1009.37, 1010.37, 1011.37],
-   [1004.16, 1005.16, 1006.16, ..., 1009.16, 1010.16, 1011.16],
-   [1004.84, 1005.84, 1006.84, ..., 1009.84, 1010.84, 1011.84]],
-
-  [[1006.84, 1007.84, 1008.84, ..., 1011.84, 1012.84, 1013.84],
-   [1007.68, 1008.68, 1009.68, ..., 1012.68, 1013.68, 1014.68],
-   [1007.75, 1008.75, 1009.75, ..., 1012.75, 1013.75, 1014.75],
-   ...,
-   [1006.08, 1007.08, 1008.08, ..., 1011.08, 1012.08, 1013.08],
-   [1005.88, 1006.88, 1007.88, ..., 1010.88, 1011.88, 1012.88],
-   [1006.56, 1007.56, 1008.56, ..., 1011.56, 1012.56, 1013.56]],
-
-  [[1011.51, 1012.51, 1013.51, ..., 1016.51, 1017.51, 1018.51],
-   [1012.35, 1013.35, 1014.35, ..., 1017.35, 1018.35, 1019.35],
-   [1012.42, 1013.42, 1014.42, ..., 1017.42, 1018.42, 1019.42],
-   ...,
-   [1010.76, 1011.76, 1012.76, ..., 1015.76, 1016.76, 1017.76],
-   [1010.55, 1011.55, 1012.55, ..., 1015.55, 1016.55, 1017.55],
-   [1011.23, 1012.23, 1013.23, ..., 1016.23, 1017.23, 1018.23]],
+ [[[ 7,  8,  9],
+   [ 8,  9, 10],
+   [ 9, 10, 11]],
+
+  [[ 8,  9, 10],
+   [ 9, 10, 11],
+   [10, 11, 12]],
+
+  [[ 9, 10, 11],
+   [10, 11, 12],
+   [11, 12, 13]],
 
   ...,
 
-  [[2100.76, 2101.76, 2102.76, ..., 2105.76, 2106.76, 2107.76],
-   [2101.60, 2102.60, 2103.60, ..., 2106.60, 2107.60, 2108.60],
-   [2101.67, 2102.67, 2103.67, ..., 2106.67, 2107.67, 2108.67],
-   ...,
-   [2100.00, 2101.00, 2102.00, ..., 2105.00, 2106.00, 2107.00],
-   [2099.80, 2100.80, 2101.80, ..., 2104.80, 2105.80, 2106.80],
-   [2100.48, 2101.48, 2102.48, ..., 2105.48, 2106.48, 2107.48]],
-
-  [[3985.08, 3986.08, 3987.08, ..., 3990.08, 3991.08, 3992.08],
-   [3985.92, 3986.92, 3987.92, ..., 3990.92, 3991.92, 3992.92],
-   [3985.99, 3986.99, 3987.99, ..., 3990.99, 3991.99, 3992.99],
-   ...,
-   [3984.32, 3985.32, 3986.32, ..., 3989.32, 3990.32, 3991.32],
-   [3984.12, 3985.12, 3986.12, ..., 3989.12, 3990.12, 3991.12],
-   [3984.80, 3985.80, 3986.80, ..., 3989.80, 3990.80, 3991.80]],
-
-  [[9107.21, 9108.21, 9109.21, ..., 9112.21, 9113.21, 9114.21],
-   [9108.05, 9109.05, 9110.05, ..., 9113.05, 9114.05, 9115.05],
-   [9108.12, 9109.12, 9110.12, ..., 9113.12, 9114.12, 9115.12],
-   ...,
-   [9106.45, 9107.45, 9108.45, ..., 9111.45, 9112.45, 9113.45],
-   [9106.25, 9107.25, 9108.25, ..., 9111.25, 9112.25, 9113.25],
-   [9106.93, 9107.93, 9108.93, ..., 9111.93, 9112.93, 9113.93]]],
-
-
- [[[1005.24, 1006.24, 1007.24, ..., 1010.24, 1011.24, 1012.24],
-   [1006.08, 1007.08, 1008.08, ..., 1011.08, 1012.08, 1013.08],
-   [1006.15, 1007.15, 1008.15, ..., 1011.15, 1012.15, 1013.15],
-   ...,
-   [1004.49, 1005.49, 1006.49, ..., 1009.49, 1010.49, 1011.49],
-   [1004.28, 1005.28, 1006.28, ..., 1009.28, 1010.28, 1011.28],
-   [1004.96, 1005.96, 1006.96, ..., 1009.96, 1010.96, 1011.96]],
-
-  [[1006.96, 1007.96, 1008.96, ..., 1011.96, 1012.96, 1013.96],
-   [1007.80, 1008.80, 1009.80, ..., 1012.80, 1013.80, 1014.80],
-   [1007.87, 1008.87, 1009.87, ..., 1012.87, 1013.87, 1014.87],
-   ...,
-   [1006.20, 1007.20, 1008.20, ..., 1011.20, 1012.20, 1013.20],
-   [1006.00, 1007.00, 1008.00, ..., 1011.00, 1012.00, 1013.00],
-   [1006.68, 1007.68, 1008.68, ..., 1011.68, 1012.68, 1013.68]],
-
-  [[1011.63, 1012.63, 1013.63, ..., 1016.63, 1017.63, 1018.63],
-   [1012.47, 1013.47, 1014.47, ..., 1017.47, 1018.47, 1019.47],
-   [1012.54, 1013.54, 1014.54, ..., 1017.54, 1018.54, 1019.54],
-   ...,
-   [1010.87, 1011.87, 1012.87, ..., 1015.87, 1016.87, 1017.87],
-   [1010.67, 1011.67, 1012.67, ..., 1015.67, 1016.67, 1017.67],
-   [1011.35, 1012.35, 1013.35, ..., 1016.35, 1017.35, 1018.35]],
+  [[14, 15, 16],
+   [15, 16, 17],
+   [16, 17, 18]],
+
+  [[15, 16, 17],
+   [16, 17, 18],
+   [17, 18, 19]],
+
+  [[16, 17, 18],
+   [17, 18, 19],
+   [18, 19, 20]]],
+
+
+ [[[ 8,  9, 10],
+   [ 9, 10, 11],
+   [10, 11, 12]],
+
+  [[ 9, 10, 11],
+   [10, 11, 12],
+   [11, 12, 13]],
+
+  [[10, 11, 12],
+   [11, 12, 13],
+   [12, 13, 14]],
 
   ...,
 
-  [[2100.88, 2101.88, 2102.88, ..., 2105.88, 2106.88, 2107.88],
-   [2101.72, 2102.72, 2103.72, ..., 2106.72, 2107.72, 2108.72],
-   [2101.79, 2102.79, 2103.79, ..., 2106.79, 2107.79, 2108.79],
-   ...,
-   [2100.12, 2101.12, 2102.12, ..., 2105.12, 2106.12, 2107.12],
-   [2099.92, 2100.92, 2101.92, ..., 2104.92, 2105.92, 2106.92],
-   [2100.60, 2101.60, 2102.60, ..., 2105.60, 2106.60, 2107.60]],
-
-  [[3985.20, 3986.20, 3987.20, ..., 3990.20, 3991.20, 3992.20],
-   [3986.04, 3987.04, 3988.04, ..., 3991.04, 3992.04, 3993.04],
-   [3986.11, 3987.11, 3988.11, ..., 3991.11, 3992.11, 3993.11],
-   ...,
-   [3984.44, 3985.44, 3986.44, ..., 3989.44, 3990.44, 3991.44],
-   [3984.24, 3985.24, 3986.24, ..., 3989.24, 3990.24, 3991.24],
-   [3984.92, 3985.92, 3986.92, ..., 3989.92, 3990.92, 3991.92]],
-
-  [[9107.33, 9108.33, 9109.33, ..., 9112.33, 9113.33, 9114.33],
-   [9108.17, 9109.17, 9110.17, ..., 9113.17, 9114.17, 9115.17],
-   [9108.24, 9109.24, 9110.24, ..., 9113.24, 9114.24, 9115.24],
-   ...,
-   [9106.57, 9107.57, 9108.57, ..., 9111.57, 9112.57, 9113.57],
-   [9106.37, 9107.37, 9108.37, ..., 9111.37, 9112.37, 9113.37],
-   [9107.05, 9108.05, 9109.05, ..., 9112.05, 9113.05, 9114.05]]],
-
-
- [[[1005.36, 1006.36, 1007.36, ..., 1010.36, 1011.36, 1012.36],
-   [1006.20, 1007.20, 1008.20, ..., 1011.20, 1012.20, 1013.20],
-   [1006.27, 1007.27, 1008.27, ..., 1011.27, 1012.27, 1013.27],
-   ...,
-   [1004.60, 1005.60, 1006.60, ..., 1009.60, 1010.60, 1011.60],
-   [1004.40, 1005.40, 1006.40, ..., 1009.40, 1010.40, 1011.40],
-   [1005.08, 1006.08, 1007.08, ..., 1010.08, 1011.08, 1012.08]],
-
-  [[1007.08, 1008.08, 1009.08, ..., 1012.08, 1013.08, 1014.08],
-   [1007.92, 1008.92, 1009.92, ..., 1012.92, 1013.92, 1014.92],
-   [1007.99, 1008.99, 1009.99, ..., 1012.99, 1013.99, 1014.99],
-   ...,
-   [1006.32, 1007.32, 1008.32, ..., 1011.32, 1012.32, 1013.32],
-   [1006.12, 1007.12, 1008.12, ..., 1011.12, 1012.12, 1013.12],
-   [1006.80, 1007.80, 1008.80, ..., 1011.80, 1012.80, 1013.80]],
-
-  [[1011.75, 1012.75, 1013.75, ..., 1016.75, 1017.75, 1018.75],
-   [1012.59, 1013.59, 1014.59, ..., 1017.59, 1018.59, 1019.59],
-   [1012.66, 1013.66, 1014.66, ..., 1017.66, 1018.66, 1019.66],
-   ...,
-   [1010.99, 1011.99, 1012.99, ..., 1015.99, 1016.99, 1017.99],
-   [1010.79, 1011.79, 1012.79, ..., 1015.79, 1016.79, 1017.79],
-   [1011.47, 1012.47, 1013.47, ..., 1016.47, 1017.47, 1018.47]],
+  [[15, 16, 17],
+   [16, 17, 18],
+   [17, 18, 19]],
+
+  [[16, 17, 18],
+   [17, 18, 19],
+   [18, 19, 20]],
+
+  [[17, 18, 19],
+   [18, 19, 20],
+   [19, 20, 21]]],
+
+
+ [[[ 9, 10, 11],
+   [10, 11, 12],
+   [11, 12, 13]],
+
+  [[10, 11, 12],
+   [11, 12, 13],
+   [12, 13, 14]],
+
+  [[11, 12, 13],
+   [12, 13, 14],
+   [13, 14, 15]],
 
   ...,
 
-  [[2100.99, 2101.99, 2102.99, ..., 2105.99, 2106.99, 2107.99],
-   [2101.83, 2102.83, 2103.83, ..., 2106.83, 2107.83, 2108.83],
-   [2101.90, 2102.90, 2103.90, ..., 2106.90, 2107.90, 2108.90],
-   ...,
-   [2100.24, 2101.24, 2102.24, ..., 2105.24, 2106.24, 2107.24],
-   [2100.03, 2101.03, 2102.03, ..., 2105.03, 2106.03, 2107.03],
-   [2100.71, 2101.71, 2102.71, ..., 2105.71, 2106.71, 2107.71]],
-
-  [[3985.32, 3986.32, 3987.32, ..., 3990.32, 3991.32, 3992.32],
-   [3986.16, 3987.16, 3988.16, ..., 3991.16, 3992.16, 3993.16],
-   [3986.23, 3987.23, 3988.23, ..., 3991.23, 3992.23, 3993.23],
-   ...,
-   [3984.56, 3985.56, 3986.56, ..., 3989.56, 3990.56, 3991.56],
-   [3984.36, 3985.36, 3986.36, ..., 3989.36, 3990.36, 3991.36],
-   [3985.04, 3986.04, 3987.04, ..., 3990.04, 3991.04, 3992.04]],
-
-  [[9107.44, 9108.44, 9109.44, ..., 9112.44, 9113.44, 9114.44],
-   [9108.28, 9109.28, 9110.28, ..., 9113.28, 9114.28, 9115.28],
-   [9108.35, 9109.35, 9110.35, ..., 9113.35, 9114.35, 9115.35],
-   ...,
-   [9106.69, 9107.69, 9108.69, ..., 9111.69, 9112.69, 9113.69],
-   [9106.48, 9107.48, 9108.48, ..., 9111.48, 9112.48, 9113.48],
-   [9107.16, 9108.16, 9109.16, ..., 9112.16, 9113.16, 9114.16]]]]";
+  [[16, 17, 18],
+   [17, 18, 19],
+   [18, 19, 20]],
+
+  [[17, 18, 19],
+   [18, 19, 20],
+   [19, 20, 21]],
+
+  [[18, 19, 20],
+   [19, 20, 21],
+   [20, 21, 22]]]]";
         assert_str_eq(expected, &actual);
     }
 }
diff --git a/src/parallel/mod.rs b/src/parallel/mod.rs
index 60dbe466..fb973881 100644
--- a/src/parallel/mod.rs
+++ b/src/parallel/mod.rs
@@ -14,7 +14,6 @@
 //! - [`ArrayView`](ArrayView): `.into_par_iter()`
 //! - [`ArrayViewMut`](ArrayViewMut): `.into_par_iter()`
 //! - [`AxisIter`](iter::AxisIter), [`AxisIterMut`](iter::AxisIterMut): `.into_par_iter()`
-//! - [`AxisChunksIter`](iter::AxisChunksIter), [`AxisChunksIterMut`](iter::AxisChunksIterMut): `.into_par_iter()`
 //! - [`Zip`] `.into_par_iter()`
 //!
 //! The following other parallelized methods exist:
@@ -77,29 +76,6 @@
 //! }
 //! ```
 //!
-//! ## Axis chunks iterators
-//!
-//! Use the parallel `.axis_chunks_iter()` to process your data in chunks.
-//!
-//! ```
-//! extern crate ndarray;
-//!
-//! use ndarray::Array;
-//! use ndarray::Axis;
-//! use ndarray::parallel::prelude::*;
-//!
-//! fn main() {
-//!     let a = Array::linspace(0., 63., 64).into_shape((4, 16)).unwrap();
-//!     let mut shapes = Vec::new();
-//!     a.axis_chunks_iter(Axis(0), 3)
-//!      .into_par_iter()
-//!      .map(|chunk| chunk.shape().to_owned())
-//!      .collect_into_vec(&mut shapes);
-//!
-//!     assert_eq!(shapes, [vec![3, 16], vec![1, 16]]);
-//! }
-//! ```
-//!
 //! ## Zip
 //!
 //! Use zip for lock step function application across several arrays
diff --git a/src/parallel/par.rs b/src/parallel/par.rs
index efd761ac..bfa7522a 100644
--- a/src/parallel/par.rs
+++ b/src/parallel/par.rs
@@ -9,8 +9,6 @@ use rayon::iter::IndexedParallelIterator;
 use rayon::iter::ParallelIterator;
 use rayon::prelude::IntoParallelIterator;
 
-use crate::iter::AxisChunksIter;
-use crate::iter::AxisChunksIterMut;
 use crate::iter::AxisIter;
 use crate::iter::AxisIterMut;
 use crate::Dimension;
@@ -114,8 +112,6 @@ macro_rules! par_iter_wrapper {
 
 par_iter_wrapper!(AxisIter, [Sync]);
 par_iter_wrapper!(AxisIterMut, [Send + Sync]);
-par_iter_wrapper!(AxisChunksIter, [Sync]);
-par_iter_wrapper!(AxisChunksIterMut, [Send + Sync]);
 
 macro_rules! par_iter_view_wrapper {
     // thread_bounds are either Sync or Send + Sync
diff --git a/src/slice.rs b/src/slice.rs
index 349e1fa8..85abfb8e 100644
--- a/src/slice.rs
+++ b/src/slice.rs
@@ -604,17 +604,6 @@ macro_rules! s(
             }
         }
     };
-    // empty call, i.e. `s![]`
-    (@parse ::std::marker::PhantomData::<$crate::Ix0>, []) => {
-        {
-            #[allow(unsafe_code)]
-            unsafe {
-                $crate::SliceInfo::new_unchecked([], ::std::marker::PhantomData::<$crate::Ix0>)
-            }
-        }
-    };
-    // Catch-all clause for syntax errors
-    (@parse $($t:tt)*) => { compile_error!("Invalid syntax in s![] call.") };
     // convert range/index into SliceOrIndex
     (@convert $r:expr) => {
         <$crate::SliceOrIndex as ::std::convert::From<_>>::from($r)


Test patch:
diff --git a/parallel/tests/rayon.rs b/parallel/tests/rayon.rs
index ca014019..9432f9ed 100644
--- a/parallel/tests/rayon.rs
+++ b/parallel/tests/rayon.rs
@@ -7,8 +7,6 @@ use ndarray_parallel::prelude::*;
 
 const M: usize = 1024 * 10;
 const N: usize = 100;
-const CHUNK_SIZE: usize = 100;
-const N_CHUNKS: usize = (M + CHUNK_SIZE - 1) / CHUNK_SIZE;
 
 #[test]
 fn test_axis_iter() {
@@ -55,32 +53,3 @@ fn test_regular_iter_collect() {
     let v = a.view().into_par_iter().map(|&x| x).collect::<Vec<_>>();
     assert_eq!(v.len(), a.len());
 }
-
-#[test]
-fn test_axis_chunks_iter() {
-    let mut a = Array2::<f64>::zeros((M, N));
-    for (i, mut v) in a.axis_chunks_iter_mut(Axis(0), CHUNK_SIZE).enumerate() {
-        v.fill(i as _);
-    }
-    assert_eq!(a.axis_chunks_iter(Axis(0), CHUNK_SIZE).len(), N_CHUNKS);
-    let s: f64 = a
-        .axis_chunks_iter(Axis(0), CHUNK_SIZE)
-        .into_par_iter()
-        .map(|x| x.sum())
-        .sum();
-    println!("{:?}", a.slice(s![..10, ..5]));
-    assert_eq!(s, a.sum());
-}
-
-#[test]
-fn test_axis_chunks_iter_mut() {
-    let mut a = Array::linspace(0., 1.0f64, M * N)
-        .into_shape((M, N))
-        .unwrap();
-    let b = a.mapv(|x| x.exp());
-    a.axis_chunks_iter_mut(Axis(0), CHUNK_SIZE)
-        .into_par_iter()
-        .for_each(|mut v| v.mapv_inplace(|x| x.exp()));
-    println!("{:?}", a.slice(s![..10, ..5]));
-    assert!(a.all_close(&b, 0.001));
-}
diff --git a/tests/array.rs b/tests/array.rs
index 6b9985c0..ea5c1e82 100644
--- a/tests/array.rs
+++ b/tests/array.rs
@@ -92,13 +92,6 @@ fn test_slice() {
     assert!(vi.iter().zip(A.iter()).all(|(a, b)| a == b));
 }
 
-#[deny(unsafe_code)]
-#[test]
-fn test_slice_ix0() {
-    let arr = arr0(5);
-    assert_eq!(arr.slice(s![]), aview0(&5));
-}
-
 #[test]
 fn test_slice_edge_cases() {
     let mut arr = Array3::<u8>::zeros((3, 4, 5));
diff --git a/tests/par_rayon.rs b/tests/par_rayon.rs
index 4d5a8f1a..24a63627 100644
--- a/tests/par_rayon.rs
+++ b/tests/par_rayon.rs
@@ -5,8 +5,6 @@ use ndarray::prelude::*;
 
 const M: usize = 1024 * 10;
 const N: usize = 100;
-const CHUNK_SIZE: usize = 100;
-const N_CHUNKS: usize = (M + CHUNK_SIZE - 1) / CHUNK_SIZE;
 
 #[test]
 fn test_axis_iter() {
@@ -55,34 +53,3 @@ fn test_regular_iter_collect() {
     let v = a.view().into_par_iter().map(|&x| x).collect::<Vec<_>>();
     assert_eq!(v.len(), a.len());
 }
-
-#[test]
-fn test_axis_chunks_iter() {
-    let mut a = Array2::<f64>::zeros((M, N));
-    for (i, mut v) in a.axis_chunks_iter_mut(Axis(0), CHUNK_SIZE).enumerate() {
-        v.fill(i as _);
-    }
-    assert_eq!(a.axis_chunks_iter(Axis(0), CHUNK_SIZE).len(), N_CHUNKS);
-    let s: f64 = a
-        .axis_chunks_iter(Axis(0), CHUNK_SIZE)
-        .into_par_iter()
-        .map(|x| x.sum())
-        .sum();
-    println!("{:?}", a.slice(s![..10, ..5]));
-    assert_eq!(s, a.sum());
-}
-
-#[test]
-#[cfg(feature = "approx")]
-fn test_axis_chunks_iter_mut() {
-    use approx::assert_abs_diff_eq;
-    let mut a = Array::linspace(0., 1.0f64, M * N)
-        .into_shape((M, N))
-        .unwrap();
-    let b = a.mapv(|x| x.exp());
-    a.axis_chunks_iter_mut(Axis(0), CHUNK_SIZE)
-        .into_par_iter()
-        .for_each(|mut v| v.mapv_inplace(|x| x.exp()));
-    println!("{:?}", a.slice(s![..10, ..5]));
-    assert_abs_diff_eq!(a, b, epsilon = 0.001);
-}