Comment #0 by bearophile_hugs — 2013-06-08T14:46:49Z
void main() {
double[3][2] mat = 1.0;
foreach (ref row; mat)
row[] *= 3; // OK
mat[] *= 3; // line 5, error.
}
dmd 2.064alpha gives:
temp.d(5): Error: incompatible types for ((mat[]) *= (3)): 'double[3u][]' and 'int'
Line 5 is an error because currently the D built-in array operations only work with 1D arrays. But the need to operate on all items of a 2D array is very commonly needed operation in the kind of array-heavy scientific code often written in Matlab or Python+SciPy.
This is in Python command line:
>>> from numpy import *
>>> mat = zeros((2, 3))
>>> mat
array([[ 0., 0., 0.],
[ 0., 0., 0.]])
>>> mat[:] = 1
>>> mat
array([[ 1., 1., 1.],
[ 1., 1., 1.]])
>>> mat *= 3
>>> mat
array([[ 3., 3., 3.],
[ 3., 3., 3.]])
So I suggest to support array ops with 2D or nD arrays (especially if they are fixed-sized arrays, so they are just a single chunk of memory, so the array op becomes just a matter of seeing the array in a linearized way).
One D syntax to support such operation is the same as for 1D arrays, I think this syntax is acceptable:
double[3][2] mat = 1.0;
mat[] *= 3;
If you really want to tell apart the 1D case from the nD case, then this is an alternative syntax, but I think it's not needed:
mat[][] *= 3;
To implement the matrix-wide operations this is a work-around that can be used now:
mat.flatView *= 3;
where flatView is similar to:
auto flatView(size_t R, size_t C)(ref double[C][R] mat) pure nothrow {
static struct FlatView(size_t N) {
double* ptr;
void opOpAssign(string op)(in double k) pure nothrow
if (op == "*") {
ptr[0 .. N] *= k;
}
}
return FlatView!(R * C)(mat[0].ptr);
}
Currently built-in array ops are designed to not t allocate intermediate arrays, so in the following code the multiplication doesn't allocate an intermediate array:
double[3] position2, velocity2;
double delta2 = 3.5;
position2[] += delta2 * velocity2[];
This too can be implemented by the compiler without intermediate arrays:
double[3][2] position, velocity;
double delta = 3.5;
position[] += delta * velocity[];
But its' not immediate to create a flatView() usable like this that doesn't allocate intermediate arrays:
double[3][2] position, velocity;
double delta = 3.5;
position.flatView += delta * velocity.flatView;
Comment #1 by robert.schadek — 2024-12-13T18:07:58Z