File indexing completed on 2025-09-16 08:38:32
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__)
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 #else
0303
0304 template<> struct fp_traits_non_native<long double, double_precision>
0305 {
0306 typedef ieee_copy_all_bits_tag method;
0307
0308 static const uint64_t sign = static_cast<uint64_t>(0x80000000u) << 32;
0309 static const uint64_t exponent = static_cast<uint64_t>(0x7ff00000) << 32;
0310 static const uint64_t flag = 0;
0311 static const uint64_t significand
0312 = (static_cast<uint64_t>(0x000fffff) << 32) + static_cast<uint64_t>(0xffffffffu);
0313
0314 typedef uint64_t bits;
0315 static void get_bits(long double x, uint64_t& a) { std::memcpy(&a, &x, 8); }
0316 static void set_bits(long double& x, uint64_t a) { std::memcpy(&x, &a, 8); }
0317 };
0318
0319 #endif
0320
0321
0322
0323
0324 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) \
0325 || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) \
0326 || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)
0327
0328
0329
0330 template<>
0331 struct fp_traits_non_native<long double, extended_double_precision>
0332 {
0333 typedef ieee_copy_leading_bits_tag method;
0334
0335 BOOST_MATH_STATIC constexpr uint32_t sign = 0x80000000u;
0336 BOOST_MATH_STATIC constexpr uint32_t exponent = 0x7fff0000;
0337 BOOST_MATH_STATIC constexpr uint32_t flag = 0x00008000;
0338 BOOST_MATH_STATIC constexpr uint32_t significand = 0x00007fff;
0339
0340 typedef uint32_t bits;
0341
0342 static void get_bits(long double x, uint32_t& a)
0343 {
0344 std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + 6, 4);
0345 }
0346
0347 static void set_bits(long double& x, uint32_t a)
0348 {
0349 std::memcpy(reinterpret_cast<unsigned char*>(&x) + 6, &a, 4);
0350 }
0351 };
0352
0353
0354
0355
0356 #elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 #elif defined(__GNUC__) && (LDBL_MANT_DIG == 106)
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376 #elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) \
0377 || defined(__ppc) || defined(__ppc__) || defined(__PPC__)
0378
0379
0380
0381 template<>
0382 struct fp_traits_non_native<long double, extended_double_precision>
0383 {
0384 typedef ieee_copy_leading_bits_tag method;
0385
0386 BOOST_MATH_STATIC constexpr uint32_t sign = 0x80000000u;
0387 BOOST_MATH_STATIC constexpr uint32_t exponent = 0x7ff00000;
0388 BOOST_MATH_STATIC constexpr uint32_t flag = 0x00000000;
0389 BOOST_MATH_STATIC constexpr uint32_t significand = 0x000fffff;
0390
0391 typedef uint32_t bits;
0392
0393 static void get_bits(long double x, uint32_t& a)
0394 {
0395 std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
0396 }
0397
0398 static void set_bits(long double& x, uint32_t a)
0399 {
0400 std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
0401 }
0402
0403 private:
0404 BOOST_MATH_STATIC constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 12;
0405 };
0406
0407
0408
0409
0410 #elif defined(__m68k) || defined(__m68k__) \
0411 || defined(__mc68000) || defined(__mc68000__) \
0412
0413
0414
0415
0416
0417
0418
0419 template<>
0420 struct fp_traits_non_native<long double, extended_double_precision>
0421 {
0422 typedef ieee_copy_leading_bits_tag method;
0423
0424 BOOST_MATH_STATIC constexpr uint32_t sign = 0x80000000u;
0425 BOOST_MATH_STATIC constexpr uint32_t exponent = 0x7fff0000;
0426 BOOST_MATH_STATIC constexpr uint32_t flag = 0x00008000;
0427 BOOST_MATH_STATIC constexpr uint32_t significand = 0x00007fff;
0428
0429
0430
0431 typedef uint32_t bits;
0432
0433 static void get_bits(long double x, uint32_t& a)
0434 {
0435 std::memcpy(&a, &x, 2);
0436 std::memcpy(reinterpret_cast<unsigned char*>(&a) + 2,
0437 reinterpret_cast<const unsigned char*>(&x) + 4, 2);
0438 }
0439
0440 static void set_bits(long double& x, uint32_t a)
0441 {
0442 std::memcpy(&x, &a, 2);
0443 std::memcpy(reinterpret_cast<unsigned char*>(&x) + 4,
0444 reinterpret_cast<const unsigned char*>(&a) + 2, 2);
0445 }
0446 };
0447
0448
0449
0450
0451 #else
0452
0453
0454
0455 template<>
0456 struct fp_traits_non_native<long double, extended_double_precision>
0457 {
0458 typedef ieee_copy_leading_bits_tag method;
0459
0460 BOOST_MATH_STATIC constexpr uint32_t sign = 0x80000000u;
0461 BOOST_MATH_STATIC constexpr uint32_t exponent = 0x7fff0000;
0462 BOOST_MATH_STATIC constexpr uint32_t flag = 0x00000000;
0463 BOOST_MATH_STATIC constexpr uint32_t significand = 0x0000ffff;
0464
0465 typedef uint32_t bits;
0466
0467 static void get_bits(long double x, uint32_t& a)
0468 {
0469 std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
0470 }
0471
0472 static void set_bits(long double& x, uint32_t a)
0473 {
0474 std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
0475 }
0476
0477 private:
0478 BOOST_MATH_STATIC constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 12;
0479 };
0480
0481 #endif
0482
0483
0484
0485
0486
0487
0488 template<size_t n, bool fp> struct size_to_precision
0489 {
0490 typedef unknown_precision type;
0491 };
0492
0493 template<> struct size_to_precision<4, true>
0494 {
0495 typedef single_precision type;
0496 };
0497
0498 template<> struct size_to_precision<8, true>
0499 {
0500 typedef double_precision type;
0501 };
0502
0503 template<> struct size_to_precision<10, true>
0504 {
0505 typedef extended_double_precision type;
0506 };
0507
0508 template<> struct size_to_precision<12, true>
0509 {
0510 typedef extended_double_precision type;
0511 };
0512
0513 template<> struct size_to_precision<16, true>
0514 {
0515 typedef extended_double_precision type;
0516 };
0517
0518
0519
0520
0521
0522
0523 template <class T>
0524 struct select_native
0525 {
0526 typedef typename size_to_precision<sizeof(T), ::std::is_floating_point<T>::value>::type precision;
0527 typedef fp_traits_non_native<T, precision> type;
0528 };
0529 template<>
0530 struct select_native<float>
0531 {
0532 typedef fp_traits_native<float> type;
0533 };
0534 template<>
0535 struct select_native<double>
0536 {
0537 typedef fp_traits_native<double> type;
0538 };
0539 template<>
0540 struct select_native<long double>
0541 {
0542 typedef fp_traits_native<long double> type;
0543 };
0544
0545
0546
0547
0548
0549 #if (defined(BOOST_MATH_USE_C99) && !(defined(__GNUC__) && (__GNUC__ < 4))) \
0550 && !defined(__hpux) \
0551 && !defined(__DECCXX)\
0552 && !defined(__osf__) \
0553 && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)\
0554 && !defined(__FAST_MATH__)\
0555 && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)\
0556 && !defined(__INTEL_COMPILER)\
0557 && !defined(sun)\
0558 && !defined(__VXWORKS__)\
0559 && !defined(BOOST_MATH_HAS_GPU_SUPPORT)
0560 # define BOOST_MATH_USE_STD_FPCLASSIFY
0561 #endif
0562
0563 template<class T> struct fp_traits
0564 {
0565 typedef typename size_to_precision<sizeof(T), ::std::is_floating_point<T>::value>::type precision;
0566 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
0567 typedef typename select_native<T>::type type;
0568 #else
0569 typedef fp_traits_non_native<T, precision> type;
0570 #endif
0571 typedef fp_traits_non_native<T, precision> sign_change_type;
0572 };
0573
0574
0575
0576 }
0577 }
0578 }
0579
0580 #endif