File indexing completed on 2026-08-06 09:00:33
0001
0002
0003 #ifndef BOOST_MATH_FP_TRAITS_HPP
0004 #define BOOST_MATH_FP_TRAITS_HPP
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT
0020
0021 # define BOOST_FPCLASSIFY_VAX_FORMAT
0022 #endif
0023
0024 #include <cstring>
0025 #include <cstdint>
0026 #include <limits>
0027 #include <type_traits>
0028 #include <boost/math/tools/config.hpp>
0029 #include <boost/math/tools/is_standalone.hpp>
0030 #include <boost/math/tools/assert.hpp>
0031
0032
0033 #ifndef BOOST_MATH_STANDALONE
0034
0035 #include <boost/predef/other/endian.h>
0036 #define BOOST_MATH_ENDIAN_BIG_BYTE BOOST_ENDIAN_BIG_BYTE
0037 #define BOOST_MATH_ENDIAN_LITTLE_BYTE BOOST_ENDIAN_LITTLE_BYTE
0038
0039 #elif defined(_WIN32)
0040
0041 #define BOOST_MATH_ENDIAN_BIG_BYTE 0
0042 #define BOOST_MATH_ENDIAN_LITTLE_BYTE 1
0043
0044 #elif defined(__BYTE_ORDER__)
0045
0046 #define BOOST_MATH_ENDIAN_BIG_BYTE (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
0047 #define BOOST_MATH_ENDIAN_LITTLE_BYTE (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
0048
0049 #else
0050 #error Could not determine endian type. Please disable standalone mode, and file an issue at https:
0051 #endif
0052
0053 static_assert((BOOST_MATH_ENDIAN_BIG_BYTE || BOOST_MATH_ENDIAN_LITTLE_BYTE)
0054 && !(BOOST_MATH_ENDIAN_BIG_BYTE && BOOST_MATH_ENDIAN_LITTLE_BYTE),
0055 "Inconsistent endianness detected. Please disable standalone mode, and file an issue at https://github.com/boostorg/math");
0056
0057 #ifdef BOOST_NO_STDC_NAMESPACE
0058 namespace std{ using ::memcpy; }
0059 #endif
0060
0061 #ifndef FP_NORMAL
0062
0063 #define FP_ZERO 0
0064 #define FP_NORMAL 1
0065 #define FP_INFINITE 2
0066 #define FP_NAN 3
0067 #define FP_SUBNORMAL 4
0068
0069 #else
0070
0071 #define BOOST_HAS_FPCLASSIFY
0072
0073 #ifndef fpclassify
0074 # if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) \
0075 && defined(_GLIBCXX_USE_C99_MATH) \
0076 && !(defined(_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC) \
0077 && (_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC != 0))
0078 # ifdef _STLP_VENDOR_CSTD
0079 # if _STLPORT_VERSION >= 0x520
0080 # define BOOST_FPCLASSIFY_PREFIX ::__std_alias::
0081 # else
0082 # define BOOST_FPCLASSIFY_PREFIX ::_STLP_VENDOR_CSTD::
0083 # endif
0084 # else
0085 # define BOOST_FPCLASSIFY_PREFIX ::std::
0086 # endif
0087 # else
0088 # undef BOOST_HAS_FPCLASSIFY
0089 # define BOOST_FPCLASSIFY_PREFIX
0090 # endif
0091 #elif (defined(__HP_aCC) && !defined(__hppa))
0092
0093 # define BOOST_FPCLASSIFY_PREFIX ::
0094 #else
0095 # define BOOST_FPCLASSIFY_PREFIX
0096 #endif
0097
0098 #ifdef __MINGW32__
0099 # undef BOOST_HAS_FPCLASSIFY
0100 #endif
0101
0102 #endif
0103
0104
0105
0106
0107 namespace boost {
0108 namespace math {
0109 namespace detail {
0110
0111
0112
0113
0114
0115
0116
0117
0118 struct native_tag {};
0119 template <bool has_limits>
0120 struct generic_tag {};
0121 struct ieee_tag {};
0122 struct ieee_copy_all_bits_tag : public ieee_tag {};
0123 struct ieee_copy_leading_bits_tag : public ieee_tag {};
0124
0125 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0126
0127
0128
0129
0130 inline bool is_generic_tag_false(const generic_tag<false>*)
0131 {
0132 return true;
0133 }
0134 inline bool is_generic_tag_false(const void*)
0135 {
0136 return false;
0137 }
0138 #endif
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 struct unknown_precision{};
0152 struct single_precision {};
0153 struct double_precision {};
0154 struct extended_double_precision {};
0155
0156
0157
0158 template<class T> struct fp_traits_native
0159 {
0160 typedef native_tag method;
0161 };
0162
0163
0164
0165 template<class T, class U> struct fp_traits_non_native
0166 {
0167 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0168 typedef generic_tag<std::numeric_limits<T>::is_specialized> method;
0169 #else
0170 typedef generic_tag<false> method;
0171 #endif
0172 };
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 #ifndef BOOST_FPCLASSIFY_VAX_FORMAT
0202
0203 template<> struct fp_traits_non_native<float, single_precision>
0204 {
0205 typedef ieee_copy_all_bits_tag method;
0206
0207 BOOST_MATH_STATIC constexpr uint32_t sign = 0x80000000u;
0208 BOOST_MATH_STATIC constexpr uint32_t exponent = 0x7f800000;
0209 BOOST_MATH_STATIC constexpr uint32_t flag = 0x00000000;
0210 BOOST_MATH_STATIC constexpr uint32_t significand = 0x007fffff;
0211
0212 typedef uint32_t bits;
0213 BOOST_MATH_GPU_ENABLED static void get_bits(float x, uint32_t& a) { std::memcpy(&a, &x, 4); }
0214 BOOST_MATH_GPU_ENABLED static void set_bits(float& x, uint32_t a) { std::memcpy(&x, &a, 4); }
0215 };
0216
0217
0218
0219 #if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) \
0220 || defined(BOOST_BORLANDC) || defined(__CODEGEAR__)
0221
0222 template<> struct fp_traits_non_native<double, double_precision>
0223 {
0224 typedef ieee_copy_leading_bits_tag method;
0225
0226 static constexpr uint32_t sign = 0x80000000u;
0227 static constexpr uint32_t exponent = 0x7ff00000;
0228 static constexpr uint32_t flag = 0;
0229 static constexpr uint32_t significand = 0x000fffff;
0230
0231 typedef uint32_t bits;
0232
0233 static void get_bits(double x, uint32_t& a)
0234 {
0235 std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
0236 }
0237
0238 static void set_bits(double& x, uint32_t a)
0239 {
0240 std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
0241 }
0242
0243 private:
0244 static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 4;
0245 };
0246
0247
0248
0249 #else
0250
0251 template<> struct fp_traits_non_native<double, double_precision>
0252 {
0253 typedef ieee_copy_all_bits_tag method;
0254
0255 BOOST_MATH_STATIC constexpr uint64_t sign = static_cast<uint64_t>(0x80000000u) << 32;
0256 BOOST_MATH_STATIC constexpr uint64_t exponent = static_cast<uint64_t>(0x7ff00000) << 32;
0257 BOOST_MATH_STATIC constexpr uint64_t flag = 0;
0258 BOOST_MATH_STATIC constexpr uint64_t significand
0259 = (static_cast<uint64_t>(0x000fffff) << 32) + static_cast<uint64_t>(0xffffffffu);
0260
0261 typedef uint64_t bits;
0262 BOOST_MATH_GPU_ENABLED static void get_bits(double x, uint64_t& a) { std::memcpy(&a, &x, 8); }
0263 BOOST_MATH_GPU_ENABLED static void set_bits(double& x, uint64_t a) { std::memcpy(&x, &a, 8); }
0264 };
0265
0266 #endif
0267
0268 #endif
0269
0270
0271
0272 #if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)\
0273 || defined(BOOST_BORLANDC) || defined(__CODEGEAR__) || (defined(__APPLE__) && defined(__aarch64__)) || defined(_MSC_VER)
0274
0275 template<> struct fp_traits_non_native<long double, double_precision>
0276 {
0277 typedef ieee_copy_leading_bits_tag method;
0278
0279 static constexpr uint32_t sign = 0x80000000u;
0280 static constexpr uint32_t exponent = 0x7ff00000;
0281 static constexpr uint32_t flag = 0;
0282 static constexpr uint32_t significand = 0x000fffff;
0283
0284 typedef uint32_t bits;
0285
0286 static void get_bits(long double x, uint32_t& a)
0287 {
0288 std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
0289 }
0290
0291 static void set_bits(long double& x, uint32_t a)
0292 {
0293 std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
0294 }
0295
0296 private:
0297 static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 4;
0298 };
0299
0300
0301
0302 #elif defined(__i386) || defined(__i386__) || defined(_M_IX86) \
0303 || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) \
0304 || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)
0305
0306
0307
0308 template<>
0309 struct fp_traits_non_native<long double, extended_double_precision>
0310 {
0311 typedef ieee_copy_leading_bits_tag method;
0312
0313 BOOST_MATH_STATIC constexpr uint32_t sign = 0x80000000u;
0314 BOOST_MATH_STATIC constexpr uint32_t exponent = 0x7fff0000;
0315 BOOST_MATH_STATIC constexpr uint32_t flag = 0x00008000;
0316 BOOST_MATH_STATIC constexpr uint32_t significand = 0x00007fff;
0317
0318 typedef uint32_t bits;
0319
0320 static void get_bits(long double x, uint32_t& a)
0321 {
0322 std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + 6, 4);
0323 }
0324
0325 static void set_bits(long double& x, uint32_t a)
0326 {
0327 std::memcpy(reinterpret_cast<unsigned char*>(&x) + 6, &a, 4);
0328 }
0329 };
0330
0331
0332
0333
0334 #elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344 #elif defined(__GNUC__) && (LDBL_MANT_DIG == 106)
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354 #elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) \
0355 || defined(__ppc) || defined(__ppc__) || defined(__PPC__)
0356
0357
0358
0359 template<>
0360 struct fp_traits_non_native<long double, extended_double_precision>
0361 {
0362 typedef ieee_copy_leading_bits_tag method;
0363
0364 BOOST_MATH_STATIC constexpr uint32_t sign = 0x80000000u;
0365 BOOST_MATH_STATIC constexpr uint32_t exponent = 0x7ff00000;
0366 BOOST_MATH_STATIC constexpr uint32_t flag = 0x00000000;
0367 BOOST_MATH_STATIC constexpr uint32_t significand = 0x000fffff;
0368
0369 typedef uint32_t bits;
0370
0371 static void get_bits(long double x, uint32_t& a)
0372 {
0373 std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
0374 }
0375
0376 static void set_bits(long double& x, uint32_t a)
0377 {
0378 std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
0379 }
0380
0381 private:
0382 BOOST_MATH_STATIC constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 12;
0383 };
0384
0385
0386
0387
0388 #elif defined(__m68k) || defined(__m68k__) \
0389 || defined(__mc68000) || defined(__mc68000__) \
0390
0391
0392
0393
0394
0395
0396
0397 template<>
0398 struct fp_traits_non_native<long double, extended_double_precision>
0399 {
0400 typedef ieee_copy_leading_bits_tag method;
0401
0402 BOOST_MATH_STATIC constexpr uint32_t sign = 0x80000000u;
0403 BOOST_MATH_STATIC constexpr uint32_t exponent = 0x7fff0000;
0404 BOOST_MATH_STATIC constexpr uint32_t flag = 0x00008000;
0405 BOOST_MATH_STATIC constexpr uint32_t significand = 0x00007fff;
0406
0407
0408
0409 typedef uint32_t bits;
0410
0411 static void get_bits(long double x, uint32_t& a)
0412 {
0413 std::memcpy(&a, &x, 2);
0414 std::memcpy(reinterpret_cast<unsigned char*>(&a) + 2,
0415 reinterpret_cast<const unsigned char*>(&x) + 4, 2);
0416 }
0417
0418 static void set_bits(long double& x, uint32_t a)
0419 {
0420 std::memcpy(&x, &a, 2);
0421 std::memcpy(reinterpret_cast<unsigned char*>(&x) + 4,
0422 reinterpret_cast<const unsigned char*>(&a) + 2, 2);
0423 }
0424 };
0425
0426
0427
0428
0429 #else
0430
0431
0432
0433 template<>
0434 struct fp_traits_non_native<long double, extended_double_precision>
0435 {
0436 typedef ieee_copy_leading_bits_tag method;
0437
0438 BOOST_MATH_STATIC constexpr uint32_t sign = 0x80000000u;
0439 BOOST_MATH_STATIC constexpr uint32_t exponent = 0x7fff0000;
0440 BOOST_MATH_STATIC constexpr uint32_t flag = 0x00000000;
0441 BOOST_MATH_STATIC constexpr uint32_t significand = 0x0000ffff;
0442
0443 typedef uint32_t bits;
0444
0445 static void get_bits(long double x, uint32_t& a)
0446 {
0447 std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
0448 }
0449
0450 static void set_bits(long double& x, uint32_t a)
0451 {
0452 std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
0453 }
0454
0455 private:
0456 BOOST_MATH_STATIC constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 12;
0457 };
0458
0459 #endif
0460
0461
0462
0463
0464
0465
0466 template<size_t n, bool fp> struct size_to_precision
0467 {
0468 typedef unknown_precision type;
0469 };
0470
0471 template<> struct size_to_precision<4, true>
0472 {
0473 typedef single_precision type;
0474 };
0475
0476 template<> struct size_to_precision<8, true>
0477 {
0478 typedef double_precision type;
0479 };
0480
0481 template<> struct size_to_precision<10, true>
0482 {
0483 typedef extended_double_precision type;
0484 };
0485
0486 template<> struct size_to_precision<12, true>
0487 {
0488 typedef extended_double_precision type;
0489 };
0490
0491 template<> struct size_to_precision<16, true>
0492 {
0493 typedef extended_double_precision type;
0494 };
0495
0496
0497
0498
0499
0500
0501 template <class T>
0502 struct select_native
0503 {
0504 typedef typename size_to_precision<sizeof(T), ::std::is_floating_point<T>::value>::type precision;
0505 typedef fp_traits_non_native<T, precision> type;
0506 };
0507 template<>
0508 struct select_native<float>
0509 {
0510 typedef fp_traits_native<float> type;
0511 };
0512 template<>
0513 struct select_native<double>
0514 {
0515 typedef fp_traits_native<double> type;
0516 };
0517 template<>
0518 struct select_native<long double>
0519 {
0520 typedef fp_traits_native<long double> type;
0521 };
0522
0523
0524
0525
0526
0527 #if (defined(BOOST_MATH_USE_C99) && !(defined(__GNUC__) && (__GNUC__ < 4))) \
0528 && !defined(__hpux) \
0529 && !defined(__DECCXX)\
0530 && !defined(__osf__) \
0531 && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)\
0532 && !defined(__FAST_MATH__)\
0533 && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)\
0534 && !defined(__INTEL_COMPILER)\
0535 && !defined(sun)\
0536 && !defined(__VXWORKS__)\
0537 && !defined(BOOST_MATH_HAS_GPU_SUPPORT)
0538 # define BOOST_MATH_USE_STD_FPCLASSIFY
0539 #endif
0540
0541 template<class T> struct fp_traits
0542 {
0543 typedef typename size_to_precision<sizeof(T), ::std::is_floating_point<T>::value>::type precision;
0544 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
0545 typedef typename select_native<T>::type type;
0546 #else
0547 typedef fp_traits_non_native<T, precision> type;
0548 #endif
0549 typedef fp_traits_non_native<T, precision> sign_change_type;
0550 };
0551
0552
0553
0554 }
0555 }
0556 }
0557
0558 #endif