bit_layouts.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright 2023 Matt Borland
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // https://www.boost.org/LICENSE_1_0.txt
  4. #ifndef BOOST_CHARCONV_DETAIL_BIT_LAYOUTS_HPP
  5. #define BOOST_CHARCONV_DETAIL_BIT_LAYOUTS_HPP
  6. #include <boost/charconv/detail/config.hpp>
  7. #include <boost/charconv/detail/emulated128.hpp>
  8. #include <cstdint>
  9. #include <cfloat>
  10. // Layouts of floating point types as specified by IEEE 754
  11. // See page 23 of IEEE 754-2008
  12. namespace boost { namespace charconv { namespace detail {
  13. struct ieee754_binary16
  14. {
  15. static constexpr int significand_bits = 10;
  16. static constexpr int exponent_bits = 5;
  17. static constexpr int min_exponent = -14;
  18. static constexpr int max_exponent = 15;
  19. static constexpr int exponent_bias = -15;
  20. static constexpr int decimal_digits = 5;
  21. };
  22. struct brainfloat16
  23. {
  24. static constexpr int significand_bits = 7;
  25. static constexpr int exponent_bits = 8;
  26. static constexpr int min_exponent = -126;
  27. static constexpr int max_exponent = 127;
  28. static constexpr int exponent_bias = -127;
  29. static constexpr int decimal_digits = 4;
  30. };
  31. struct ieee754_binary32
  32. {
  33. static constexpr int significand_bits = 23;
  34. static constexpr int exponent_bits = 8;
  35. static constexpr int min_exponent = -126;
  36. static constexpr int max_exponent = 127;
  37. static constexpr int exponent_bias = -127;
  38. static constexpr int decimal_digits = 9;
  39. };
  40. struct ieee754_binary64
  41. {
  42. static constexpr int significand_bits = 52;
  43. static constexpr int exponent_bits = 11;
  44. static constexpr int min_exponent = -1022;
  45. static constexpr int max_exponent = 1023;
  46. static constexpr int exponent_bias = -1023;
  47. static constexpr int decimal_digits = 17;
  48. };
  49. // 80 bit long double (e.g. x86-64)
  50. #if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
  51. struct IEEEl2bits
  52. {
  53. #if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
  54. std::uint64_t mantissa_l : 64;
  55. std::uint32_t exponent : 15;
  56. std::uint32_t sign : 1;
  57. std::uint64_t pad : 48;
  58. #else // Big endian
  59. std::uint64_t pad : 48;
  60. std::uint32_t sign : 1;
  61. std::uint32_t exponent : 15;
  62. std::uint64_t mantissa_h : 64;
  63. #endif
  64. };
  65. struct ieee754_binary80
  66. {
  67. static constexpr int significand_bits = 64; // Fraction is 63 and 1 integer bit
  68. static constexpr int exponent_bits = 15;
  69. static constexpr int min_exponent = -16382;
  70. static constexpr int max_exponent = 16383;
  71. static constexpr int exponent_bias = -16383;
  72. static constexpr int decimal_digits = 18;
  73. };
  74. #define BOOST_CHARCONV_LDBL_BITS 80
  75. // 128 bit long double (e.g. s390x, ppcle64)
  76. #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
  77. struct IEEEl2bits
  78. {
  79. #if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
  80. std::uint64_t mantissa_l : 64;
  81. std::uint64_t mantissa_h : 48;
  82. std::uint32_t exponent : 15;
  83. std::uint32_t sign : 1;
  84. #else // Big endian
  85. std::uint32_t sign : 1;
  86. std::uint32_t exponent : 15;
  87. std::uint64_t mantissa_h : 48;
  88. std::uint64_t mantissa_l : 64;
  89. #endif
  90. };
  91. #define BOOST_CHARCONV_LDBL_BITS 128
  92. // 64 bit long double (double == long double on ARM)
  93. #elif LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
  94. struct IEEEl2bits
  95. {
  96. #if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
  97. std::uint32_t mantissa_l : 32;
  98. std::uint32_t mantissa_h : 20;
  99. std::uint32_t exponent : 11;
  100. std::uint32_t sign : 1;
  101. #else // Big endian
  102. std::uint32_t sign : 1;
  103. std::uint32_t exponent : 11;
  104. std::uint32_t mantissa_h : 20;
  105. std::uint32_t mantissa_l : 32;
  106. #endif
  107. };
  108. #define BOOST_CHARCONV_LDBL_BITS 64
  109. #else // Unsupported long double representation
  110. # define BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE
  111. # define BOOST_CHARCONV_LDBL_BITS -1
  112. #endif
  113. struct IEEEbinary128
  114. {
  115. #if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
  116. std::uint64_t mantissa_l : 64;
  117. std::uint64_t mantissa_h : 48;
  118. std::uint32_t exponent : 15;
  119. std::uint32_t sign : 1;
  120. #else // Big endian
  121. std::uint32_t sign : 1;
  122. std::uint32_t exponent : 15;
  123. std::uint64_t mantissa_h : 48;
  124. std::uint64_t mantissa_l : 64;
  125. #endif
  126. };
  127. struct ieee754_binary128
  128. {
  129. static constexpr int significand_bits = 112;
  130. static constexpr int exponent_bits = 15;
  131. static constexpr int min_exponent = -16382;
  132. static constexpr int max_exponent = 16383;
  133. static constexpr int exponent_bias = 16383;
  134. static constexpr int decimal_digits = 33;
  135. };
  136. }}} // Namespaces
  137. #endif // BOOST_CHARCONV_DETAIL_BIT_LAYOUTS_HPP