@@ -2538,27 +2538,6 @@ where
25382538 unsafe { self . with_strides_dim ( new_strides, new_dim) }
25392539 }
25402540
2541- /// Transpose the array by reversing axes.
2542- ///
2543- /// Transposition reverses the order of the axes (dimensions and strides)
2544- /// while retaining the same data.
2545- pub fn reversed_axes ( mut self ) -> ArrayBase < S , D >
2546- {
2547- self . layout . dim . slice_mut ( ) . reverse ( ) ;
2548- self . layout . strides . slice_mut ( ) . reverse ( ) ;
2549- self
2550- }
2551-
2552- /// Reverse the axes of the array in-place.
2553- ///
2554- /// This does not move any data, it just adjusts the array's dimensions
2555- /// and strides.
2556- pub fn reverse_axes ( & mut self )
2557- {
2558- self . layout . dim . slice_mut ( ) . reverse ( ) ;
2559- self . layout . strides . slice_mut ( ) . reverse ( ) ;
2560- }
2561-
25622541 /// Permute the axes in-place.
25632542 ///
25642543 /// This does not move any data, it just adjusts the array's dimensions
@@ -2568,10 +2547,38 @@ where
25682547 /// becomes `self`'s *j*-th axis
25692548 ///
25702549 /// **Panics** if any of the axes are out of bounds, if an axis is missing,
2571- /// or if an axis is repeated more than once.
2572- ///
2573- /// # Examples
2550+ /// or if an axis is repeated more than once.
2551+ ///
2552+ /// # About the Cycle Detection
2553+ ///
2554+ /// The cycle detection is done using a bitmask to track visited positions.
2555+ ///
2556+ /// For example, axes from [0,1,2] to [2, 0, 1]
2557+ /// For axis values [1, 0, 2]:
2558+ /// 1 << 1; // 0b0001 << 1 = 0b0010 (decimal 2)
2559+ /// 1 << 0; // 0b0001 << 0 = 0b0001 (decimal 1)
2560+ /// 1 << 2; // 0b0001 << 2 = 0b0100 (decimal 4)
2561+ ///
2562+ /// Each axis gets its own unique bit position in the bitmask:
2563+ /// - Axis 0: bit 0 (rightmost)
2564+ /// - Axis 1: bit 1
2565+ /// - Axis 2: bit 2
2566+ ///
2567+ /// The check `(visited & (1 << axis)) != 0` works as follows:
2568+ /// ```no_run
2569+ /// let mut visited = 0; // 0b0000
2570+ /// // Check axis 1
2571+ /// if (visited & (1 << 1)) != 0 { // 0b0000 & 0b0010 = 0b0000
2572+ /// // Not visited yet
2573+ /// }
2574+ /// // Mark axis 1 as visited
2575+ /// visited |= (1 << axis) | (1 << new_axis); /// // Check axis 1 again
2576+ /// if (visited & (1 << 1)) != 0 { // 0b0010 & 0b0010 = 0b0010
2577+ /// // Already visited!
2578+ /// }
2579+ /// ```
25742580 ///
2581+ /// # Example
25752582 /// ```rust
25762583 /// use ndarray::{arr2, Array3};
25772584 ///
@@ -2597,25 +2604,46 @@ where
25972604 assert_eq ! ( * count, 1 , "each axis must be listed exactly once" ) ;
25982605 }
25992606
2600- // Create temporary arrays for the new dimensions and strides
2601- let mut new_dim = D :: zeros ( self . ndim ( ) ) ;
2602- let mut new_strides = D :: zeros ( self . ndim ( ) ) ;
2607+ let dim = self . layout . dim . slice_mut ( ) ;
2608+ let strides = self . layout . strides . slice_mut ( ) ;
2609+ let axes = axes . slice ( ) ;
26032610
2604- {
2605- let dim = self . layout . dim . slice ( ) ;
2606- let strides = self . layout . strides . slice ( ) ;
2607- for ( new_axis, & axis) in axes. slice ( ) . iter ( ) . enumerate ( ) {
2608- new_dim[ new_axis] = dim[ axis] ;
2609- new_strides[ new_axis] = strides[ axis] ;
2611+ let mut visited = 0usize ;
2612+ for ( new_axis, & axis) in axes. iter ( ) . enumerate ( ) {
2613+ if ( visited & ( 1 << axis) ) != 0 {
2614+ continue ;
26102615 }
2616+
2617+ let temp = dim[ axis] ;
2618+ dim[ axis] = dim[ new_axis] ;
2619+ dim[ new_axis] = temp;
2620+
2621+ let temp = strides[ axis] ;
2622+ strides[ axis] = strides[ new_axis] ;
2623+ strides[ new_axis] = temp;
2624+ visited |= ( 1 << axis) | ( 1 << new_axis) ;
26112625 }
2626+ }
2627+
2628+ /// Transpose the array by reversing axes.
2629+ ///
2630+ /// Transposition reverses the order of the axes (dimensions and strides)
2631+ /// while retaining the same data.
2632+ pub fn reversed_axes ( mut self ) -> ArrayBase < S , D >
2633+ {
2634+ self . layout . dim . slice_mut ( ) . reverse ( ) ;
2635+ self . layout . strides . slice_mut ( ) . reverse ( ) ;
2636+ self
2637+ }
26122638
2613- // Update the dimensions and strides in place
2614- self . layout . dim . slice_mut ( ) . copy_from_slice ( new_dim. slice ( ) ) ;
2615- self . layout
2616- . strides
2617- . slice_mut ( )
2618- . copy_from_slice ( new_strides. slice ( ) ) ;
2639+ /// Reverse the axes of the array in-place.
2640+ ///
2641+ /// This does not move any data, it just adjusts the array's dimensions
2642+ /// and strides.
2643+ pub fn reverse_axes ( & mut self )
2644+ {
2645+ self . layout . dim . slice_mut ( ) . reverse ( ) ;
2646+ self . layout . strides . slice_mut ( ) . reverse ( ) ;
26192647 }
26202648}
26212649
0 commit comments