www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mapping float to ulong in CTFE

reply berni44 <dlang d-ecke.de> writes:
Is it possible to get to the bits of a float in CTFE? I tried the 
following, but this doesn't work:

```
import std.stdio;

union FloatBits
{
     float floatValue;
     ulong ulongValue;
}

ulong test(float f)
{
     FloatBits fb;
     fb.floatValue = f;
     return fb.ulongValue;
}

void main()
{
     static assert(test(3.0) == 1077936128);
}
```

test.d(13): Error: reinterpretation through overlapped field 
ulongValue is not allowed in CTFE
test.d(18):        called from here: test(3.00000F)
test.d(18):        while evaluating: static assert(test(3.00000F) 
== 1077936128LU)
Dec 12 2019
parent reply Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Thursday, 12 December 2019 at 19:21:22 UTC, berni44 wrote:
 Is it possible to get to the bits of a float in CTFE? I tried 
 the following, but this doesn't work:

 ```
 import std.stdio;

 union FloatBits
 {
     float floatValue;
     ulong ulongValue;
 }

 ulong test(float f)
 {
     FloatBits fb;
     fb.floatValue = f;
     return fb.ulongValue;
 }

 void main()
 {
     static assert(test(3.0) == 1077936128);
 }
 ```

 test.d(13): Error: reinterpretation through overlapped field 
 ulongValue is not allowed in CTFE
 test.d(18):        called from here: test(3.00000F)
 test.d(18):        while evaluating: static 
 assert(test(3.00000F) == 1077936128LU)
You can use a C-style pointer reinterpret cast like this: uint test(float f) { return *cast(uint*)&f; } Make sure that source and destination types have the same size. Or more generally: IntegerOfSize!T bitRepresentation(T)(T f) { return *cast(IntegerOfSize!T*)&f; } pragma (msg, bitRepresentation(3.0f)); // 1077936128u pragma (msg, bitRepresentation(3.0)); // 4613937818241073152LU void main() { static assert(bitRepresentation(3.0f) == 1077936128); } template IntegerOfSize(T) { static if (T.sizeof == 1) alias IntegerOfSize = ubyte; else static if (T.sizeof == 2) alias IntegerOfSize = ushort; else static if (T.sizeof == 4) alias IntegerOfSize = uint; else static if (T.sizeof == 8) alias IntegerOfSize = ulong; else static assert(0); }
Dec 12 2019
parent reply berni44 <dlang d-ecke.de> writes:
On Thursday, 12 December 2019 at 19:39:16 UTC, Petar Kirov 
[ZombineDev] wrote:
 You can use a C-style pointer reinterpret cast like this:

 uint test(float f) { return *cast(uint*)&f; }

 Make sure that source and destination types have the same size.
Hey, great! :-)
Dec 13 2019
parent berni44 <dlang d-ecke.de> writes:
Yeah, it worked (at least for %a):

static assert(format!"%.3a"(1.0f) == "0x1.000p+0");
Dec 13 2019