[Issue 10304] New: Array operations for multi-dimensional fixed-sized arrays with the same size

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sat Jun 8 14:46:51 PDT 2013


http://d.puremagic.com/issues/show_bug.cgi?id=10304

           Summary: Array operations for multi-dimensional fixed-sized
                    arrays with the same size
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody at puremagic.com
        ReportedBy: bearophile_hugs at eml.cc


--- Comment #0 from bearophile_hugs at eml.cc 2013-06-08 14:46:49 PDT ---
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;

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list