0

To implement Block floating point, I'm using the following structure in my code:

struct ff32{
    int16_t _exp;
    int32_t _frac;

    ff32(int16_t e, int32_t f)
        : _exp(e), _frac(f)
    {};
};

I can instantiate variables of this structure type and initialized them as follow:

ff32 x(2, 0x60000000);
ff32 y = {2, 0x60000000};

I'd like to extend the constructor to include float data type as follow:

struct ff32{
    int16_t _exp;
    int32_t _frac;

    ff32(int16_t e, int32_t f)
        : _exp(e), _frac(f)
    {};

    ff32(float x)
    {
        // some code that extract _exp and _frac 
        // for a given floating-point number x
    };
};

I've already implemented the body of the constructor ff32(float x) but I don't want this code to be executed at run-time for constant float arguments, e.g. ff32(2.7f). Is it possible to achieve this using some kind of meta-programming? I should also mention that my tool-chain only supports C++11.

m.s.
  • 16,063
  • 7
  • 53
  • 88
Ali
  • 288
  • 3
  • 10
  • what does `I don't want this code to be executed at run-time` mean? do you want to perform compile time computation? – m.s. Dec 08 '18 at 11:38
  • 1
    As you use run-time variables, it makes no sense to do any computation for setting them in compile-time. Everything the compiler already optimizes seems to be enough. If you "variables" becomes compile time constants, you can think about compile time math. giving constexpr to the constructor give the compiler an additional hint for optimization possibilities. – Klaus Dec 08 '18 at 12:21

1 Answers1

1

No meta-programming is needed here.

The function ff32(float x) will be created in any case, but as Klaus mentioned, you can rely on compiler optimization to replace it's result on constexpr floats with the respective values without calling the function in run-time. Simply use the following calculations (that can be performed in compilation-time):

struct float32{
    unsigned const bits;
    unsigned const exponent;
    unsigned const fraction;
    bool const sign;

    constexpr float32(float input_float):
        bits(*reinterpret_cast<unsigned*>(&input_float)),
        exponent((bits & 0x7f800000) >> 23),
        fraction((bits & 0x007fffff)),
        sign((bits & 0x80000000) > 0)
    {}
};

you can watch the assembly your code compiles to here. Make sure to use the -O3 flag and see how this works on constexpr floats.

Benny K
  • 868
  • 6
  • 18
  • maybe declare the constructors constexpr and use mem-initializers instead, gets the point across more clearly – Yamahari Feb 05 '19 at 11:49
  • also with static cast you avoid warning about narrowing conversions https://godbolt.org/z/uvWY1T – Yamahari Feb 05 '19 at 11:52