Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Axis permutation to correctly handle cycles using bitmask approach#1505

Merged
akern40 merged 7 commits intorust-ndarray:masterrust-ndarray/ndarray:masterfrom
NewBornRustacean:feature-axes-inplaceNewBornRustacean/ndarray:feature-axes-inplaceCopy head branch name to clipboard
May 21, 2025
Merged

Axis permutation to correctly handle cycles using bitmask approach#1505
akern40 merged 7 commits intorust-ndarray:masterrust-ndarray/ndarray:masterfrom
NewBornRustacean:feature-axes-inplaceNewBornRustacean/ndarray:feature-axes-inplaceCopy head branch name to clipboard

Conversation

@NewBornRustacean
Copy link
Contributor

Overview

What's up! 😃 Currently, there're two functions to deal with permuting and reversing arrays(permuted_axes and reversed_axes).
As mentioned from related issue, they're not in-place, so I added permute_axes and reverse_axes. The new implementation for permute_axes uses a bitmask-based approach to efficiently track and process cycles in axis permutations!

Related issue

Changes

  1. permute_axes (in-place):

    • A new function with a cycle detection algorithm based on bitmasking.
    • try to maintain the zero-allocation, in-place modification approach
  2. reverse_axes (in-place):

    • simply use &mut self

Details on permute_axes

How it works

The new implementation uses a bitmask to track visited axes during permutation cycles:

  1. Cycle Detection: When permuting axes, we identify cycles of positions that need to be updated.
  2. Bitmask Tracking: A single usize is used as a bitmask to efficiently track which axes have been processed.
  3. In-place Updates: Each cycle is processed in-place by following the permutation pattern.

Example

Consider permuting a 2×2 array from [[1, 2], [3, 4]] with axes permutation [1, 0] (transpose):

// Original array
let mut arr = array![[1, 2], [3, 4]];
// Original: dims = [2, 2], strides = [2, 1]

// Permute axes [1, 0]
arr.permute_axes([1, 0]);
// Result: dims = [2, 2], strides = [1, 2]
// Array is now [[1, 3], [2, 4]]

Here's how the algorithm processes this:

  1. Start with axis 1 (new_axis=0):

    • Store initial values: dim[1]=2, stride[1]=1
    • Follow cycle: 1 → 0 → 1
    • Update dim[1] = dim[0] = 2
    • Update stride[1] = stride[0] = 2
    • Mark axes 0 and 1 as visited
  2. Process axis 0 (new_axis=1):

    • Already visited in the previous cycle, skip

The bitmask approach ensures each axis is processed exactly once, even in complex permutations with multiple cycles. The key operations are:

  • visited |= 1 << axis: Mark axis as visited
  • (visited & (1 << axis)) != 0: Check if axis is visited

@akern40 @nilgoyette added test cases similar to the original functions(premuted_axes and reversed_axes), but there might be missing cases. please take a look when you guys have some time! 🚀

src/impl_methods.rs Outdated Show resolved Hide resolved
src/impl_methods.rs Show resolved Hide resolved
@akern40 akern40 merged commit 2a2287c into rust-ndarray:master May 21, 2025
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.