www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - wth!! ctfe cannot format floating point at compile time?

reply Johnson Jones <JJ Dynomite.com> writes:
Error: uncaught CTFE exception std.format.FormatException("Cannot 
format floating point types at compile-time")
called from here: to(0.75)

pretty simply, trying to convert a floating point to a string in 
a ctfe function and it thinks that it is too complex to do in a 
ctfe, really?
Aug 13
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 14 August 2017 at 01:52:16 UTC, Johnson Jones wrote:
 pretty simply, trying to convert a floating point to a string 
 in a ctfe function and it thinks that it is too complex to do 
 in a ctfe, really?
It uses a C function to do the conversion, which is not available at compile time since CTFE can't run extern functions. And it is a LOT harder to do than you might think which is why it still uses the C function - implementing one in D is legit pretty complex. When I first saw this too, I figured it must be simple to slap something together, even if it is horribly inefficient and doesn't work everywhere... and I ended up giving up after spending a few hours on it too. If you search the web, you get academic papers describing it, eeek. Of course, it might be reasonable to port one of the C implementations directly... but even that is a fairly big job (and you might as well just call the C function itself for all but CTFE cases) - the GNU one is 1,300 lines, for example. And that has an incompatible license with the rest of druntime!
Aug 13
next sibling parent Johnson <Johnson Johnson.com> writes:
On Monday, 14 August 2017 at 03:44:27 UTC, Adam D. Ruppe wrote:
 On Monday, 14 August 2017 at 01:52:16 UTC, Johnson Jones wrote:
 pretty simply, trying to convert a floating point to a string 
 in a ctfe function and it thinks that it is too complex to do 
 in a ctfe, really?
It uses a C function to do the conversion, which is not available at compile time since CTFE can't run extern functions. And it is a LOT harder to do than you might think which is why it still uses the C function - implementing one in D is legit pretty complex. When I first saw this too, I figured it must be simple to slap something together, even if it is horribly inefficient and doesn't work everywhere... and I ended up giving up after spending a few hours on it too. If you search the web, you get academic papers describing it, eeek. Of course, it might be reasonable to port one of the C implementations directly... but even that is a fairly big job (and you might as well just call the C function itself for all but CTFE cases) - the GNU one is 1,300 lines, for example. And that has an incompatible license with the rest of druntime!
I don't believe that! Just run dmd on it like ctfe does. Maybe the problem is that to should be a bit more intelligent and if it is ran at ctfe should try something else. I don't see why it would be all that difficult maybe for complex floating point numbers it is but for most ordinary numbers used as most literals(e.g., terminating decimals), it is very very easy to convert. It is not much more difficult than storing it as a string. After all 0.43425 is actually a string that will be converted to fp. I realize there are accuracy issues but I seriously think there should be something suitable rather than crapping out ;/ e.g., 0.43425 = 43425/100000. Remember, we are converting a literal string represented floating point value to a string. It should be a direct conversion. Basically a copy and paste. (at run time, it is different, obviously since the value is actually a fp, but at compile time it is simply a string. There is this trick as workaround: As HypperParrow says, it's easy as pi: ``` auto valueToString(alias v)(){return v.stringof;} enum a = valueToString!(0.75); static assert(a == "0.75"); ``` to!string(float) should detect that and just do it. No need to try to do anything complex.
Aug 13
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/13/17 11:44 PM, Adam D. Ruppe wrote:
 On Monday, 14 August 2017 at 01:52:16 UTC, Johnson Jones wrote:
 pretty simply, trying to convert a floating point to a string in a 
 ctfe function and it thinks that it is too complex to do in a ctfe, 
 really?
It uses a C function to do the conversion, which is not available at compile time since CTFE can't run extern functions. And it is a LOT harder to do than you might think which is why it still uses the C function - implementing one in D is legit pretty complex. When I first saw this too, I figured it must be simple to slap something together, even if it is horribly inefficient and doesn't work everywhere... and I ended up giving up after spending a few hours on it too. If you search the web, you get academic papers describing it, eeek. Of course, it might be reasonable to port one of the C implementations directly... but even that is a fairly big job (and you might as well just call the C function itself for all but CTFE cases) - the GNU one is 1,300 lines, for example. And that has an incompatible license with the rest of druntime!
Another reasonable idea is to have the compiler call the function for you. Since the compiler only ever exists on platforms with libc available, the libc function is available to the compiler too. having some special intrinsic to format floating points wouldn't be out of the question. It is quite limiting to have floating point string conversions not available. -Steve
Aug 14
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 14 August 2017 at 13:11:20 UTC, Steven Schveighoffer 
wrote:
 Another reasonable idea is to have the compiler call the 
 function for you.
Yeah, I was thinking that too. Heck, the compiler prolly uses it for reading source and writing errors. Perhaps just special case hack the function it uses in the ctfe engine.
Aug 14
prev sibling parent reply HypperParrow <yaya abc.de> writes:
On Monday, 14 August 2017 at 01:52:16 UTC, Johnson Jones wrote:
 Error: uncaught CTFE exception 
 std.format.FormatException("Cannot format floating point types 
 at compile-time")
 called from here: to(0.75)

 pretty simply, trying to convert a floating point to a string 
 in a ctfe function and it thinks that it is too complex to do 
 in a ctfe, really?
There is this trick as workaround: ``` auto valueToString(alias v)(){return v.stringof;} enum a = valueToString!(0.75); static assert(a == "0.75"); ``` The problem with to() and format() is that is requires external library calls that are not available at compile-time, just like when you try to use malloc() at CT.
Aug 13
parent reply Johnson <Johnson Johnson.com> writes:
On Monday, 14 August 2017 at 03:52:40 UTC, HypperParrow wrote:
 On Monday, 14 August 2017 at 01:52:16 UTC, Johnson Jones wrote:
 Error: uncaught CTFE exception 
 std.format.FormatException("Cannot format floating point types 
 at compile-time")
 called from here: to(0.75)

 pretty simply, trying to convert a floating point to a string 
 in a ctfe function and it thinks that it is too complex to do 
 in a ctfe, really?
There is this trick as workaround: ``` auto valueToString(alias v)(){return v.stringof;} enum a = valueToString!(0.75); static assert(a == "0.75"); ``` The problem with to() and format() is that is requires external library calls that are not available at compile-time, just like when you try to use malloc() at CT.
Thanks! You'd think that to would do this internally automatically ;/
Aug 13
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Monday, 14 August 2017 at 04:29:17 UTC, Johnson wrote:

 ```
 auto valueToString(alias v)(){return v.stringof;}
 enum a = valueToString!(0.75);
 static assert(a == "0.75");
 ```
Thanks! You'd think that to would do this internally automatically ;/
It only works on literals. valueToString!(a) will give you a;
Aug 14