Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-05 Thread Johannes Loher via Digitalmars-d-learn
Am 05.07.2016 um 17:22 schrieb Marc Schütz:
> auto concat(T : E[n], E, size_t n)(const E[][] args...) @nogc
> {
> size_t offset = 0;
> T result = void;
> foreach(arr; args) {
> result[offset .. offset+arr.length] = arr;
> offset += arr.length;
> }
> assert(offset == result.length);
> return result;
> }
> 
> static immutable ubyte[4] sigma0 = [101, 120, 112,  97];
> static immutable ubyte[4] sigma1 = [110, 100,  32,  51];
> static immutable ubyte[4] sigma2 = [ 50,  45,  98, 121];
> static immutable ubyte[4] sigma3 = [116, 101,  32, 107];
> 
> void func(in ref ubyte[32] key, in ref ubyte[16] n) @nogc
> {
> ubyte[64] buf;
> buf[0..4] = sigma0;
> buf[4..20] = key[0..16];
> buf[20..24] = sigma1;
> buf[24..40] = n;
> buf[40..44] = sigma2;
> buf[44..60] = key[16..$];
> buf[60..64] = sigma3;
> 
> auto buf2 = concat!(ubyte[64])(sigma0, key[0..16], sigma1, n,
> sigma2, key[16..$], sigma3);
> 
> assert(buf == buf2);
> }
> 
> void main() {
> ubyte[32] key =
> [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1];
> ubyte[16] n   = key[0..16];
> func(key, n);
> }
> 
> 
> Some remarks:
> 
> * I added `ref` to `func`'s parameters, because the arrays are
> relatively large, so passing them by value might be costly (you should
> measure it if you care).
> 
> * The `void` initialization in `concat` is an optimization that is valid
> only for POD types.
> 
> * Returning the array is cheap because of NRVO.

This seems to be exactly what I was looking for. Thanks a lot!



Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-05 Thread Johannes Loher via Digitalmars-d-learn
Am 05.07.2016 um 17:12 schrieb Johannes Loher:
> Am 05.07.2016 um 16:39 schrieb Rene Zwanenburg:
>> On Tuesday, 5 July 2016 at 12:34:20 UTC, Johannes Loher wrote:
>>> I tried this, but it does not work correctly with slices.
>>
>> The length of a slice is a runtime value, which is why it can't be used
>> to set static array size. What were you trying to achieve? Avoid copying
>> the input arrays, or accepting any slice?
>>
>> In case of the first, you can put ref in front of the Args:
>> auto combineArrays(Args...)(ref Args args)
>>
>> The second case will be a bit harder to solve nicely..
> 
> I would like to be able, to accept any slice. In the example in my first
> post, I need this for key[0..16] and key[16..$] (which are slices).
> Strangely enough, the solution I am leaning towards at the moment also
> uses length, but it does work for slices of static arrays (i.e. key[0..16]):
> 
> template expand(alias A)
> {
> auto ref M(alias I)() @property { return A[I]; }
> mixin(q{alias expand = TypeTuple!(}
> ~ iota(A.length).map!(a => "M!" ~ a.to!string).join(",")
> ~ q{);});
> }
> 
> ubyte[64] buf = [expand!sigma0,
>  expand!key[0..16],
>  expand!sigma1,
>  expand!n,
>  expand!sigma2,
>  expand!key[16..$],
>  expand!sigma3];
> 
> I suppose this is because the length of those slices is actually known
> at copiletime, but it looks a bit strange to me...
> 
> I was trying to write another template that takes several arrays and
> expands all of them:
> 
> template expand(Args...)
> {
> mixin(q{alias expand = TypeTuple!(}
> ~ iota(Args.length).map!(a => "expand!(Args[" ~ a.to!string ~
> "])").join(",")
> ~ q{);});
> }
> 
> It works for static arrays, but not for slices, because the template
> parameters are not alias parameters, so the length is then not "known"
> at compile time (at least that's what I think why it fails). Is there a
> way to specify variadic templates taking any number of alias template
> parameters?
> 

Well, I just realized my method does not work in the case that I want to
use expand on static arrays, which are returned from template functions...



Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-05 Thread Marc Schütz via Digitalmars-d-learn

auto concat(T : E[n], E, size_t n)(const E[][] args...) @nogc
{
size_t offset = 0;
T result = void;
foreach(arr; args) {
result[offset .. offset+arr.length] = arr;
offset += arr.length;
}
assert(offset == result.length);
return result;
}

static immutable ubyte[4] sigma0 = [101, 120, 112,  97];
static immutable ubyte[4] sigma1 = [110, 100,  32,  51];
static immutable ubyte[4] sigma2 = [ 50,  45,  98, 121];
static immutable ubyte[4] sigma3 = [116, 101,  32, 107];

void func(in ref ubyte[32] key, in ref ubyte[16] n) @nogc
{
ubyte[64] buf;
buf[0..4] = sigma0;
buf[4..20] = key[0..16];
buf[20..24] = sigma1;
buf[24..40] = n;
buf[40..44] = sigma2;
buf[44..60] = key[16..$];
buf[60..64] = sigma3;

auto buf2 = concat!(ubyte[64])(sigma0, key[0..16], sigma1, n, 
sigma2, key[16..$], sigma3);


assert(buf == buf2);
}

void main() {
ubyte[32] key = 
[0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1];

ubyte[16] n   = key[0..16];
func(key, n);
}


Some remarks:

* I added `ref` to `func`'s parameters, because the arrays are 
relatively large, so passing them by value might be costly (you 
should measure it if you care).


* The `void` initialization in `concat` is an optimization that 
is valid only for POD types.


* Returning the array is cheap because of NRVO.


Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-05 Thread Johannes Loher via Digitalmars-d-learn
Am 05.07.2016 um 16:39 schrieb Rene Zwanenburg:
> On Tuesday, 5 July 2016 at 12:34:20 UTC, Johannes Loher wrote:
>> I tried this, but it does not work correctly with slices.
> 
> The length of a slice is a runtime value, which is why it can't be used
> to set static array size. What were you trying to achieve? Avoid copying
> the input arrays, or accepting any slice?
> 
> In case of the first, you can put ref in front of the Args:
> auto combineArrays(Args...)(ref Args args)
> 
> The second case will be a bit harder to solve nicely..

I would like to be able, to accept any slice. In the example in my first
post, I need this for key[0..16] and key[16..$] (which are slices).
Strangely enough, the solution I am leaning towards at the moment also
uses length, but it does work for slices of static arrays (i.e. key[0..16]):

template expand(alias A)
{
auto ref M(alias I)() @property { return A[I]; }
mixin(q{alias expand = TypeTuple!(}
~ iota(A.length).map!(a => "M!" ~ a.to!string).join(",")
~ q{);});
}

ubyte[64] buf = [expand!sigma0,
 expand!key[0..16],
 expand!sigma1,
 expand!n,
 expand!sigma2,
 expand!key[16..$],
 expand!sigma3];

I suppose this is because the length of those slices is actually known
at copiletime, but it looks a bit strange to me...

I was trying to write another template that takes several arrays and
expands all of them:

template expand(Args...)
{
mixin(q{alias expand = TypeTuple!(}
~ iota(Args.length).map!(a => "expand!(Args[" ~ a.to!string ~
"])").join(",")
~ q{);});
}

It works for static arrays, but not for slices, because the template
parameters are not alias parameters, so the length is then not "known"
at compile time (at least that's what I think why it fails). Is there a
way to specify variadic templates taking any number of alias template
parameters?



Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-05 Thread Rene Zwanenburg via Digitalmars-d-learn

On Tuesday, 5 July 2016 at 12:34:20 UTC, Johannes Loher wrote:

I tried this, but it does not work correctly with slices.


The length of a slice is a runtime value, which is why it can't 
be used to set static array size. What were you trying to 
achieve? Avoid copying the input arrays, or accepting any slice?


In case of the first, you can put ref in front of the Args:
auto combineArrays(Args...)(ref Args args)

The second case will be a bit harder to solve nicely..


Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-05 Thread Johannes Loher via Digitalmars-d-learn
Am 05.07.2016 um 00:41 schrieb Rene Zwanenburg:
> On Monday, 4 July 2016 at 19:22:52 UTC, Johannes Loher wrote:
>> This looks really nice, but I have several occurences of this, with
>> different arrays (and lengths), so i would need to create several of
>> those structs. But it looks really clean :)
> 
> You can use a template to remove the boilerplate. Here's a quick example:
> 
> https://dpaste.dzfl.pl/43b379992648

I tried this, but it does not work correctly with slices.


Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-04 Thread Rene Zwanenburg via Digitalmars-d-learn

On Monday, 4 July 2016 at 19:22:52 UTC, Johannes Loher wrote:
This looks really nice, but I have several occurences of this, 
with different arrays (and lengths), so i would need to create 
several of those structs. But it looks really clean :)


You can use a template to remove the boilerplate. Here's a quick 
example:


https://dpaste.dzfl.pl/43b379992648


Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-04 Thread Johannes Loher via Digitalmars-d-learn
Am 04.07.2016 um 19:24 schrieb ZombineDev:
> On Monday, 4 July 2016 at 14:31:41 UTC, Johannes Loher wrote:
>> In a project I am currently working on, I have lot's of code of the
>> following form:
>>
>> static immutable ubyte[4] sigma0 = [101, 120, 112,  97]; static
>> immutable ubyte[4] sigma1 = [110, 100,  32,  51]; static immutable
>> ubyte[4] sigma2 = [ 50,  45,  98, 121]; static immutable ubyte[4]
>> sigma3 = [116, 101,  32, 107];
>>
>> void func(in ubyte[32] key, in ubyte[16] n)
>> {
>> ubyte[64] buf;
>> buf[0..4] = sigma0;
>> buf[4..20] = key[0..16];
>> buf[20..24] = sigma1;
>> buf[24..40] = n;
>> buf[40..44] = sigma2;
>> buf[44..60] = key[16..$];
>> buf[60..64] = sigma3;
>>
>>/* do something with buf */
>> }
>>
>> This looks really bad to me. I would like to initialize buf with the
>> corresponding values (the way it's done now, it is impossible to make
>> buf immutable...).
>>
>> One option for this would be to use ~ to concatenate the arrays. But
>> this obviously results in GC allocations, which I want to avoid here,
>> because the functions get called very often.
>>
>> Another option would be to to manually expand the arrays and
>> initialize buf with that:
>>
>> ubyte[64] buf = [sigma0[0], sigma0[1], /* ... */, sigma3[3]];
>>
>> This is obviously very annoying and error prone.
>>
>> Whe searching for a solution, I found this thread about automatic
>> expanding of arrays:
>>
>> http://forum.dlang.org/thread/hwellpcaomwbpnpof...@forum.dlang.org?page=1
>>
>> This would result in the following code for me:
>>
>> ubyte[64] buf = [
>> expand!sigma0,
>> expand!key[0..16],
>> expand!sigma1,
>> expand!n,
>> expand!sigma2,
>> expand!key[16..$],
>> expand!sigma3
>> ];
>>
>> Is this the suggested solution (is it robust)? Is there anything like
>> this in Phobos?
>>
>> Thanks for your help!
> 
> You should be able to use
> http://dlang.org/phobos-prerelease/std_meta#aliasSeqOf for this.
> 
> I think it should work with the same syntax as expand, but with added
> bonus that it also handles ranges like those in std.range and
> std.algorithm.
I just tried that, but it does not work for arrays, which can not be
read at compile time.


Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-04 Thread Johannes Loher via Digitalmars-d-learn
Am 04.07.2016 um 20:33 schrieb Ali Çehreli:
> On 07/04/2016 07:31 AM, Johannes Loher wrote:
>> In a project I am currently working on, I have lot's of code of the
>> following form:
>>
>> static immutable ubyte[4] sigma0 = [101, 120, 112,  97];
>> static immutable ubyte[4] sigma1 = [110, 100,  32,  51];
>> static immutable ubyte[4] sigma2 = [ 50,  45,  98, 121];
>> static immutable ubyte[4] sigma3 = [116, 101,  32, 107];
>>
>> void func(in ubyte[32] key, in ubyte[16] n)
>> {
>>  ubyte[64] buf;
>>  buf[0..4] = sigma0;
>>  buf[4..20] = key[0..16];
>>  buf[20..24] = sigma1;
>>  buf[24..40] = n;
>>  buf[40..44] = sigma2;
>>  buf[44..60] = key[16..$];
>>  buf[60..64] = sigma3;
>>
>> /* do something with buf */
>> }
> 
> Here's an option that overlays a struct on top of the bytes:
> 
> struct Buf {
> union {
> struct {
> ubyte[4] sigma0 = [101, 120, 112,  97];
> ubyte[16] keyBeg;
> ubyte[4] sigma1 = [110, 100,  32,  51];
> ubyte[16] n;
> ubyte[4] sigma2 = [ 50,  45,  98, 121];
> ubyte[16] keyEnd;
> ubyte[4] sigma3 = [116, 101,  32, 107];
> }
> 
> ubyte[64] bytes;
> }
> 
> this(const ubyte[] key, const ubyte[] n) {
> this.keyBeg = key[0..16];
> this.keyEnd = key[16..$];
> this.n = n;
> }
> }
> 
> static assert(Buf.sizeof == 64);
> 
> void func(in ubyte[] key, in ubyte[] n) {
> auto buf = Buf(key, n);
> writeln(buf.bytes);
> }
> 
> import std.stdio;
> import std.range;
> import std.array;
> 
> void main() {
> func(ubyte(32).iota.array,
>  ubyte(16).iota.array);
> }
> 
> Prints:
> 
> [101, 120, 112, 97, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
> 15, 110, 100, 32, 51, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
> 15, 50, 45, 98, 121, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
> 29, 30, 31, 116, 101, 32, 107]
> 
> Ali
> 
This looks really nice, but I have several occurences of this, with
different arrays (and lengths), so i would need to create several of
those structs. But it looks really clean :)


Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-04 Thread Ali Çehreli via Digitalmars-d-learn

On 07/04/2016 07:31 AM, Johannes Loher wrote:
> In a project I am currently working on, I have lot's of code of the
> following form:
>
> static immutable ubyte[4] sigma0 = [101, 120, 112,  97];
> static immutable ubyte[4] sigma1 = [110, 100,  32,  51];
> static immutable ubyte[4] sigma2 = [ 50,  45,  98, 121];
> static immutable ubyte[4] sigma3 = [116, 101,  32, 107];
>
> void func(in ubyte[32] key, in ubyte[16] n)
> {
>  ubyte[64] buf;
>  buf[0..4] = sigma0;
>  buf[4..20] = key[0..16];
>  buf[20..24] = sigma1;
>  buf[24..40] = n;
>  buf[40..44] = sigma2;
>  buf[44..60] = key[16..$];
>  buf[60..64] = sigma3;
>
> /* do something with buf */
> }

Here's an option that overlays a struct on top of the bytes:

struct Buf {
union {
struct {
ubyte[4] sigma0 = [101, 120, 112,  97];
ubyte[16] keyBeg;
ubyte[4] sigma1 = [110, 100,  32,  51];
ubyte[16] n;
ubyte[4] sigma2 = [ 50,  45,  98, 121];
ubyte[16] keyEnd;
ubyte[4] sigma3 = [116, 101,  32, 107];
}

ubyte[64] bytes;
}

this(const ubyte[] key, const ubyte[] n) {
this.keyBeg = key[0..16];
this.keyEnd = key[16..$];
this.n = n;
}
}

static assert(Buf.sizeof == 64);

void func(in ubyte[] key, in ubyte[] n) {
auto buf = Buf(key, n);
writeln(buf.bytes);
}

import std.stdio;
import std.range;
import std.array;

void main() {
func(ubyte(32).iota.array,
 ubyte(16).iota.array);
}

Prints:

[101, 120, 112, 97, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
15, 110, 100, 32, 51, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
15, 50, 45, 98, 121, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 
29, 30, 31, 116, 101, 32, 107]


Ali



Re: Initializing static array with contents of (static and dynamic) arrays

2016-07-04 Thread ZombineDev via Digitalmars-d-learn

On Monday, 4 July 2016 at 14:31:41 UTC, Johannes Loher wrote:
In a project I am currently working on, I have lot's of code of 
the following form:


static immutable ubyte[4] sigma0 = [101, 120, 112,  97]; static 
immutable ubyte[4] sigma1 = [110, 100,  32,  51]; static 
immutable ubyte[4] sigma2 = [ 50,  45,  98, 121]; static 
immutable ubyte[4] sigma3 = [116, 101,  32, 107];


void func(in ubyte[32] key, in ubyte[16] n)
{
ubyte[64] buf;
buf[0..4] = sigma0;
buf[4..20] = key[0..16];
buf[20..24] = sigma1;
buf[24..40] = n;
buf[40..44] = sigma2;
buf[44..60] = key[16..$];
buf[60..64] = sigma3;

   /* do something with buf */
}

This looks really bad to me. I would like to initialize buf 
with the corresponding values (the way it's done now, it is 
impossible to make buf immutable...).


One option for this would be to use ~ to concatenate the 
arrays. But this obviously results in GC allocations, which I 
want to avoid here, because the functions get called very often.


Another option would be to to manually expand the arrays and 
initialize buf with that:


ubyte[64] buf = [sigma0[0], sigma0[1], /* ... */, sigma3[3]];

This is obviously very annoying and error prone.

Whe searching for a solution, I found this thread about 
automatic expanding of arrays:


http://forum.dlang.org/thread/hwellpcaomwbpnpof...@forum.dlang.org?page=1

This would result in the following code for me:

ubyte[64] buf = [
expand!sigma0,
expand!key[0..16],
expand!sigma1,
expand!n,
expand!sigma2,
expand!key[16..$],
expand!sigma3
];

Is this the suggested solution (is it robust)? Is there 
anything like

this in Phobos?

Thanks for your help!


You should be able to use 
http://dlang.org/phobos-prerelease/std_meta#aliasSeqOf for this.


I think it should work with the same syntax as expand, but with 
added bonus that it also handles ranges like those in std.range 
and std.algorithm.


Initializing static array with contents of (static and dynamic) arrays

2016-07-04 Thread Johannes Loher via Digitalmars-d-learn
In a project I am currently working on, I have lot's of code of the
following form:

static immutable ubyte[4] sigma0 = [101, 120, 112,  97];
static immutable ubyte[4] sigma1 = [110, 100,  32,  51];
static immutable ubyte[4] sigma2 = [ 50,  45,  98, 121];
static immutable ubyte[4] sigma3 = [116, 101,  32, 107];

void func(in ubyte[32] key, in ubyte[16] n)
{
ubyte[64] buf;
buf[0..4] = sigma0;
buf[4..20] = key[0..16];
buf[20..24] = sigma1;
buf[24..40] = n;
buf[40..44] = sigma2;
buf[44..60] = key[16..$];
buf[60..64] = sigma3;

   /* do something with buf */
}

This looks really bad to me. I would like to initialize buf with the
corresponding values (the way it's done now, it is impossible to make
buf immutable...).

One option for this would be to use ~ to concatenate the arrays. But
this obviously results in GC allocations, which I want to avoid here,
because the functions get called very often.

Another option would be to to manually expand the arrays and initialize
buf with that:

ubyte[64] buf = [sigma0[0], sigma0[1], /* ... */, sigma3[3]];

This is obviously very annoying and error prone.

Whe searching for a solution, I found this thread about automatic
expanding of arrays:

http://forum.dlang.org/thread/hwellpcaomwbpnpof...@forum.dlang.org?page=1

This would result in the following code for me:

ubyte[64] buf = [
expand!sigma0,
expand!key[0..16],
expand!sigma1,
expand!n,
expand!sigma2,
expand!key[16..$],
expand!sigma3
];

Is this the suggested solution (is it robust)? Is there anything like
this in Phobos?

Thanks for your help!