Thread overview
Ways to initialize static arrays
Aug 23, 2010
Stanislav Blinov
Aug 23, 2010
bearophile
Aug 23, 2010
Stanislav Blinov
Aug 25, 2010
Philippe Sigaud
Aug 26, 2010
Stanislav Blinov
Aug 26, 2010
Philippe Sigaud
Aug 26, 2010
Stanislav Blinov
Aug 26, 2010
Philippe Sigaud
Aug 26, 2010
Stanislav Blinov
Aug 28, 2010
Stanislav Blinov
August 23, 2010
 Hello,

I was wondering if anyone has suggestions on performing arbitrary initialization of static arrays, size of which is arbitrary at compile time.

Consider this:

template StaticArray(T,int N,T v) if (N > 0)
{
    static if (N == 1)
    {
        enum T[N] StaticArray = cast(T[N])[v];
    }
    else
    {
        enum T[N] StaticArray = cast(T[N])([v] ~ StaticArray!(T,N-1,v));
    }
}

T[] generateArray(T,int N,string G=q{a[i] = 0})()
{
    T[] a;
    foreach(i;0..N)
    {
        mixin(G ~ ";");
    }
    return a.dup;
}

template GenStaticArray(T,int N,string G=q{a[i] = 0})
{
    enum T[N] GenStaticArray = cast(T[N])generateArray!(T,N,G)();
}

struct Vector(int N,T)
{
    T data_[N];

    static immutable Vector Identity = { StaticArray!(T,N,1) };
    static immutable Vector Zero = { StaticArray!(T,N,0) };
    static immutable Vector UnitX = { GenStaticArray!(T,N,q{a[i] = i ? 0 : 1}) };
    static immutable Vector UnitY = { GenStaticArray!(T,N,q{a[i] = i != 1 ? 0 : 1}) };
    static immutable Vector UnitZ = { GenStaticArray!(T,N,q{a[i] = i != 2 ? 0 : 1}) };
}

I don't like those casts in templates. In fact, I'm not even sure if such code is legal. Maybe there is some better way of doing this?

-- 

	

August 23, 2010
Stanislav Blinov:

> I was wondering if anyone has suggestions on performing arbitrary initialization of static arrays, size of which is arbitrary at compile time.

Please explain your purposes a bit better.

Bye,
bearophile
August 23, 2010
 23.08.2010 16:31, bearophile wrote:
> Stanislav Blinov:
>
>> I was wondering if anyone has suggestions on performing arbitrary
>> initialization of static arrays, size of which is arbitrary at compile time.
> Please explain your purposes a bit better.
>
I have a struct template (let's call it S) that wraps an array of N elements. N is set at compile time via template parameter. S uses static array as storage (T[N]). I need a set of constants of type S which I'd like to be evaluatable at compile time. I can create these constants with the following constructs:

static immutable S C1 = { /* initialization of struct fields here */ };
static immutable S C2 = { /* initialization of struct fields here */ };

Hence, I need some way to initialize a field which is T[N].

Later, I could use those constants like this:

class Foo
{
    S s1_ = S.C1;
    S s2_ = S.C2;
}

I can write a set of initializers for some values of N, but I'd like them to be generic so that I could apply them for arbitrary value of N.
E.g. one can do things like T[3] a = [ 1, 2, 3 ], but I'd like to be able to do T[N] = SomeInitializerForArrayOfNElements;

What I'm trying to achieve is:

1. Initialize T[N] elements to a specific value.
2. Initialize every element of T[N] to some value deduced at compile time using it's index.

I came up with the templates in my initial post. They seem to work, but I doubt those are legal solutions.
August 25, 2010
2010/8/23 Stanislav Blinov <blinov@loniir.ru>

> I have a struct template (let's call it S) that wraps an array of N elements. N is set at compile time via template parameter. S uses static array as storage (T[N]). I need a set of constants of type S which I'd like to be evaluatable at compile time. I can create these constants with the following constructs:
>
> static immutable S C1 = { /* initialization of struct fields here */ }; static immutable S C2 = { /* initialization of struct fields here */ };
>
> Hence, I need some way to initialize a field which is T[N].
>
> Later, I could use those constants like this:
>
> class Foo
> {
>    S s1_ = S.C1;
>    S s2_ = S.C2;
> }
>
> I can write a set of initializers for some values of N, but I'd like them
> to be generic so that I could apply them for arbitrary value of N.
> E.g. one can do things like T[3] a = [ 1, 2, 3 ], but I'd like to be able
> to do T[N] = SomeInitializerForArrayOfNElements;
>
> What I'm trying to achieve is:
>
> 1. Initialize T[N] elements to a specific value.
> 2. Initialize every element of T[N] to some value deduced at compile time
> using it's index.
>
> I came up with the templates in my initial post. They seem to work, but I doubt those are legal solutions.
>

If they work, then they are legal :)

If I understand correctly what you want, you can achieve it with compile-time-evaluable functions:

module main;
import std.stdio;

/**
return a T[N] with all elements equal to t.
*/
T[N] initializeWith(T, size_t N)(T t) if (N>0)
{
    T[N] result;
    foreach(i, _; result)
    {
        result[i] = t;
    }
    return result;
}

/**
Returns a T[N] with all elements equal to foo(index)
*/
T[N] initializeWith(alias fun, T, size_t N)() if (N>0)
{
    T[N] result;
    foreach(i, _; result)
    {
        result[i] = fun(i);
    }
    return result;
}

int foo(int i) { return i*i;}

struct S
{
    static immutable int[10] arr = initializeWith!(foo, int, 10);
}

void main()
{
    auto a = initializeWith!(int,10)(8);

    writeln(a);
    a = initializeWith!(foo,int,10);
    writeln(a);
    S s;
    writeln(s.arr);
}

Does that work for you?

Philippe


August 26, 2010
 Sorry, I pressed the wrong button so the message was sent to your email. Reciting:

 26.08.2010 1:53, Philippe Sigaud wrote:
>
>
>     I came up with the templates in my initial post. They seem to
>     work, but I doubt those are legal solutions.
>
>     .
>
>
> If they work, then they are legal :)
>
How it would be better for us all if we could always say that :)
> If I understand correctly what you want, you can achieve it with compile-time-evaluable functions:
>
> Does that work for you?
>
Yes! Beautiful, thanks! That beats hell out of my clumsy templates :)

When I was on the way to my initial solutions I was under strong impression that T[N] func() won't work. Now I see that was because I didn't bother to fully understand how arrays are returned from functions. I got it now, so thanks a lot again!

August 26, 2010
On Thu, Aug 26, 2010 at 14:11, Stanislav Blinov <blinov@loniir.ru> wrote:

>  Sorry, I pressed the wrong button so the message was sent to your email.
> Reciting:
>
>
> Does that work for you?
>>
>>  Yes! Beautiful, thanks! That beats hell out of my clumsy templates :)
>

Your templates are not clumsy, it's typically the way some other PL would process lists/arrays. I used to write a lot of these. But 6 months ago, CTFE got seven-leagues boots and right now it's much easier on the eye to use CT functions.


>
> When I was on the way to my initial solutions I was under strong impression that T[N] func() won't work. Now I see that was because I didn't bother to fully understand how arrays are returned from functions. I got it now, so thanks a lot again!
>

There used to be a time, maybe not 18 months ago where returning static arrays from functions was not possible, IIRC. Right now, I think you can use them with no problem. Maybe someone well-versed in optimization will tell us it's not a good idea, I don't know.


Philippe


August 26, 2010
Philippe Sigaud wrote:
> 
> That beats hell out of my clumsy templates :)
> 
> 
> Your templates are not clumsy, it's typically the way some other PL would process lists/arrays. I used to write a lot of these. But 6 months ago, CTFE got seven-leagues boots and right now it's much easier on the eye to use CT functions.
>

Thanks for friendly shoulder tap :)
I think I just need to get accustomed with CTFE. I mostly work in C++, and it's templates (much inspired by Andrei's C++ publications as well as Loki, by the way) are telling on me. I constantly tend to forget there are so many constructs in D I can use at compile time without worry.

> 
> 
>     When I was on the way to my initial solutions I was under strong
>     impression that T[N] func() won't work. Now I see that was because I
>     didn't bother to fully understand how arrays are returned from
>     functions. I got it now, so thanks a lot again!
> 
> 
> There used to be a time, maybe not 18 months ago where returning static arrays from functions was not possible, IIRC.. 

This may have something to do with my assumptions. I haven't tried D much since when shared was introduced (don't remember how long ago it was).

> Right now, I think you can use them with no problem. Maybe someone well-versed in optimization will tell us it's not a good idea, I don't know.

Well, as you've said yourself, if it works... :)

PS. I'm not sure as to where to post this, but after I tried your solution I've noticed one interesting (or rather strange) thing:

struct S(T,size_t N)
{
	T[N] arr;
	int foo;	// type doesn't seem to matter here,
			// taking int for clarity

	static immutable S C1   =   { initializeWith!(T,N)(0) 5 };
	// Note there is no comma after first initializer    ^
}

This actually compiles and works, though I have an impression that syntax error is in order. Putting in second array and attempting similar initialization without commas leads to one. I've only tried it with Windows 2.048, though I think the front end would eat this on Linux too. Is this valid, already known or I should report this?
August 26, 2010
On Thu, Aug 26, 2010 at 23:49, Stanislav Blinov <stanislav.blinov@gmail.com>wrote:

> struct S(T,size_t N)
> {
>        T[N] arr;
>        int foo;        // type doesn't seem to matter here,
>                        // taking int for clarity
>
>        static immutable S C1   =   { initializeWith!(T,N)(0) 5 };
>        // Note there is no comma after first initializer    ^
> }
>
> This actually compiles and works, though I have an impression that syntax error is in order. Putting in second array and attempting similar initialization without commas leads to one. I've only tried it with Windows 2.048, though I think the front end would eat this on Linux too. Is this valid, already known or I should report this?
>

Dunno, I never use the = { ... } syntax to create structs. I always do =
S(...);
I even thought the literal syntax was being deprecated. Maybe I'm mistaken.

In any case, please report this.


August 26, 2010
Philippe Sigaud wrote:
>     I have an impression that
>     syntax error is in order. Putting in second array and attempting
>     similar initialization without commas leads to one. I've only tried
>     it with Windows 2.048, though I think the front end would eat this
>     on Linux too. Is this valid, already known or I should report this?
> 
> 
> Dunno, I never use the = { ... } syntax to create structs. I always do = S(...);
> I even thought the literal syntax was being deprecated. Maybe I'm mistaken.
> 
> In any case, please report this.
> 

Ok, I'll do that once I narrow it down to anything meaningful (I've found that behavior on 2.047 Linux is somewhat different).
August 28, 2010
Done:

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