在编译时初始化double

Initializing double at compile-time

本文关键字:double 初始化 编译      更新时间:2023-10-16

我正在通过模板元编程编写浮点运算的编译时实现。我的实现具有以下特点:

  • 16位有符号整数指数。
  • 32位无符号整数尾数,没有隐含的最高有效1(这样做是为了简化调试)。

类型如下:

template<bool S , std::int16_t E , std::uint32_t M>
struct number
{
    static constexpr const bool          sign     = S;
    static constexpr const std::int16_t  exponent = E;
    static constexpr const std::uint32_t mantissa = M;
};

操作工作得很好,但是现在我需要一个方法来在编译时提取这些值并获得相应的double值。由于编译时算法的目标是加快计算速度,将解直接注入可执行程序,因此我需要一种方法来在编译时有效地初始化双常量。所以涉及std::pow( 2.0 , E )的简单解是不允许的。

据我所知,双精度IEE754浮点数具有10位带符号指数和53位无符号整数尾号。我尝试的解决方案是通过联合使用类型双关语:

template<bool S , std::int16_t E , std::uint32_t M>
struct to_runtime<tml::floating::number<S,E,M>>
{
    static constexpr const long unsigned int mantissa = M << (53 - 32);
    static constexpr const               int exponent = E + (53 - 32);

    struct double_parts 
    {
             unsigned int sign     : 1;
                      int exponent : 10;
        long unsigned int mantissa : 53;
    };
    union double_rep
    {
        double d;
        double_parts parts;
    };
    static constexpr const double_parts parts = { .sign = ((bool)S) ? 0 : 1 , .exponent = exponent , .mantissa = mantissa };
    static constexpr const double_rep   rep   = { .parts = parts };
    static constexpr double execute()
    {
        return rep.d;
    }
};

但是这个解决方案是不可移植的,调用未定义的行为(因为在做类型双关语时,我们读取尚未写入的联合成员),而且在实现转换时我也有一些问题(这个解决方案不返回正确的数字)。

是否有其他方法来初始化double在编译时给定我的数据(符号,指数,尾数)?

您可以实现constexpr pow2(std::int16_t),如:

constexpr double pow2(std::int16_t e)
{
    return e == 0 ? 1. :
            e > 0 ? 2. * pow2(std::int16_t(e - 1)) :
                    0.5 * pow2(std::int16_t(e + 1));
}

constexpr double pow2(std::int16_t e)
{
    return e == 0 ? 1. :
                    ((e & 1) ? (e > 0 ? 2. : 0.5) : 1.)
                    * pow2(std::int16_t(e / 2))
                    * pow2(std::int16_t(e / 2));
}

template<bool S , std::int16_t E , std::uint32_t M>
struct number
{
    static constexpr const double value = (sign ? -1. : 1.) * M * pow2(E);
};

生活例子

相关文章: