Home > Enterprise >  How to get the valid bit length of long double in C ?
How to get the valid bit length of long double in C ?

Time:12-27

Via std::numeric_limits, we can get some kinds of information of long double, such as max/min value. And the memory usage could be get by sizeof(long double).

But the valid bytes/bits of long double is not specified in C standard, it may be 80/96/128 or others, So is there a compile-time method to get the valid bit length?

A portable method is better.

void dump(auto x)
{
    auto vss = bit_cast<bitset<sizeof(x) * 8>>(x);
    cout << vss.to_string().substr(0, 48) << ' ' << vss.to_string().substr(48) << endl;
}

int main(int argc, char const *argv[])
{

    long double x = 0;

    dump(x);
    dump(-x);

    return 0;
}

On x86-64, you would see only the 79th bit has been fliped. So there are only 80 bits of all 128 bits is valid.

CodePudding user response:

#include <bit>
#include <cstddef>

constinit size_t valid_bits = []
{
    long double zero{};

    struct long_double_bytes
    {
        unsigned char b[sizeof(long double)];
    };

    long_double_bytes x = std::bit_cast<long_double_bytes>(zero);
    long_double_bytes y = std::bit_cast<long_double_bytes>(-zero);

    for (size_t i = 0; i < sizeof(long double); i  )
    {
        x.b[i] ^= y.b[i];
    }

    size_t r = 0, i;
    for (i = 0; i < sizeof(long double) && !x.b[i]; i  )
    {
        r  = 8;
    }
    for (size_t j = 0; j < 8 && !((x.b[i] >> j) & 1); j  )
    {
        r  ;
    }

    return r   1;
}();

A compile-time solution.

CodePudding user response:

Isn't just counting parts bits enough?

Along the lines

#include <iostream>
#include <cfloat>

static unsigned int ilog2(unsigned int val) {
    if (val == 0) return UINT_MAX;
    if (val == 1) return 0;
    unsigned int ret = 0;
    while (val > 1) {
        val >>= 1;
        ret  ;
    }
    return ret;
}

int main() {
    unsigned int bitsinLDBL = LDBL_MANT_DIG; // mantissa
    bitsinLDBL  = ilog2(LDBL_MAX_EXP);       // exponent
    bitsinLDBL  = 1u;                        // sign bit

    std::cout << bitsinLDBL << " " << bitsinLDBL/CHAR_BIT << '\n';
    return 0;
}
  •  Tags:  
  • c
  • Related