www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - static arrays.

reply Dave <Dave_member pathlink.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit


Static ("rectangular") multi-dim arrays can perform pretty well - until you
start passing them 
around as function parameters.

Two ways to get around that would be to wrap the arrays with a UDT passed
byref, or use ptr params, 
with ptr's being much more intuitive for most applications of static arrays
(IMO).

Attached is a matrix multiplication program ported to D from the original
Shootout Delphi version (*).

The Delphi program has much cleaner syntax. For example, D pointer param
dereferencing would be 
(*m1)[a][b] = (*m2)[c][d] * (*m3)[e][f] .

For me this begs the question: Why aren't D static arrays passed byref (**)?

(*) http://dada.perl.it/shootout/matrix_allsrc.html
(**) static array params cannot be 'inout'.

Thanks,

- Dave
Jan 29 2007
parent reply Dave <Dave_member pathlink.com> writes:
Whoops - I should have made it clear that the programs perform roughly the same
(D being about 10% 
faster), but only if the static matrices are passed byref (using pointer
params) in D.

For Delphi, static arrays are passed byref.

Dave wrote:
 
 Static ("rectangular") multi-dim arrays can perform pretty well - until 
 you start passing them around as function parameters.
 
 Two ways to get around that would be to wrap the arrays with a UDT 
 passed byref, or use ptr params, with ptr's being much more intuitive 
 for most applications of static arrays (IMO).
 
 Attached is a matrix multiplication program ported to D from the 
 original Shootout Delphi version (*).
 
 The Delphi program has much cleaner syntax. For example, D pointer param 
 dereferencing would be (*m1)[a][b] = (*m2)[c][d] * (*m3)[e][f] .
 
 For me this begs the question: Why aren't D static arrays passed byref 
 (**)?
 
 (*) http://dada.perl.it/shootout/matrix_allsrc.html
 (**) static array params cannot be 'inout'.
 
 Thanks,
 
 - Dave
 
 
 ------------------------------------------------------------------------
 
 module matrix;
 
 import std.conv, std.stdio;
 
 void main(char[][] args)
 {
   int NUM = args.length > 1 ? toInt(args[1]) : 1;
   TMatrix M1, M2, MM;
 
   mkmatrix(SIZE, SIZE, &M1);
   mkmatrix(SIZE, SIZE, &M2);
   for(int i = 0; i < NUM; i++)
     mmult(SIZE, SIZE, &M1, &M2, &MM);
   writefln(MM[0][0]," ",MM[2][3]," ",MM[3][2]," ",MM[4][4]);
 }
 
 const SIZE = 30;
 
 typedef int[SIZE][SIZE] TMatrix;
 
 void mkmatrix(int rows, int cols, TMatrix* mx)
 {
   int count = 1;
   for(int R = 0; R < rows; R++)
     for(int C = 0; C < cols; C++)
     {
       (*mx)[R][C] = count;
       count++;
     }
 }
 
 void mmult(int rows, int cols, TMatrix* m1, TMatrix* m2, TMatrix* mm)
 {
   for(int i = 0; i < rows; i++)
     for(int j = 0; j < cols; j++)
     {
       int val = 0;
       for(int k = 0; k < cols; k++)
         val += (*m1)[i][k] * (*m2)[k][j];
       (*mm)[i][j] = val;
     }
 }

Jan 30 2007
parent reply torhu <fake address.dude> writes:
Dave wrote:
 Whoops - I should have made it clear that the programs perform roughly the
same (D being about 10% 
 faster), but only if the static matrices are passed byref (using pointer
params) in D.
 

I'm not sure what you mean. Static arrays in D are passed as the address of the first element. They are compatible with C arrays, at least in this respect. So the speedup has to be caused by something else.
Jan 31 2007
parent Dave <Dave_member pathlink.com> writes:
torhu wrote:
 Dave wrote:
 Whoops - I should have made it clear that the programs perform roughly 
 the same (D being about 10% faster), but only if the static matrices 
 are passed byref (using pointer params) in D.

I'm not sure what you mean. Static arrays in D are passed as the address of the first element. They are compatible with C arrays, at least in this respect. So the speedup has to be caused by something else.

Thanks - you're right. I think I made a bad assumption based on a botched comparison. Looking at it again, the following performs just as well. When I 'ported' it the first time from Delphi Pascal, I most likely had a typo in the original D code (?) module matrix2; import std.conv, std.stdio; void main(char[][] args) { int NUM = args.length > 1 ? toInt(args[1]) : 1; TMatrix M1, M2, MM; mkmatrix(SIZE, SIZE, M1); mkmatrix(SIZE, SIZE, M2); for(int i = 0; i < NUM; i++) mmult(SIZE, SIZE, M1, M2, MM); writefln(MM[0][0]," ",MM[2][3]," ",MM[3][2]," ",MM[4][4]); } const SIZE = 30; typedef int[SIZE][SIZE] TMatrix; void mkmatrix(int rows, int cols, TMatrix mx) { int count = 1; for(int R = 0; R < rows; R++) for(int C = 0; C < cols; C++) { mx[R][C] = count; count++; } } void mmult(int rows, int cols, TMatrix m1, TMatrix m2, TMatrix mm) { for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) { int val = 0; for(int k = 0; k < cols; k++) val += m1[i][k] * m2[k][j]; mm[i][j] = val; } }
Jan 31 2007