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;
}