Matrix allocation question


#1

I’d like to allocate a 3D matrix like this, where n is a run-time value (using inner Vecs isn’t an option, too much inefficient):

let mut mat = vec![[[10u32; 3]; 100]; n];

Unfortunately currently Rust doesn’t allow that. So I am using code like:

let mut mat = Vec::with_capacity(n);
for _ in 0 .. n {
    mat.push([[10u32; 3]; 100]);
}

But currently with -O Rustc produces awful asm output from that building loop.

So what’s the perfectly efficient way to do that in Rust today?

(An enhancement request: I’d like the Rust standard library/Prelude to offer me a maximally efficient and safe way to allocate a matrix like that).


#2

The following gets you code using appropriate vectorized, unrolled stores. The output’s not exactly what I would write by hand in assembly, but it’s reasonable.

pub fn f(n:usize) -> Vec<[[u32; 3]; 100]> {
    let mut mat = Vec::with_capacity(n);
    unsafe {
        mat.set_len(n);
        let ptr = mat.as_mut_ptr() as *mut u32;
        for i in 0..(300*n) {
            *ptr.offset(i as isize) = 10;
        }
    }
    mat
}

#3

I recommend you allocate an l*n*m array/vector and write a wrapper type (or use one from crates.io). When you get down to it, they’re the same thing.


#4

Thank you, it’s simple enough code (still, I wait for future Rust to not need such function).

For the record, this is how you do it in D language:

uint[3][100][] mat_alloc(in size_t n) pure nothrow @safe {
    auto buf = new int[3 * 100 * n];
    buf[] = 10;
    return cast(typeof(return))buf;
}

It’s more DRY and it performs no copies of data, and just one allocation (as your code). Unlike your Rust code it contains no unsafe code because the D compiler inserts run-time tests that verify all lengths match correctly (in simpler cases the test is done at compile-time by the compiler).