Disjoint slices of an array as reference

data pulverizer data.pulverizer at gmail.com
Thu Aug 20 12:13:10 UTC 2020


On Thursday, 20 August 2020 at 08:26:59 UTC, Ali Çehreli wrote:
> On 8/19/20 9:11 PM, data pulverizer wrote:
>> Thanks. I might go for a design like this:
>> 
>> ```
>> struct View(T){
>>    T* data;
>>    long[2][] ranges;
>> }
>> ```
>> [...]
>
> I implemented the same idea recently; it's a fun exercise. :) I 
> didn't bother with opIndex because my use case was happy with 
> just the InputRange primitives (and .length I think).
>
> And I had to implement it because std.range.chain works only 
> with statically known number of sub-ranges. :/ If the number of 
> ranges are known, then this works:
>
> import std.stdio;
> import std.range;
>
> void main() {
>   auto x = [1,  2,  3, 4,  5,
>             6,  7,  8, 9,  10,
>             11, 12, 13, 14, 15];
>   auto y = chain(x[0..5], x[9..14]);
>   writeln(y);
> }
>
> [1, 2, 3, 4, 5, 10, 11, 12, 13, 14]
>
> Ali

Many thanks for confirming the internal structure of D's arrays 
and for the tip on std.range's chain function. It's exactly what 
I need. In fact the number of sub-ranges are statically known ...

As an aside, the reason for this query is that I have written a 
small module for multidimensional arrays to be included in a GLM 
(generalized linear models) package I am writing in D (in fact 
this will be the second major version of the package in D) - I 
know about Mir but my array doesn't have to be feature rich and 
only requires very few methods, I'm also probably going to write 
an article about it's internal structure and I've learned a lot 
creating it, and it means the GLM library won't have dependencies 
outside D's standard library and BLAS/LAPACK.

The multidimensional array is structured like this:

```
Array(long N, T)
if(isFloatingPoint!T && (N >= 1))
{
   T[] data;
   long[N] dim;
   ...
}
```

Where N is the number of dimensions. The indexing and stuff works 
fine but I wasn't happy that subsetting the array with slices 
returns a copy (for example an 2D array `A[0..2, 1..$]`) and 
since the subsetting is not necessarily contiguous, directly 
slicing from the data array was not feasible. But now N is known 
at compile time (`A[r[0][0]..r[0][1], r[1][0]..r[1][1], ... , 
r[N][0]..r[N][1]]`) so doing a subset using std.range's `chain` 
on `data` is easy. It also means I don't have to implement a 
separate `View` struct. This chain function will also simplify my 
indexing code, at the moment I am using string mixins to generate 
code for for loops over all the different dimensions where the 
function creating string the is recursive ... which was fun to 
write [:laugh:]!



More information about the Digitalmars-d-learn mailing list