Thread overview
Mapping float to ulong in CTFE
Dec 12, 2019
berni44
Dec 13, 2019
berni44
Dec 13, 2019
berni44
December 12, 2019
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)
December 12, 2019
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);
}
December 13, 2019
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! :-)
December 13, 2019
Yeah, it worked (at least for %a):

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