Jump to page: 1 2
Thread overview
At compile time
Aug 04, 2009
bearophile
Aug 05, 2009
bearophile
Aug 05, 2009
bearophile
Aug 05, 2009
Ary Borenszweig
Aug 06, 2009
Don
[OT] Re: At compile time
Aug 05, 2009
BCS
Aug 05, 2009
Don
Aug 21, 2009
Don
Aug 22, 2009
bearophile
Aug 24, 2009
Don
Aug 05, 2009
div0
Aug 06, 2009
Sergey Gromov
August 04, 2009
D2 is now able to execute math functions (sin, cos, sqrt, etc) at compile time.

This little C++ program compiles correctly with G++:

// C++ code
#include <math.h>
#include <stdio.h>

struct V3 {
    double x, y, z;
    V3(const double a, const double b, const double c) : x(a), y(b), z(c) {}
    V3 operator*(const double d) const { return V3(x * d, y * d, z * d); }
    V3 norm() const { return *this * (1.0 / sqrt(magsqr())); }
    double dot(const V3 &v) const { return x * v.x+y * v.y + z * v.z; }
    double magsqr() const { return dot(*this); }
};

const V3 v(V3(-0.5, -0.65, 0.9).norm());

int main() {
    printf("%f %f %f\n", v.x, v.y, v.z);
    return 0;
}


But similar D2 program produces, with DMD v.2.031:
test.d(12): Error: non-constant expression (V3(1,2,3)).norm()

// D2 code
import std.math, std.c.stdio;

struct V3 {
    double x, y, z;
    V3 opMul(double d) { return V3(x * d, y * d, z * d); }
    V3 norm() { return this * (1.0 / sqrt(this.magsqr())); }
    double dot(ref V3 v) { return x * v.x+y * v.y + z * v.z; }
    double magsqr() { return dot(this); }
}

const V3 v = V3(1.0, 2.0, 3.0).norm();

int main() {
    printf("%f %f %f\n", v.x, v.y, v.z);
    return 0;
}

Do you know why?
Can the D2 compiler modified/improved to allow this?

Bye and thank you,
bearophile
August 05, 2009
On Tue, Aug 4, 2009 at 7:57 PM, bearophile<bearophileHUGS@lycos.com> wrote:
> D2 is now able to execute math functions (sin, cos, sqrt, etc) at compile time.
>
> This little C++ program compiles correctly with G++:
>
> // C++ code
> #include <math.h>
> #include <stdio.h>
>
> struct V3 {
>    double x, y, z;
>    V3(const double a, const double b, const double c) : x(a), y(b), z(c) {}
>    V3 operator*(const double d) const { return V3(x * d, y * d, z * d); }
>    V3 norm() const { return *this * (1.0 / sqrt(magsqr())); }
>    double dot(const V3 &v) const { return x * v.x+y * v.y + z * v.z; }
>    double magsqr() const { return dot(*this); }
> };
>
> const V3 v(V3(-0.5, -0.65, 0.9).norm());
>
> int main() {
>    printf("%f %f %f\n", v.x, v.y, v.z);
>    return 0;
> }
>
>
> But similar D2 program produces, with DMD v.2.031:
> test.d(12): Error: non-constant expression (V3(1,2,3)).norm()
>
> // D2 code
> import std.math, std.c.stdio;
>
> struct V3 {
>    double x, y, z;
>    V3 opMul(double d) { return V3(x * d, y * d, z * d); }
>    V3 norm() { return this * (1.0 / sqrt(this.magsqr())); }
>    double dot(ref V3 v) { return x * v.x+y * v.y + z * v.z; }
>    double magsqr() { return dot(this); }
> }
>
> const V3 v = V3(1.0, 2.0, 3.0).norm();
>
> int main() {
>    printf("%f %f %f\n", v.x, v.y, v.z);
>    return 0;
> }
>
> Do you know why?

I don't think you can call struct methods at compile-time.  Kind of lame, I know.  Try making norm a free function.

> Can the D2 compiler modified/improved to allow this?

It sure would be nice.
August 05, 2009
Jarrett Billingsley:
> I don't think you can call struct methods at compile-time.  Kind of lame, I know.  Try making norm a free function.

I see. It's a significant limitation, that curiously G++ doesn't share.
I have tried to follow your suggestion, but so far with not too much luck, even essentially pulling out all methods of that struct :-)

Thank you,
bye,
bearophile
August 05, 2009
On Tue, Aug 4, 2009 at 10:13 PM, bearophile<bearophileHUGS@lycos.com> wrote:
> Jarrett Billingsley:
>> I don't think you can call struct methods at compile-time.  Kind of lame, I know.  Try making norm a free function.
>
> I see. It's a significant limitation, that curiously G++ doesn't share.

I don't think your C++ code is doing what you think it's doing.  I'm pretty sure the C++ code:

const V3 v(V3(-0.5, -0.65, 0.9).norm());

is equivalent to the following D code:

const V3 v;
static this() { v = V3(-0.5, -0.65, 0.9).norm(); }

C++ has static initialization that occurs before main() too.  It's
just.. hidden.
August 05, 2009
Jarrett Billingsley wrote:
> I don't think you can call struct methods at compile-time.  Kind of
> lame, I know.  Try making norm a free function.
> 
>> Can the D2 compiler modified/improved to allow this?
> 
> It sure would be nice.

In fact the D1 compiler should support it too.
BTW a few of the restrictions on CTFE will be removed in the next release.
August 05, 2009
Don wrote:
> Jarrett Billingsley wrote:
>> I don't think you can call struct methods at compile-time.  Kind of
>> lame, I know.  Try making norm a free function.
>>
>>> Can the D2 compiler modified/improved to allow this?
>>
>> It sure would be nice.
> 
> In fact the D1 compiler should support it too.
> BTW a few of the restrictions on CTFE will be removed in the next release.


This is good news! The restrictions you are referring to, are they any of the ones documented here:

    http://www.digitalmars.com/d/2.0/function.html#interpretation

or are they "undocumented" restrictions, i.e. bugs?

-Lars
August 05, 2009
Jarrett Billingsley:
>C++ has static initialization that occurs before main() too.  It's just.. hidden.<

I see. I have to learn more about C++. Thank you.

------------------
Lars T. Kyllingstad:

>This is good news! The restrictions you are referring to, are they any of the ones documented here: http://www.digitalmars.com/d/2.0/function.html#interpretation <

That list has a point regarding what I was trying to do:
>4. the function may not be a non-static member, i.e. it may not have a this pointer<
It's true regarding stucts used as values too, and not just classes...

Bye,
bearophile
August 05, 2009
bearophile escribió:
> Jarrett Billingsley:
>> C++ has static initialization that occurs before main() too.  It's just.. hidden.<
> 
> I see. I have to learn more about C++. Thank you.
> 
> ------------------
> Lars T. Kyllingstad:
> 
>> This is good news! The restrictions you are referring to, are they any of the ones documented here: http://www.digitalmars.com/d/2.0/function.html#interpretation <
> 
> That list has a point regarding what I was trying to do:
>> 4. the function may not be a non-static member, i.e. it may not have a this pointer<
> It's true regarding stucts used as values too, and not just classes...

It would be nice if the compiler could say so: "I can't evaluate it because you are using a this pointer". With other words, but much more useful than "non-constant expression".
August 05, 2009
*On Wed, Aug 5, 2009 at 7:23 AM, Ary Borenszweig<ary@esperanto.org.ar> wrote:
> bearophile escribió:
>>
>> Jarrett Billingsley:
>>>
>>> C++ has static initialization that occurs before main() too.  It's just..
>>> hidden.<
>>
>> I see. I have to learn more about C++. Thank you.
>>
>> ------------------
>> Lars T. Kyllingstad:
>>
>>> This is good news! The restrictions you are referring to, are they any of the ones documented here: http://www.digitalmars.com/d/2.0/function.html#interpretation <
>>
>> That list has a point regarding what I was trying to do:
>>>
>>> 4. the function may not be a non-static member, i.e. it may not have a this pointer<
>>
>> It's true regarding stucts used as values too, and not just classes...
>
> It would be nice if the compiler could say so: "I can't evaluate it because you are using a this pointer". With other words, but much more useful than "non-constant expression".

Yes, oh my God, this is the main reason I don't use CTFE: debugging them is virtually impossible, and the compiler does nothing to help there.
August 05, 2009
bearophile wrote:

> D2 is now able to execute math functions (sin, cos, sqrt, etc) at compile time.
> 
> This little C++ program compiles correctly with G++:
> 
> // C++ code
> #include <math.h>
> #include <stdio.h>
> 
> struct V3 {
>     double x, y, z;
>     V3(const double a, const double b, const double c) : x(a), y(b), z(c) {}
>     V3 operator*(const double d) const { return V3(x * d, y * d, z * d); }
>     V3 norm() const { return *this * (1.0 / sqrt(magsqr())); }
>     double dot(const V3 &v) const { return x * v.x+y * v.y + z * v.z; }
>     double magsqr() const { return dot(*this); }
> };
> 
> const V3 v(V3(-0.5, -0.65, 0.9).norm());
> 
> int main() {
>     printf("%f %f %f\n", v.x, v.y, v.z);
>     return 0;
> }

<snip>

> Do you know why?
> Can the D2 compiler modified/improved to allow this?
> 
> Bye and thank you,
> bearophile

Not really relevant to the compile time issue but, your d2 code should be:

import std.math;
import std.stdio;

struct V3 {
    double x, y, z;

	this(double _x, double _y, double _z) {
		x = _x;
		y = _y;
		z = _z;
	}
    V3 opMul(double d) const	{ return V3(x * d, y * d, z * d); }
    V3 norm() const 		{ return this * (1.0 / sqrt(this.magsqr())); }
    double dot(ref V3 v) const	{ return x * v.x+y * v.y + z * v.z; }
    double magsqr()	const		{ return dot(this); }
}

const V3 v;

static this() {
	v = V3(1.0, 2.0, 3.0).norm();
}

int main() {
    writefln("%f %f %f", v.x, v.y, v.z);
    writefln("%f", v.magsqr());
    return 0;
}

This produces identical behavior to the c++ example.

As Jarrett said, in c++ you have hidden runtime initialisation, which is made explicit in D.

Having it work at compile time would be sweet.

- --
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk
« First   ‹ Prev
1 2