3个版本 (破坏性更新)

0.3.0 2022年2月13日
0.2.0 2021年10月28日
0.1.0 2021年9月28日

数据结构 中排名 1748

Download history 378/week @ 2024-04-01 458/week @ 2024-04-08 216/week @ 2024-04-15 211/week @ 2024-04-22 197/week @ 2024-04-29 196/week @ 2024-05-06 214/week @ 2024-05-13 290/week @ 2024-05-20 163/week @ 2024-05-27 191/week @ 2024-06-03 158/week @ 2024-06-10 182/week @ 2024-06-17 162/week @ 2024-06-24 66/week @ 2024-07-01 118/week @ 2024-07-08 165/week @ 2024-07-15

每月下载量 526
10crate中使用(直接使用8个)

MIT/Apache

32KB
646

ndshape

简单、快速线性化2D、3D和4D坐标。

线性化函数的规范选择是按行优先顺序,即逐行遍历N维数组时,首先遍历X,然后Y,然后Z等,假设提供坐标为[T; N]作为[X, Y, Z, ...]

linearize([x, y, z, ...]) = x + X_SIZE * y + X_SIZE * Y_SIZE * z + ...

为了实现不同的布局,只需要选择不同的坐标排列。例如,列优先布局需要将坐标指定为[..., Z, Y, X]。对于每个Y级别在内存中连续的3D布局,无论是布局[X, Z, Y]还是[Z, X, Y]都可以工作。

示例:多维数组的索引

use ndshape::{Shape, ConstShape3u32, ConstShape4u32, ConstPow2Shape3u32, RuntimeShape};

// An arbitrary shape.
let shape = ConstShape3u32::<5, 6, 7>;
let index = shape.linearize([1, 2, 3]);
assert_eq!(index, 101);
assert_eq!(shape.delinearize(index), [1, 2, 3]);

// A shape with power-of-two dimensions
// This allows us to use bit shifting and masking for linearization.
let shape = ConstPow2Shape3u32::<1, 2, 3>; // These are number of bits per dimension.
let index = shape.linearize([1, 2, 3]);
assert_eq!(index, 0b011_10_1);
assert_eq!(shape.delinearize(index), [1, 2, 3]);

// A runtime shape.
let shape = RuntimeShape::<u32, 3>::new([5, 6, 7]);
let index = shape.linearize([1, 2, 3]);
assert_eq!(index, 101);
assert_eq!(shape.delinearize(index), [1, 2, 3]);

// Use a shape for indexing an array in 4D.
// Step X, then Y, then Z, since that results in monotonic increasing indices.
// (Believe it or not, Rust's N-dimensional array (e.g. `[[T; N]; M]`)
// indexing is significantly slower than this).
let shape = ConstShape4u32::<5, 6, 7, 8>;
let data = [0; 5 * 6 * 7 * 8];
for w in 0..8 {
    for z in 0..7 {
        for y in 0..6 {
            for x in 0..5 {
                let i = shape.linearize([x, y, z, w]);
                assert_eq!(0, data[i as usize]);
            }
        }
    }
}

示例:使用模运算的负步长

将负向量线性化通常是有益的,因为它会产生负的线性“步长”。但是,当使用无符号线性索引时,负步长需要使用模运算表示,例如 -1 映射到 u32::MAX。这对于任何 Shape 都适用。您只需确保使用模运算来处理结果线性步长,例如使用 u32::wrapping_addu32::wrapping_mul。此外,使用模运算无法将负步长反线性化。为此,您必须使用有符号整数坐标。

use ndshape::{Shape, ConstShape3u32, ConstShape3i32};

let shape = ConstShape3u32::<10, 10, 10>;
let stride = shape.linearize([0, -1i32 as u32, 0]);
assert_eq!(stride, -10i32 as u32);

// Delinearize does not work with unsigned coordinates!
assert_ne!(shape.delinearize(stride), [0, -1i32 as u32, 0]);
assert_eq!(shape.delinearize(stride), [6, 8, 42949672]);

let shape = ConstShape3i32::<10, 10, 10>;
let stride = shape.linearize([0, -1, 0]);
assert_eq!(stride, -10);

// Delinearize works with signed coordinates.
assert_eq!(shape.delinearize(stride), [0, -1, 0]);

许可:MIT OR Apache-2.0

依赖项

~42KB