Repository: bluss/rust-ndarray
Pull request #239 (2016-11-18 21:39:51)

Adjust .dim() and related methods


Patch:
diff --git a/README.rst b/README.rst
index dcb7b06f..55563511 100644
--- a/README.rst
+++ b/README.rst
@@ -105,8 +105,8 @@ Recent Changes (ndarray)
   - Constructors and methods that take tuples for array sizes, like ``Array::zeros,``
     ``Array::from_shape_vec``, ``.into_shape()`` and so on will continue to work
     with tuples.
-  - The array method ``.dim()`` returns the dimension as it is. To get
-    a tuple, use ``.dim_pattern()``.
+  - The array method ``.raw_dimension()`` returns the shape description
+    ``D`` as it is.
   - Renamed iterators for consistency (each iterator is named for the
     method that creates it, for example ``.iter()`` returns ``Iter``).
   - The index iterator is now created with free functions ``indices`` or
diff --git a/examples/convo.rs b/examples/convo.rs
index a944e635..a15132fa 100644
--- a/examples/convo.rs
+++ b/examples/convo.rs
@@ -18,8 +18,8 @@ type Kernel3x3<A> = [[A; 3]; 3];
 fn conv_3x3<F>(a: &ArrayView2<F>, out: &mut ArrayViewMut2<F>, kernel: &Kernel3x3<F>) 
     where F: Float,
 {
-    let (n, m) = a.dim_pattern();
-    let (np, mp) = out.dim_pattern();
+    let (n, m) = a.dim();
+    let (np, mp) = out.dim();
     if n < 3 || m < 3 {
         return;
     }
diff --git a/examples/linalg.rs b/examples/linalg.rs
index 3d602dd8..ec864809 100644
--- a/examples/linalg.rs
+++ b/examples/linalg.rs
@@ -178,7 +178,7 @@ pub fn least_squares<A: ComplexField>(a: &Mat<A>, b: &Col<A>) -> Col<A>
     if <A as ComplexField>::is_complex() {
         // conjugate transpose
         // only elements below the diagonal have imag part
-        let (m, _) = L.dim_pattern();
+        let (m, _) = L.dim();
         for i in 1..m {
             for j in 0..i {
                 let elt = &mut L[[i, j]];
@@ -210,7 +210,7 @@ pub fn least_squares<A: ComplexField>(a: &Mat<A>, b: &Col<A>) -> Col<A>
 pub fn cholesky<A: ComplexField>(a: Mat<A>) -> Mat<A>
 {
     let z = A::zero();
-    let (m, n) = a.dim_pattern();
+    let (m, n) = a.dim();
     assert!(m == n);
     // Perform the operation in-place on `a`
     let mut L = a;
@@ -259,7 +259,7 @@ pub fn cholesky<A: ComplexField>(a: Mat<A>) -> Mat<A>
 /// Solve *L x = b* where *L* is a lower triangular matrix.
 pub fn subst_fw<A: Copy + Field>(l: &Mat<A>, b: &Col<A>) -> Col<A>
 {
-    let (m, n) = l.dim_pattern();
+    let (m, n) = l.dim();
     assert!(m == n);
     assert!(m == b.len());
     let mut x = Col::zeros(m);
@@ -277,7 +277,7 @@ pub fn subst_fw<A: Copy + Field>(l: &Mat<A>, b: &Col<A>) -> Col<A>
 /// Solve *U x = b* where *U* is an upper triangular matrix.
 pub fn subst_bw<A: Copy + Field>(u: &Mat<A>, b: &Col<A>) -> Col<A>
 {
-    let (m, n) = u.dim_pattern();
+    let (m, n) = u.dim();
     assert!(m == n);
     assert!(m == b.len());
     let mut x = Col::zeros(m);
diff --git a/src/array_serde.rs b/src/array_serde.rs
index d80d8a46..966dbc8a 100644
--- a/src/array_serde.rs
+++ b/src/array_serde.rs
@@ -50,7 +50,7 @@ impl<A, D, S> Serialize for ArrayBase<S, D>
     {
         let mut struct_state = try!(serializer.serialize_struct("Array", 3));
         try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION));
-        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.dim()));
+        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.raw_dimension()));
         try!(serializer.serialize_struct_elt(&mut struct_state, "data", Sequence(self.iter())));
         serializer.serialize_struct_end(struct_state)
     }
diff --git a/src/dimension/dim.rs b/src/dimension/dim.rs
index fb8b9b47..e5e3a4b5 100644
--- a/src/dimension/dim.rs
+++ b/src/dimension/dim.rs
@@ -34,7 +34,7 @@ use Ix;
 ///
 /// let mut array = Array2::zeros((3, 2));
 /// array[[0, 0]] = 1.;
-/// assert_eq!(array.dim(), Dim([3, 2]));
+/// assert_eq!(array.raw_dimension(), Dim([3, 2]));
 /// ```
 #[derive(Copy, Clone, PartialEq, Eq, Default)]
 pub struct Dim<I: ?Sized> {
diff --git a/src/impl_methods.rs b/src/impl_methods.rs
index c71d3d38..03f7fe14 100644
--- a/src/impl_methods.rs
+++ b/src/impl_methods.rs
@@ -47,19 +47,18 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
 
     /// Return the length of `axis`.
     ///
+    /// The axis should be in the range `Axis(` 0 .. *n* `)` where *n* is the
+    /// number of dimensions (axes) of the array.
+    ///
     /// ***Panics*** if the axis is out of bounds.
     pub fn len_of(&self, axis: Axis) -> usize {
         self.dim[axis.axis()]
     }
 
-    /// Return the shape of the array.
-    pub fn dim(&self) -> D {
-        self.dim.clone()
-        //self.dim.as_tuple()
-    }
-
-    /// Return the shape of the array as the "pattern" type (usually a tuple).
-    pub fn dim_pattern(&self) -> D::Pattern {
+    /// Return the shape of the array in its “pattern” form,
+    /// an integer in the one-dimensional case, tuple in the n-dimensional cases
+    /// and so on.
+    pub fn dim(&self) -> D::Pattern {
         self.dim.clone().into_pattern()
     }
 
@@ -68,7 +67,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
         self.dim.slice()
     }
 
-    /// Return the strides of the array
+    /// Return the strides of the array as a slice
     pub fn strides(&self) -> &[Ixs] {
         let s = self.strides.slice();
         // reinterpret unsigned integer as signed
@@ -82,6 +81,11 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
         self.dim.ndim()
     }
 
+    /// Return the shape of the array as it stored in the array.
+    pub fn raw_dimension(&self) -> D {
+        self.dim.clone()
+    }
+
     /// Return a read-only view of the array
     pub fn view(&self) -> ArrayView<A, D> {
         debug_assert!(self.pointer_is_inbounds());
@@ -453,7 +457,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
             sub.isubview(axis, i);
         }
         if subs.is_empty() {
-            let mut dim = self.dim();
+            let mut dim = self.raw_dimension();
             dim.set_axis(axis, 0);
             unsafe {
                 Array::from_shape_vec_unchecked(dim, vec![])
@@ -1120,7 +1124,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
         } else if self.dim.ndim() == rhs.dim.ndim() && self.shape() == rhs.shape() {
             self.zip_mut_with_same_shape(rhs, f);
         } else {
-            let rhs_broadcast = rhs.broadcast_unwrap(self.dim());
+            let rhs_broadcast = rhs.broadcast_unwrap(self.raw_dimension());
             self.zip_mut_with_by_rows(&rhs_broadcast, f);
         }
     }
@@ -1281,7 +1285,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
               F: FnMut(&B, &A) -> B,
               B: Clone,
     {
-        let mut res = Array::from_elem(self.dim().remove_axis(axis), init);
+        let mut res = Array::from_elem(self.raw_dimension().remove_axis(axis), init);
         for subview in self.axis_iter(axis) {
             res.zip_mut_with(&subview, |x, y| *x = fold(x, y));
         }
diff --git a/src/lib.rs b/src/lib.rs
index 923f562b..d771f38a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -772,7 +772,7 @@ pub struct Shape<D> {
     is_c: bool,
 }
 
-/// An array shape of n dimensions c-order, f-order or custom strides.
+/// An array shape of n dimensions in c-order, f-order or custom strides.
 #[derive(Copy, Clone, Debug)]
 pub struct StrideShape<D> {
     dim: D,
diff --git a/src/linalg/impl_linalg.rs b/src/linalg/impl_linalg.rs
index b3b599bc..dcc9c8a0 100644
--- a/src/linalg/impl_linalg.rs
+++ b/src/linalg/impl_linalg.rs
@@ -199,7 +199,7 @@ impl<A, S, S2> Dot<ArrayBase<S2, Ix2>> for ArrayBase<S, Ix2>
     {
         let a = self.view();
         let b = b.view();
-        let ((m, k), (k2, n)) = (a.dim_pattern(), b.dim_pattern());
+        let ((m, k), (k2, n)) = (a.dim(), b.dim());
         if k != k2 || m.checked_mul(n).is_none() {
             dot_shape_error(m, k, k2, n);
         }
@@ -253,7 +253,7 @@ impl<A, S, S2> Dot<ArrayBase<S2, Ix1>> for ArrayBase<S, Ix2>
     type Output = Array<A, Ix1>;
     fn dot(&self, rhs: &ArrayBase<S2, Ix1>) -> Array<A, Ix1>
     {
-        let ((m, a), n) = (self.dim_pattern(), rhs.dim_pattern());
+        let ((m, a), n) = (self.dim(), rhs.dim());
         if a != n {
             dot_shape_error(m, a, n, 1);
         }
@@ -312,7 +312,7 @@ fn mat_mul_impl<A>(alpha: A,
 {
     // size cutoff for using BLAS
     let cut = GEMM_BLAS_CUTOFF;
-    let ((mut m, a), (_, mut n)) = (lhs.dim_pattern(), rhs.dim_pattern());
+    let ((mut m, a), (_, mut n)) = (lhs.dim(), rhs.dim());
     if !(m > cut || n > cut || a > cut) ||
         !(same_type::<A, f32>() || same_type::<A, f64>()) {
         return mat_mul_general(alpha, lhs, rhs, beta, c);
@@ -351,15 +351,15 @@ fn mat_mul_impl<A>(alpha: A,
                     && blas_row_major_2d::<$ty, _>(&c_)
                 {
                     let (m, k) = match lhs_trans {
-                        CblasNoTrans => lhs_.dim_pattern(),
+                        CblasNoTrans => lhs_.dim(),
                         _ => {
-                            let (rows, cols) = lhs_.dim_pattern();
+                            let (rows, cols) = lhs_.dim();
                             (cols, rows)
                         }
                     };
                     let n = match rhs_trans {
-                        CblasNoTrans => rhs_.dim()[1],
-                        _ => rhs_.dim()[0],
+                        CblasNoTrans => rhs_.raw_dimension()[1],
+                        _ => rhs_.raw_dimension()[0],
                     };
                     // adjust strides, these may [1, 1] for column matrices
                     let lhs_stride = cmp::max(lhs_.strides()[0] as blas_index, k as blas_index);
@@ -403,7 +403,7 @@ fn mat_mul_general<A>(alpha: A,
                       c: &mut ArrayViewMut2<A>)
     where A: LinalgScalar,
 {
-    let ((m, k), (_, n)) = (lhs.dim_pattern(), rhs.dim_pattern());
+    let ((m, k), (_, n)) = (lhs.dim(), rhs.dim());
 
     // common parameters for gemm
     let ap = lhs.as_ptr();
@@ -486,8 +486,8 @@ pub fn general_mat_mul<A, S1, S2, S3>(alpha: A,
           S3: DataMut<Elem=A>,
           A: LinalgScalar,
 {
-    let ((m, k), (k2, n)) = (a.dim_pattern(), b.dim_pattern());
-    let (m2, n2) = c.dim_pattern();
+    let ((m, k), (k2, n)) = (a.dim(), b.dim());
+    let (m2, n2) = c.dim();
     if k != k2 || m != m2 || n != n2 {
         general_dot_shape_error(m, k, k2, n, m2, n2);
     } else {
@@ -553,7 +553,7 @@ fn blas_row_major_2d<A, S>(a: &ArrayBase<S, Ix2>) -> bool
     {
         return false;
     }
-    let (m, n) = a.dim_pattern();
+    let (m, n) = a.dim();
     if m > blas_index::max_value() as usize ||
         n > blas_index::max_value() as usize
     {
diff --git a/src/numeric/impl_numeric.rs b/src/numeric/impl_numeric.rs
index 04c35ca7..6134f9f4 100644
--- a/src/numeric/impl_numeric.rs
+++ b/src/numeric/impl_numeric.rs
@@ -124,7 +124,7 @@ impl<A, S, D> ArrayBase<S, D>
               S2: Data<Elem=A>,
               E: Dimension,
     {
-        let rhs_broadcast = rhs.broadcast_unwrap(self.dim());
+        let rhs_broadcast = rhs.broadcast_unwrap(self.raw_dimension());
         self.iter().zip(rhs_broadcast.iter()).all(|(x, y)| (*x - *y).abs() <= tol)
     }
 }
diff --git a/src/stacking.rs b/src/stacking.rs
index 74cc57f2..ce8c11bd 100644
--- a/src/stacking.rs
+++ b/src/stacking.rs
@@ -37,12 +37,12 @@ pub fn stack<'a, A, D>(axis: Axis, arrays: &[ArrayView<'a, A, D>])
     if arrays.len() == 0 {
         return Err(from_kind(ErrorKind::Unsupported));
     }
-    let mut res_dim = arrays[0].dim();
+    let mut res_dim = arrays[0].raw_dimension();
     if axis.axis() >= res_dim.ndim() {
         return Err(from_kind(ErrorKind::OutOfBounds));
     }
     let common_dim = res_dim.remove_axis(axis);
-    if arrays.iter().any(|a| a.dim().remove_axis(axis) != common_dim) {
+    if arrays.iter().any(|a| a.raw_dimension().remove_axis(axis) != common_dim) {
         return Err(from_kind(ErrorKind::IncompatibleShape));
     }
 


Test patch:
diff --git a/tests/array.rs b/tests/array.rs
index 6de31915..84d84ffa 100644
--- a/tests/array.rs
+++ b/tests/array.rs
@@ -259,14 +259,14 @@ fn test_select(){
 fn diag()
 {
     let d = arr2(&[[1., 2., 3.0f32]]).into_diag();
-    assert_eq!(d.dim_pattern(), 1);
+    assert_eq!(d.dim(), 1);
     let a = arr2(&[[1., 2., 3.0f32], [0., 0., 0.]]);
     let d = a.view().into_diag();
-    assert_eq!(d.dim_pattern(), 2);
+    assert_eq!(d.dim(), 2);
     let d = arr2::<f32, _>(&[[]]).into_diag();
-    assert_eq!(d.dim_pattern(), 0);
+    assert_eq!(d.dim(), 0);
     let d = RcArray::<f32, _>::zeros(()).into_diag();
-    assert_eq!(d.dim_pattern(), 1);
+    assert_eq!(d.dim(), 1);
 }
 
 #[test]
@@ -389,7 +389,7 @@ fn zero_axes()
 
     // we can even get a subarray of b
     let bsub = b.subview(Axis(0), 2);
-    assert_eq!(bsub.dim_pattern(), 0);
+    assert_eq!(bsub.dim(), 0);
 }
 
 #[test]
@@ -515,7 +515,7 @@ fn from_vec_dim_stride_2d_3() {
     let a = arr3(&[[[1]],
                    [[2]],
                    [[3]]]);
-    let d = a.dim();
+    let d = a.raw_dimension();
     let s = d.default_strides();
     assert_matches!(Array::from_shape_vec(d.strides(s), a.as_slice().unwrap().to_vec()), Ok(_));
 }
@@ -525,7 +525,7 @@ fn from_vec_dim_stride_2d_4() {
     let a = arr3(&[[[1]],
                    [[2]],
                    [[3]]]);
-    let d = a.dim();
+    let d = a.raw_dimension();
     let s = d.fortran_strides();
     assert_matches!(Array::from_shape_vec(d.strides(s), a.as_slice().unwrap().to_vec()), Ok(_));
 }
@@ -533,7 +533,7 @@ fn from_vec_dim_stride_2d_4() {
 #[test]
 fn from_vec_dim_stride_2d_5() {
     let a = arr3(&[[[1, 2, 3]]]);
-    let d = a.dim();
+    let d = a.raw_dimension();
     let s = d.fortran_strides();
     assert_matches!(Array::from_shape_vec(d.strides(s), a.as_slice().unwrap().to_vec()), Ok(_));
 }
diff --git a/tests/oper.rs b/tests/oper.rs
index 4a20ec26..2c83f3a6 100644
--- a/tests/oper.rs
+++ b/tests/oper.rs
@@ -284,7 +284,7 @@ fn reference_mat_mul<A, S, S2>(lhs: &ArrayBase<S, Ix2>, rhs: &ArrayBase<S2, Ix2>
           S: Data<Elem=A>,
           S2: Data<Elem=A>,
 {
-    let ((m, k), (k2, n)) = (lhs.dim_pattern(), rhs.dim_pattern());
+    let ((m, k), (k2, n)) = (lhs.dim(), rhs.dim());
     assert!(m.checked_mul(n).is_some());
     assert_eq!(k, k2);
     let mut res_elems = Vec::<A>::with_capacity(m * n);