@@ -208,7 +208,7 @@ impl<A, D: Dimension> ArrayRef<A, D>
208208 /// memory layout. Otherwise, the layout of the output array is unspecified.
209209 /// If you need a particular layout, you can allocate a new array with the
210210 /// desired memory layout and [`.assign()`](Self::assign) the data.
211- /// Alternatively, you can collectan iterator, like this for a result in
211+ /// Alternatively, you can collect an iterator, like this for a result in
212212 /// standard layout:
213213 ///
214214 /// ```
@@ -463,7 +463,7 @@ impl<A, D: Dimension> ArrayRef<A, D>
463463 pub fn iter ( & self ) -> Iter < ' _ , A , D >
464464 {
465465 // debug_assert!(self.pointer_is_inbounds());
466- self . view ( ) . into_iter_ ( )
466+ self . view ( ) . into_iter ( )
467467 }
468468
469469 /// Return an iterator of mutable references to the elements of the array.
@@ -474,7 +474,7 @@ impl<A, D: Dimension> ArrayRef<A, D>
474474 /// Iterator element type is `&mut A`.
475475 pub fn iter_mut ( & mut self ) -> IterMut < ' _ , A , D >
476476 {
477- self . view_mut ( ) . into_iter_ ( )
477+ self . view_mut ( ) . into_iter ( )
478478 }
479479
480480 /// Return an iterator of indexes and references to the elements of the array.
@@ -1290,7 +1290,7 @@ impl<A, D: Dimension> ArrayRef<A, D>
12901290 pub fn outer_iter_mut ( & mut self ) -> AxisIterMut < ' _ , A , D :: Smaller >
12911291 where D : RemoveAxis
12921292 {
1293- self . view_mut ( ) . into_outer_iter ( )
1293+ self . view_mut ( ) . into_outer_iter_mut ( )
12941294 }
12951295
12961296 /// Return an iterator that traverses over `axis`
@@ -1516,6 +1516,17 @@ impl<A, D: Dimension> ArrayRef<A, D>
15161516 /// }
15171517 /// ```
15181518 pub fn axis_windows ( & self , axis : Axis , window_size : usize ) -> AxisWindows < ' _ , A , D >
1519+ {
1520+ self . axis_windows_with_stride ( axis, window_size, 1 )
1521+ }
1522+
1523+ /// Returns a producer which traverses over windows of a given length and
1524+ /// stride along an axis.
1525+ ///
1526+ /// Note that a calling this method with a stride of 1 is equivalent to
1527+ /// calling [`ArrayRef::axis_windows()`].
1528+ pub fn axis_windows_with_stride ( & self , axis : Axis , window_size : usize , stride_size : usize )
1529+ -> AxisWindows < ' _ , A , D >
15191530 {
15201531 let axis_index = axis. index ( ) ;
15211532
@@ -1527,7 +1538,12 @@ impl<A, D: Dimension> ArrayRef<A, D>
15271538 self . shape( )
15281539 ) ;
15291540
1530- AxisWindows :: new ( self . view ( ) , axis, window_size)
1541+ ndassert ! (
1542+ stride_size >0 ,
1543+ "Stride size must be greater than zero"
1544+ ) ;
1545+
1546+ AxisWindows :: new_with_stride ( self . view ( ) , axis, window_size, stride_size)
15311547 }
15321548
15331549 /// Return a view of the diagonal elements of the array.
@@ -2338,7 +2354,7 @@ impl<A, D: Dimension> ArrayRef<A, D>
23382354 /// The implementation creates a view with strides set to zero for the
23392355 /// axes that are to be repeated.
23402356 ///
2341- /// The broadcasting documentation for Numpy has more information.
2357+ /// The broadcasting documentation for NumPy has more information.
23422358 ///
23432359 /// ```
23442360 /// use ndarray::{aview1, aview2};
@@ -2526,6 +2542,72 @@ where
25262542 unsafe { self . with_strides_dim ( new_strides, new_dim) }
25272543 }
25282544
2545+ /// Permute the axes in-place.
2546+ ///
2547+ /// This does not move any data, it just adjusts the array's dimensions
2548+ /// and strides.
2549+ ///
2550+ /// *i* in the *j*-th place in the axes sequence means `self`'s *i*-th axis
2551+ /// becomes `self`'s *j*-th axis
2552+ ///
2553+ /// **Panics** if any of the axes are out of bounds, if an axis is missing,
2554+ /// or if an axis is repeated more than once.
2555+ ///
2556+ /// # Example
2557+ /// ```rust
2558+ /// use ndarray::{arr2, Array3};
2559+ ///
2560+ /// let mut a = arr2(&[[0, 1], [2, 3]]);
2561+ /// a.permute_axes([1, 0]);
2562+ /// assert_eq!(a, arr2(&[[0, 2], [1, 3]]));
2563+ ///
2564+ /// let mut b = Array3::<u8>::zeros((1, 2, 3));
2565+ /// b.permute_axes([1, 0, 2]);
2566+ /// assert_eq!(b.shape(), &[2, 1, 3]);
2567+ /// ```
2568+ #[ track_caller]
2569+ pub fn permute_axes < T > ( & mut self , axes : T )
2570+ where T : IntoDimension < Dim = D >
2571+ {
2572+ let axes = axes. into_dimension ( ) ;
2573+ // Ensure that each axis is used exactly once.
2574+ let mut usage_counts = D :: zeros ( self . ndim ( ) ) ;
2575+ for axis in axes. slice ( ) {
2576+ usage_counts[ * axis] += 1 ;
2577+ }
2578+ for count in usage_counts. slice ( ) {
2579+ assert_eq ! ( * count, 1 , "each axis must be listed exactly once" ) ;
2580+ }
2581+
2582+ let dim = self . layout . dim . slice_mut ( ) ;
2583+ let strides = self . layout . strides . slice_mut ( ) ;
2584+ let axes = axes. slice ( ) ;
2585+
2586+ // The cycle detection is done using a bitmask to track visited positions.
2587+ // For example, axes from [0,1,2] to [2, 0, 1]
2588+ // For axis values [1, 0, 2]:
2589+ // 1 << 1 // 0b0001 << 1 = 0b0010 (decimal 2)
2590+ // 1 << 0 // 0b0001 << 0 = 0b0001 (decimal 1)
2591+ // 1 << 2 // 0b0001 << 2 = 0b0100 (decimal 4)
2592+ //
2593+ // Each axis gets its own unique bit position in the bitmask:
2594+ // - Axis 0: bit 0 (rightmost)
2595+ // - Axis 1: bit 1
2596+ // - Axis 2: bit 2
2597+ //
2598+ let mut visited = 0usize ;
2599+ for ( new_axis, & axis) in axes. iter ( ) . enumerate ( ) {
2600+ if ( visited & ( 1 << axis) ) != 0 {
2601+ continue ;
2602+ }
2603+
2604+ dim. swap ( axis, new_axis) ;
2605+ strides. swap ( axis, new_axis) ;
2606+
2607+ visited |= ( 1 << axis) | ( 1 << new_axis) ;
2608+ }
2609+ }
2610+
25292611 /// Transpose the array by reversing axes.
25302612 ///
25312613 /// Transposition reverses the order of the axes (dimensions and strides)
@@ -2536,6 +2618,16 @@ where
25362618 self . layout . strides . slice_mut ( ) . reverse ( ) ;
25372619 self
25382620 }
2621+
2622+ /// Reverse the axes of the array in-place.
2623+ ///
2624+ /// This does not move any data, it just adjusts the array's dimensions
2625+ /// and strides.
2626+ pub fn reverse_axes ( & mut self )
2627+ {
2628+ self . layout . dim . slice_mut ( ) . reverse ( ) ;
2629+ self . layout . strides . slice_mut ( ) . reverse ( ) ;
2630+ }
25392631}
25402632
25412633impl < A , D : Dimension > ArrayRef < A , D >
@@ -2690,7 +2782,7 @@ where
26902782
26912783impl < A , D : Dimension > ArrayRef < A , D >
26922784{
2693- /// Perform an elementwise assigment to `self` from `rhs`.
2785+ /// Perform an elementwise assignment to `self` from `rhs`.
26942786 ///
26952787 /// If their shapes disagree, `rhs` is broadcast to the shape of `self`.
26962788 ///
@@ -2702,7 +2794,7 @@ impl<A, D: Dimension> ArrayRef<A, D>
27022794 self . zip_mut_with ( rhs, |x, y| x. clone_from ( y) ) ;
27032795 }
27042796
2705- /// Perform an elementwise assigment of values cloned from `self` into array or producer `to`.
2797+ /// Perform an elementwise assignment of values cloned from `self` into array or producer `to`.
27062798 ///
27072799 /// The destination `to` can be another array or a producer of assignable elements.
27082800 /// [`AssignElem`] determines how elements are assigned.
@@ -2718,7 +2810,7 @@ impl<A, D: Dimension> ArrayRef<A, D>
27182810 Zip :: from ( self ) . map_assign_into ( to, A :: clone) ;
27192811 }
27202812
2721- /// Perform an elementwise assigment to `self` from element `x`.
2813+ /// Perform an elementwise assignment to `self` from element `x`.
27222814 pub fn fill ( & mut self , x : A )
27232815 where A : Clone
27242816 {
@@ -3087,13 +3179,7 @@ impl<A, D: Dimension> ArrayRef<A, D>
30873179 Zip :: from ( self . lanes_mut ( axis) ) . map_collect ( mapping)
30883180 }
30893181 }
3090- }
30913182
3092- impl < A , S , D > ArrayBase < S , D >
3093- where
3094- S : DataOwned < Elem = A > + DataMut ,
3095- D : Dimension ,
3096- {
30973183 /// Remove the `index`th elements along `axis` and shift down elements from higher indexes.
30983184 ///
30993185 /// Note that this "removes" the elements by swapping them around to the end of the axis and
@@ -3212,7 +3298,7 @@ impl<A, D: Dimension> ArrayRef<A, D>
32123298 let mut result = self . to_owned ( ) ;
32133299
32143300 // Return early if the array has zero-length dimensions
3215- if self . shape ( ) . iter ( ) . any ( |s| * s == 0 ) {
3301+ if result . shape ( ) . contains ( & 0 ) {
32163302 return result;
32173303 }
32183304
0 commit comments