Proposal: Multidimensional opSlice solution

Norbert Nemec Norbert at Nemec-online.de
Mon Mar 8 14:31:38 PST 2010


Don wrote:
> Norbert Nemec wrote:
>> The compiler would need to be aware of the data type Slice. It would 
>> therefore have to be something like a "builtin" type. If I am not 
>> mistaken, the language definition so far never makes use of "builtin" 
>> struct types.
> 
> You are mistaken <g>.
> object, TypeInfo, AssociativeArray, ...
> Complex will be added to that list, too.

Indeed? If that is so, a builtin Slice type as syntactic sugar would be 
just as good as my proposal. Just note that the slice operator "a..b" 
should also allow strided slicing "a..b:c"

>>     auto A = MyArray(["zero","one","two","three"]);
>>     assert( A[ [2,3,0] ] == MyArray(["two","three","zero"]) );
> 
> But that syntax doesn't allow slices.
> 
> It's only an issue if a dimension can be BOTH a slice T..T, AND T[2], 
> and they are not equivalent.
> I tried to come up with a plausible scenario where it was really a 
> problem, but failed. It requires that both T and T[2] are valid indices 
> for the same dimension, AND that slicing is supported.

Which is not only feasible but implemented and widely used in Fortran, 
Matlab and Python/NumPy:

	a[5]
	--> returns a single element

	a[5..8]
	--> returns a slice [ a[5],a[6],a[7] ]

	a[[5,3,1,4,6]]
	--> returns a list of elements selected by the list of indices
	    [a[5],a[3],a[1],a[4],a[6]]

In the last case, the list of indices can of course have just two 
entries, so
	a[[5,10]] == [ a[5],a[10] ]


> But this is all a bit academic since it's not going to happen. Maybe if 
> you'd been around a few months back, things would be different.

Yea, seems like I missed some important decisions. May indeed be too 
late for some ideas. Still - not giving up quite yet.


> Agreed. Multidimensional slicing is a costly operation, though, so I 
> think the absence of syntax sugar is tolerable.

Costly? Not at all! Just a bit of integer arithmetic that would need to 
be done anyway to access the data. Most numerical code consist of many 
nested loops containing very few operations. Strided multidimensional 
slicing operations in combination with array expressions allow to 
express this equivalently in very few lines that can be optimized very 
effectively.

As for the necessity of syntactic sugar, consider one typical line that 
I picked from my own numerical Python code:

Python/NumPy:
   off = (y[:-1,:]*x[1:,:] - y[1:,:]*x[:-1,:]) / (x[1:,:]-x[:-1,:])

D no slicing
   for(int i=0;i<off.shape[0]-1;i++)
     for(int j=0;j<off.shape[1];j++)
       off[i,j] = (y[i,j]*x[i+1,j]-y[i+1,j]*x[i,j]) / (x[i+1,j]-x[i,j])

D currently possible:
   off[] = (y[slice(0,$-1),slice(0,$)]*x[slice(1,$),slice(0,$)]
            - y[slice(1,$),slice(0,$)]*x[slice(0,$-1),slice(0,$)]) /
           (x[slice(1,$),slice(0,$)] - x[slice(0,$-1),slice(0,$)]);

D with syntactic sugar:
   off[] = (y[0..$-1,0..$]*x[1..$,0..$] - y[1..$,0..$]*x[0..$-1,0..$]) /
            (x[1..$,0..$] - x[0..$-1,0..$]);

D with defaults 0 and $ for missing boundaries:
   off[] = (y[..$-1,..]*x[1..,..] - y[1..,..]*x[..$-1,..]) /
                       (x[1..,..] - x[..$-1,..]);

Admitted, the last case does not work quite as nicely with ".." as it 
does with Python's ":". Still, the point should be clear.


> I see syntax sugar for slicing as much less important than 
> multidimensional $, where the alternative is really quite ugly. So I 
> pushed hard for opDollar.

Thanks for that. It is indeed essential.



More information about the Digitalmars-d mailing list