Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning values in a 2D array

Tags:

rust

I'm writing some code in Rust (mainly as a POC). The code takes a 2D array, passes it to a second function to do some matrix math (I know there is a standard library to do this, but I want to get used to how things work).

The problem is that the assignment to a 2D array is causing an issue.

My code looks like this

fn main() 
{
    // first create a couple of arrays - these will be used
    // for the vectors
    let line1: [i32; 4] = [4, 2, 3, 3];
    let line2: [i32; 4] = [3, 4, 5, 7];
    let line3: [i32; 4] = [2, 9, 6, 2];
    let line4: [i32; 4] = [5, 7, 2, 4];

    // create two holding arrays and assign
    let array_one = [line1, line3, line4, line2];
    let array_two = [line2, line1, line3, line4];

    // let's do the multiply
    let result = matrix_multiply(&array_one, &array_two);
    println!("{:?}", result);
}

fn matrix_multiply(vec1:&[&[i32;4];4], vec2:&[&[i32;4];4]) -> [[i32; 4];4]
{
    // we need to deference the parameters passed in
    let vec_one:[[i32;4];4] = vec1;
    let vec_two:[[i32;4];4] = vec2;

    // we need to store the sum
    let mut sum = 0;

    // we need to create the arrays to put the results into
    let mut result = [[0i32; 4]; 4];

    // loop through the two vectors
    for vone in 0..4
    {
        for vtwo in 0..4
        {
            for k in 0..4
            {
                sum = sum + vec1[[vone].k] * vec2[[k].vtwo];
            }
            result[[vec_one].vec_two] = sum;
            sum = 0;
        }
   }

   return result;
}

I've also tried result[vec_one][vec_two] = sum but when I come to compile, it looks like there is a problem assigning to array.

What am I doing wrong here?

like image 578
Nodoid Avatar asked Mar 14 '23 11:03

Nodoid


1 Answers

Here is your error, I believe (at least one of them):

<anon>:15:34: 15:44 error: mismatched types:
 expected `&[&[i32; 4]; 4]`,
    found `&[[i32; 4]; 4]`
(expected &-ptr,
    found array of 4 elements) [E0308]
<anon>:15     let result = matrix_multiply(&array_one, &array_two);
                                           ^~~~~~~~~~

The problem is, reference or dereference of arrays can't go on multiple levels of their nesting. This is because the memory layout of, say, [&[i32; 4]; 4] and [[i32; 4]; 4] is radically different, both in contents and in size - the former array consists of four pointers to other arrays (4*4=16/8*4=32 bytes total, depending on architecture of your machine), while the latter consists of four arrays laid out sequentially (4*4*4=64 bytes total). There is simply no way to go from [[i32; 4]; 4] to &[&[i32; 4]; 4] without rebuilding the outer array, which Rust won't ever do for you because it is too much magic.

You don't really need to use the inner reference; in fact, you probably don't even need to pass these arrays by reference at all: arrays of Copy types are Copy as well, so you can pass them by value. They are small enough to not cause any performance impact, and the compiler will probably optimize it automatically anyway:

fn main()  {
    // first create a couple of arrays - these will be used
    // for the vectors
    let line1: [i32; 4] = [4, 2, 3, 3];
    let line2: [i32; 4] = [3, 4, 5, 7];
    let line3: [i32; 4] = [2, 9, 6, 2];
    let line4: [i32; 4] = [5, 7, 2, 4];

    // create two holding arrays and assign
    let array_one = [line1, line3, line4, line2];
    let array_two = [line2, line1, line3, line4];

    // let's do the multiply
    let result = matrix_multiply(array_one, array_two);
    println!("{:?}", result);
}

fn matrix_multiply(vec1: [[i32; 4]; 4], vec2: [[i32; 4]; 4]) -> [[i32; 4]; 4] {
    // we need to create the arrays to put the results into
    let mut result = [[0i32; 4]; 4];

    // loop through the two vectors
    for vone in 0..4 {
        for vtwo in 0..4 {
            let mut sum = 0;
            for k in 0..4 {
                sum += vec1[vone][k] * vec2[k][vtwo];
            }
            result[vone][vtwo] = sum;
        }
   }

   result
}

(try it here)

I've also made your code more idiomatic according to the current community practices (braces positioning, spacing, etc.), and I've fixed the weird syntax for accessing arrays.

like image 53
Vladimir Matveev Avatar answered Mar 30 '23 12:03

Vladimir Matveev