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