How to sum multidimensional arrays?

AB nospam at nospam.me
Fri Feb 28 16:51:10 UTC 2020


On Thursday, 27 February 2020 at 14:15:26 UTC, p.shkadzko wrote:
> I'd like to sum 2D arrays. Let's create 2 random 2D arrays and 
> sum them.
>
> ```
> import std.random : Xorshift, unpredictableSeed, uniform;
> import std.range : generate, take, chunks;
> import std.array : array;
>
> static T[][] rndMatrix(T)(T max, in int rows, in int cols)
> {
>     Xorshift rnd;
>     rnd.seed(unpredictableSeed);
>     const amount = rows * cols;
>     return generate(() => uniform(0, max, 
> rnd)).take(amount).array.chunks(cols).array;
> }
>
> void main() {
>     int[][] m1 = rndMatrix(10, 2, 3);
>     int[][] m2 = rndMatrix(10, 2, 3);
>
>     auto c = m1[] + m2[];
> }
> ```
>

Maybe this is already clear, but it is important to highlight 
that 2D arrays and arrays of arrays are two different things.

int[][] is an array of arrays, for each outer index the element 
is an array that has its own allocated memory and length.

2D arrays are not provided by the language, but can be 
implemented by defining a type with the required operator 
overloads.

Using an array of arrays for a 10000x10000 matrix requires 10001 
allocations while a dedicated 2D array implementation needs only 
1;


Example of an array of arrays where the inner arrays have 
different lengths:

------------
module test;
void main()
{
     import std.stdio;

     int[][] a;
     a.length=3;

     a[0]=[1,2,3];
     a[1]=[3,4];
     a[2]=[];
     writeln(a);
}
------------


Your Example with a minimal 2D array.


------------
module test2;

import std.random : Xorshift, unpredictableSeed, uniform;
import std.range : generate, take, chunks;
import std.array : array;
import std.stdio : writeln;

struct Matrix(T)
{
  int rows;
  T[] data;
  alias data this;
  int cols() {return cast(int) data.length/rows;}
  this(int r, int c) { data=new int[r*c]; rows=r;}
  this(int r, int c, T[] d) {assert(r*c==data.length); data=d; 
rows=r; }

  auto opIndex(int r, int c) {return data[rows*c+r];}

}

auto rndMatrix(T)(T max, in int rows, in int cols)
{
     Xorshift rnd;
     rnd.seed(unpredictableSeed);
     const amount = rows * cols;
     return Matrix!T(rows,cols,generate(() => uniform(0, max, 
rnd)).take(amount).array);
}

void main() {
     auto m1 = rndMatrix(10, 2, 3);
     auto m2 = rndMatrix(10, 2, 3);

     auto c = Matrix!int(2,3);
     c[] = m1[] + m2[];
     writeln(m1[1,2]);
     writeln(m2[1,2]);
     writeln(c[1,2]);
}
----------------

See https://dlang.org/spec/operatoroverloading.html#array-ops for 
a better overview of the required operators or mir.ndslice for an 
nD implementation.


More information about the Digitalmars-d-learn mailing list