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