123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920 |
- ///////////////////////////////////////////////////////////////
- // Copyright 2013 John Maddock. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
- #ifndef BOOST_MP_FLOAT128_HPP
- #define BOOST_MP_FLOAT128_HPP
- // https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
- #if !defined(__amd64__) && !defined(__amd64) && !defined(__x86_64__) && !defined(__x86_64) && !defined(_M_X64) && !defined(_M_AMD64) && \
- !defined(i386) && !defined(__i386) && !defined(__i386__) && !defined(_M_IX86) && !defined(__X86__) && !defined(_X86_) && !defined(__I86__) && \
- !defined(__ia64__) && !defined(_IA64) && !defined(__IA64__) && !defined(__ia64) && !defined(_M_IA64) && !defined(__itanium__) && \
- !defined(__hppa__) && !defined(__HPPA__) && !defined(__hppa) && \
- !defined(__powerpc) && !defined(_M_PPC) && !defined(_ARCH_PPC) && !defined(_ARCH_PPC64) && !defined(__PPCBROADWAY__)
- #error libquadmath only works on on i386, x86_64, IA-64, and hppa HP-UX, as well as on PowerPC GNU/Linux targets that enable the vector scalar (VSX) instruction set.
- #endif
- #include <memory>
- #include <climits>
- #include <cfloat>
- #include <tuple>
- #include <cstring>
- #include <boost/multiprecision/detail/standalone_config.hpp>
- #include <boost/multiprecision/number.hpp>
- #include <boost/multiprecision/detail/hash.hpp>
- #include <boost/multiprecision/detail/no_exceptions_support.hpp>
- #if defined(BOOST_INTEL) && !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
- #if defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION >= 1310) && defined(__GNUC__)
- #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
- #define BOOST_MP_USE_FLOAT128
- #endif
- #endif
- #ifndef BOOST_MP_USE_FLOAT128
- #define BOOST_MP_USE_QUAD
- #endif
- #endif
- #if defined(__GNUC__) && !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
- #define BOOST_MP_USE_FLOAT128
- #endif
- #if !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
- #error "Sorry compiler is neither GCC, not Intel, don't know how to configure this header."
- #endif
- #if defined(BOOST_MP_USE_FLOAT128) && defined(BOOST_MP_USE_QUAD)
- #error "Oh dear, both BOOST_MP_USE_FLOAT128 and BOOST_MP_USE_QUAD are defined, which one should I be using?"
- #endif
- #if defined(BOOST_MP_USE_FLOAT128)
- extern "C" {
- #include <quadmath.h>
- }
- using float128_type = __float128;
- #elif defined(BOOST_MP_USE_QUAD)
- #include <boost/multiprecision/detail/float_string_cvt.hpp>
- using float128_type = _Quad;
- extern "C" {
- _Quad __ldexpq(_Quad, int);
- _Quad __frexpq(_Quad, int*);
- _Quad __fabsq(_Quad);
- _Quad __floorq(_Quad);
- _Quad __ceilq(_Quad);
- _Quad __sqrtq(_Quad);
- _Quad __truncq(_Quad);
- _Quad __expq(_Quad);
- _Quad __powq(_Quad, _Quad);
- _Quad __logq(_Quad);
- _Quad __log10q(_Quad);
- _Quad __sinq(_Quad);
- _Quad __cosq(_Quad);
- _Quad __tanq(_Quad);
- _Quad __asinq(_Quad);
- _Quad __acosq(_Quad);
- _Quad __atanq(_Quad);
- _Quad __sinhq(_Quad);
- _Quad __coshq(_Quad);
- _Quad __tanhq(_Quad);
- _Quad __fmodq(_Quad, _Quad);
- _Quad __atan2q(_Quad, _Quad);
- #define ldexpq __ldexpq
- #define frexpq __frexpq
- #define fabsq __fabsq
- #define floorq __floorq
- #define ceilq __ceilq
- #define sqrtq __sqrtq
- #define truncq __truncq
- #define expq __expq
- #define powq __powq
- #define logq __logq
- #define log10q __log10q
- #define sinq __sinq
- #define cosq __cosq
- #define tanq __tanq
- #define asinq __asinq
- #define acosq __acosq
- #define atanq __atanq
- #define sinhq __sinhq
- #define coshq __coshq
- #define tanhq __tanhq
- #define fmodq __fmodq
- #define atan2q __atan2q
- }
- inline _Quad isnanq(_Quad v)
- {
- return v != v;
- }
- inline _Quad isinfq(_Quad v)
- {
- return __fabsq(v) > 1.18973149535723176508575932662800702e4932Q;
- }
- #endif
- namespace boost {
- namespace multiprecision {
- #ifndef BOOST_MP_BITS_OF_FLOAT128_DEFINED
- namespace detail {
- template <>
- struct bits_of<float128_type>
- {
- static constexpr const unsigned value = 113;
- };
- }
- #endif
- template <>
- struct number_category<backends::float128_backend> : public std::integral_constant<int, number_kind_floating_point>
- {};
- #if defined(BOOST_MP_USE_QUAD)
- template <>
- struct number_category<float128_type> : public std::integral_constant<int, number_kind_floating_point>
- {};
- #endif
- namespace quad_constants {
- constexpr float128_type quad_min = static_cast<float128_type>(1) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) / 1073741824;
- constexpr float128_type quad_denorm_min = static_cast<float128_type>(1) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) / 5.5751862996326557854e+42;
- constexpr double dbl_mult = 8.9884656743115795386e+307; // This has one bit set only.
- constexpr float128_type quad_max = (static_cast<float128_type>(1) - 9.62964972193617926527988971292463659e-35) // This now has all bits sets to 1
- * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * 65536;
- } // namespace quad_constants
- #define BOOST_MP_QUAD_MIN boost::multiprecision::quad_constants::quad_min
- #define BOOST_MP_QUAD_DENORM_MIN boost::multiprecision::quad_constants::quad_denorm_min
- #define BOOST_MP_QUAD_MAX boost::multiprecision::quad_constants::quad_max
- namespace backends {
- struct float128_backend
- {
- using signed_types = std::tuple<signed char, short, int, long, long long>;
- using unsigned_types = std::tuple<unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>;
- using float_types = std::tuple<float, double, long double>;
- using exponent_type = int ;
- private:
- float128_type m_value;
- public:
- constexpr float128_backend() noexcept : m_value(0) {}
- constexpr float128_backend(const float128_backend& o) noexcept : m_value(o.m_value) {}
- BOOST_MP_CXX14_CONSTEXPR float128_backend& operator=(const float128_backend& o) noexcept
- {
- m_value = o.m_value;
- return *this;
- }
- template <class T>
- constexpr float128_backend(const T& i, const typename std::enable_if<std::is_convertible<T, float128_type>::value>::type* = nullptr) noexcept(noexcept(std::declval<float128_type&>() = std::declval<const T&>()))
- : m_value(i) {}
- template <class T>
- BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value || std::is_convertible<T, float128_type>::value, float128_backend&>::type operator=(const T& i) noexcept(noexcept(std::declval<float128_type&>() = std::declval<const T&>()))
- {
- m_value = i;
- return *this;
- }
- BOOST_MP_CXX14_CONSTEXPR float128_backend(long double const& f) : m_value(f)
- {
- if (f > LDBL_MAX)
- m_value = static_cast<float128_type>(HUGE_VAL);
- else if (-f > LDBL_MAX)
- m_value = -static_cast<float128_type>(HUGE_VAL);
- }
- BOOST_MP_CXX14_CONSTEXPR float128_backend& operator=(long double const& f)
- {
- if (f > LDBL_MAX)
- m_value = static_cast<float128_type>(HUGE_VAL);
- else if (-f > LDBL_MAX)
- m_value = -static_cast<float128_type>(HUGE_VAL);
- else
- m_value = f;
- return *this;
- }
- float128_backend& operator=(const char* s)
- {
- #ifndef BOOST_MP_USE_QUAD
- char* p_end;
- m_value = strtoflt128(s, &p_end);
- if (p_end - s != (std::ptrdiff_t)std::strlen(s))
- {
- BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a floating point value"));
- }
- #else
- boost::multiprecision::detail::convert_from_string(*this, s);
- #endif
- return *this;
- }
- BOOST_MP_CXX14_CONSTEXPR void swap(float128_backend& o) noexcept
- {
- // We don't call std::swap here because it's no constexpr (yet):
- float128_type t(o.value());
- o.value() = m_value;
- m_value = t;
- }
- std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
- {
- #ifndef BOOST_MP_USE_QUAD
- char buf[128];
- std::string format = "%";
- if (f & std::ios_base::showpos)
- format += "+";
- if (f & std::ios_base::showpoint)
- format += "#";
- format += ".*";
- if ((digits == 0) && !(f & std::ios_base::fixed))
- digits = 36;
- format += "Q";
- if (f & std::ios_base::scientific)
- format += "e";
- else if (f & std::ios_base::fixed)
- format += "f";
- else
- format += "g";
- int v;
- if ((f & std::ios_base::scientific) && (f & std::ios_base::fixed))
- {
- v = quadmath_snprintf(buf, sizeof buf, "%Qa", m_value);
- }
- else
- {
- v = quadmath_snprintf(buf, sizeof buf, format.c_str(), digits, m_value);
- }
- if ((v < 0) || (v >= 127))
- {
- int v_max = v;
- std::unique_ptr<char[]> buf2;
- buf2.reset(new char[v + 3]);
- v = quadmath_snprintf(&buf2[0], v_max + 3, format.c_str(), digits, m_value);
- if (v >= v_max + 3)
- {
- BOOST_MP_THROW_EXCEPTION(std::runtime_error("Formatting of float128_type failed."));
- }
- return &buf2[0];
- }
- return buf;
- #else
- return boost::multiprecision::detail::convert_to_string(*this, digits ? digits : 36, f);
- #endif
- }
- BOOST_MP_CXX14_CONSTEXPR void negate() noexcept
- {
- m_value = -m_value;
- }
- BOOST_MP_CXX14_CONSTEXPR int compare(const float128_backend& o) const
- {
- return m_value == o.m_value ? 0 : m_value < o.m_value ? -1 : 1;
- }
- template <class T>
- BOOST_MP_CXX14_CONSTEXPR int compare(const T& i) const
- {
- return m_value == i ? 0 : m_value < i ? -1 : 1;
- }
- BOOST_MP_CXX14_CONSTEXPR float128_type& value()
- {
- return m_value;
- }
- BOOST_MP_CXX14_CONSTEXPR const float128_type& value() const
- {
- return m_value;
- }
- };
- inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a)
- {
- result.value() += a.value();
- }
- template <class A>
- inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const A& a)
- {
- result.value() += a;
- }
- inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a)
- {
- result.value() -= a.value();
- }
- template <class A>
- inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const A& a)
- {
- result.value() -= a;
- }
- inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a)
- {
- result.value() *= a.value();
- }
- template <class A>
- inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const A& a)
- {
- result.value() *= a;
- }
- inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const float128_backend& a)
- {
- result.value() /= a.value();
- }
- template <class A>
- inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const A& a)
- {
- result.value() /= a;
- }
- inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a, const float128_backend& b)
- {
- result.value() = a.value() + b.value();
- }
- template <class A>
- inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a, const A& b)
- {
- result.value() = a.value() + b;
- }
- inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a, const float128_backend& b)
- {
- result.value() = a.value() - b.value();
- }
- template <class A>
- inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a, const A& b)
- {
- result.value() = a.value() - b;
- }
- template <class A>
- inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const A& a, const float128_backend& b)
- {
- result.value() = a - b.value();
- }
- inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a, const float128_backend& b)
- {
- result.value() = a.value() * b.value();
- }
- template <class A>
- inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a, const A& b)
- {
- result.value() = a.value() * b;
- }
- inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const float128_backend& a, const float128_backend& b)
- {
- result.value() = a.value() / b.value();
- }
- template <class R>
- inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(R* result, const float128_backend& val)
- {
- *result = static_cast<R>(val.value());
- }
- inline void eval_frexp(float128_backend& result, const float128_backend& arg, int* exp)
- {
- result.value() = frexpq(arg.value(), exp);
- }
- inline void eval_ldexp(float128_backend& result, const float128_backend& arg, int exp)
- {
- result.value() = ldexpq(arg.value(), exp);
- }
- inline void eval_floor(float128_backend& result, const float128_backend& arg)
- {
- result.value() = floorq(arg.value());
- }
- inline void eval_ceil(float128_backend& result, const float128_backend& arg)
- {
- result.value() = ceilq(arg.value());
- }
- inline void eval_sqrt(float128_backend& result, const float128_backend& arg)
- {
- result.value() = sqrtq(arg.value());
- }
- inline void eval_rsqrt(float128_backend& result, const float128_backend& arg)
- {
- #if (LDBL_MANT_DIG > 100)
- // GCC can't mix and match __float128 and quad precision long double
- // error: __float128 and long double cannot be used in the same expression
- result.value() = 1 / sqrtq(arg.value());
- #else
- if (arg.value() < std::numeric_limits<long double>::denorm_min() || arg.value() > (std::numeric_limits<long double>::max)()) {
- result.value() = 1/sqrtq(arg.value());
- return;
- }
- using std::sqrt;
- float128_backend xk = 1/sqrt(static_cast<long double>(arg.value()));
- // Newton iteration for f(x) = arg.value() - 1/x^2.
- BOOST_IF_CONSTEXPR (sizeof(long double) == sizeof(double)) {
- // If the long double is the same as a double, then we need two Newton iterations:
- xk.value() = xk.value() + xk.value()*(1-arg.value()*xk.value()*xk.value())/2;
- result.value() = xk.value() + xk.value()*(1-arg.value()*xk.value()*xk.value())/2;
- }
- else
- {
- // 80 bit long double only needs a single iteration to produce ~2ULPs.
- result.value() = xk.value() + xk.value() * (1 - arg.value() * xk.value() * xk.value()) / 2;
- }
- #endif
- }
- #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
- inline BOOST_MP_CXX14_CONSTEXPR
- #else
- inline
- #endif
- int eval_fpclassify(const float128_backend& arg)
- {
- float128_type v = arg.value();
- #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
- if (BOOST_MP_IS_CONST_EVALUATED(v))
- {
- if (v != v)
- return FP_NAN;
- if (v == 0)
- return FP_ZERO;
- float128_type t(v);
- if (t < 0)
- t = -t;
- if (t > BOOST_MP_QUAD_MAX)
- return FP_INFINITE;
- if (t < BOOST_MP_QUAD_MIN)
- return FP_SUBNORMAL;
- return FP_NORMAL;
- }
- else
- #endif
- {
- if (isnanq(v))
- return FP_NAN;
- else if (isinfq(v))
- return FP_INFINITE;
- else if (v == 0)
- return FP_ZERO;
- float128_backend t(arg);
- if (t.value() < 0)
- t.negate();
- if (t.value() < BOOST_MP_QUAD_MIN)
- return FP_SUBNORMAL;
- return FP_NORMAL;
- }
- }
- #if defined(BOOST_GCC) && (__GNUC__ == 9)
- // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91705
- inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(float128_backend& arg)
- {
- arg.value() = 1 + arg.value();
- }
- inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(float128_backend& arg)
- {
- arg.value() = arg.value() - 1;
- }
- #else
- inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(float128_backend& arg)
- {
- ++arg.value();
- }
- inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(float128_backend& arg)
- {
- --arg.value();
- }
- #endif
- /*********************************************************************
- *
- * abs/fabs:
- *
- *********************************************************************/
- #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
- inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(float128_backend& result, const float128_backend& arg)
- #else
- inline void eval_abs(float128_backend& result, const float128_backend& arg)
- #endif
- {
- #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
- float128_type v(arg.value());
- if (BOOST_MP_IS_CONST_EVALUATED(v))
- {
- result.value() = v < 0 ? -v : v;
- }
- else
- #endif
- {
- result.value() = fabsq(arg.value());
- }
- }
- #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
- inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(float128_backend& result, const float128_backend& arg)
- #else
- inline void eval_fabs(float128_backend& result, const float128_backend& arg)
- #endif
- {
- #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
- float128_type v(arg.value());
- if (BOOST_MP_IS_CONST_EVALUATED(v))
- {
- result.value() = v < 0 ? -v : v;
- }
- else
- #endif
- {
- result.value() = fabsq(arg.value());
- }
- }
- /*********************************************************************
- *
- * Floating point functions:
- *
- *********************************************************************/
- inline void eval_trunc(float128_backend& result, const float128_backend& arg)
- {
- result.value() = truncq(arg.value());
- }
- /*
- //
- // This doesn't actually work... rely on our own default version instead.
- //
- inline void eval_round(float128_backend& result, const float128_backend& arg)
- {
- if(isnanq(arg.value()) || isinf(arg.value()))
- {
- result = boost::math::policies::raise_rounding_error(
- "boost::multiprecision::trunc<%1%>(%1%)", nullptr,
- number<float128_backend, et_off>(arg),
- number<float128_backend, et_off>(arg),
- boost::math::policies::policy<>()).backend();
- return;
- }
- result.value() = roundq(arg.value());
- }
- */
- inline void eval_exp(float128_backend& result, const float128_backend& arg)
- {
- result.value() = expq(arg.value());
- }
- inline void eval_log(float128_backend& result, const float128_backend& arg)
- {
- result.value() = logq(arg.value());
- }
- inline void eval_log10(float128_backend& result, const float128_backend& arg)
- {
- result.value() = log10q(arg.value());
- }
- inline void eval_sin(float128_backend& result, const float128_backend& arg)
- {
- result.value() = sinq(arg.value());
- }
- inline void eval_cos(float128_backend& result, const float128_backend& arg)
- {
- result.value() = cosq(arg.value());
- }
- inline void eval_tan(float128_backend& result, const float128_backend& arg)
- {
- result.value() = tanq(arg.value());
- }
- inline void eval_asin(float128_backend& result, const float128_backend& arg)
- {
- result.value() = asinq(arg.value());
- }
- inline void eval_acos(float128_backend& result, const float128_backend& arg)
- {
- result.value() = acosq(arg.value());
- }
- inline void eval_atan(float128_backend& result, const float128_backend& arg)
- {
- result.value() = atanq(arg.value());
- }
- inline void eval_sinh(float128_backend& result, const float128_backend& arg)
- {
- result.value() = sinhq(arg.value());
- }
- inline void eval_cosh(float128_backend& result, const float128_backend& arg)
- {
- result.value() = coshq(arg.value());
- }
- inline void eval_tanh(float128_backend& result, const float128_backend& arg)
- {
- result.value() = tanhq(arg.value());
- }
- inline void eval_fmod(float128_backend& result, const float128_backend& a, const float128_backend& b)
- {
- result.value() = fmodq(a.value(), b.value());
- }
- inline void eval_pow(float128_backend& result, const float128_backend& a, const float128_backend& b)
- {
- result.value() = powq(a.value(), b.value());
- }
- inline void eval_atan2(float128_backend& result, const float128_backend& a, const float128_backend& b)
- {
- result.value() = atan2q(a.value(), b.value());
- }
- #ifndef BOOST_MP_USE_QUAD
- inline void eval_multiply_add(float128_backend& result, const float128_backend& a, const float128_backend& b, const float128_backend& c)
- {
- result.value() = fmaq(a.value(), b.value(), c.value());
- }
- inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend& arg)
- {
- return ::signbitq(arg.value());
- }
- #endif
- inline std::size_t hash_value(const float128_backend& val)
- {
- return boost::multiprecision::detail::hash_value(static_cast<double>(val.value()));
- }
- } // namespace backends
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- return asinhq(arg.backend().value());
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- return acoshq(arg.backend().value());
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- return atanhq(arg.backend().value());
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- return cbrtq(arg.backend().value());
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- return erfq(arg.backend().value());
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- return erfcq(arg.backend().value());
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- return expm1q(arg.backend().value());
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- return lgammaq(arg.backend().value());
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- if(eval_signbit(arg.backend()) != 0)
- {
- const bool result_is_neg = ((static_cast<unsigned long long>(floorq(-arg.backend().value())) % 2U) == 0U);
- const boost::multiprecision::number<float128_backend, ExpressionTemplates> result_of_tgammaq = fabsq(tgammaq(arg.backend().value()));
- return ((result_is_neg == false) ? result_of_tgammaq : -result_of_tgammaq);
- }
- else
- {
- return tgammaq(arg.backend().value());
- }
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- return log1pq(arg.backend().value());
- }
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<float128_backend, ExpressionTemplates> rsqrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
- {
- boost::multiprecision::number<float128_backend, ExpressionTemplates> res;
- eval_rsqrt(res.backend(), arg.backend());
- return res;
- }
- #ifndef BOOST_MP_USE_QUAD
- template <multiprecision::expression_template_option ExpressionTemplates>
- inline boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& b)
- {
- return ::copysignq(a.backend().value(), b.backend().value());
- }
- namespace backends {
- inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b)
- {
- result.value() = remainderq(a.value(), b.value());
- }
- inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b, int* pi)
- {
- result.value() = remquoq(a.value(), b.value(), pi);
- }
- } // namespace backends
- #endif
- } // namespace multiprecision
- namespace math {
- using boost::multiprecision::copysign;
- using boost::multiprecision::signbit;
- } // namespace math
- } // namespace boost
- #ifndef BOOST_MP_STANDALONE
- namespace boost {
- namespace archive {
- class binary_oarchive;
- class binary_iarchive;
- } // namespace archive
- namespace serialization {
- namespace float128_detail {
- template <class Archive>
- void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&)
- {
- // saving
- // non-binary
- std::string s(val.str(0, std::ios_base::scientific));
- ar& boost::make_nvp("value", s);
- }
- template <class Archive>
- void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&)
- {
- // loading
- // non-binary
- std::string s;
- ar& boost::make_nvp("value", s);
- val = s.c_str();
- }
- template <class Archive>
- void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
- {
- // saving
- // binary
- ar.save_binary(&val, sizeof(val));
- }
- template <class Archive>
- void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&)
- {
- // loading
- // binary
- ar.load_binary(&val, sizeof(val));
- }
- } // namespace float128_detail
- template <class Archive>
- void serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, unsigned int /*version*/)
- {
- using load_tag = typename Archive::is_loading ;
- using loading = std::integral_constant<bool, load_tag::value> ;
- using binary_tag = typename std::integral_constant<bool, std::is_same<Archive, boost::archive::binary_oarchive>::value || std::is_same<Archive, boost::archive::binary_iarchive>::value>;
- float128_detail::do_serialize(ar, val, loading(), binary_tag());
- }
- } // namespace serialization
- } // namespace boost
- #endif // BOOST_MP_STANDALONE
- namespace std {
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >
- {
- using number_type = boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>;
- public:
- static constexpr bool is_specialized = true;
- static BOOST_MP_CXX14_CONSTEXPR number_type(min)() noexcept { return BOOST_MP_QUAD_MIN; }
- static BOOST_MP_CXX14_CONSTEXPR number_type(max)() noexcept { return BOOST_MP_QUAD_MAX; }
- static BOOST_MP_CXX14_CONSTEXPR number_type lowest() noexcept { return -(max)(); }
- static constexpr int digits = 113;
- static constexpr int digits10 = 33;
- static constexpr int max_digits10 = 36;
- static constexpr bool is_signed = true;
- static constexpr bool is_integer = false;
- static constexpr bool is_exact = false;
- static constexpr int radix = 2;
- static BOOST_MP_CXX14_CONSTEXPR number_type epsilon() { return 1.92592994438723585305597794258492732e-34; /* this double value has only one bit set and so is exact */ }
- static BOOST_MP_CXX14_CONSTEXPR number_type round_error() { return 0.5; }
- static constexpr int min_exponent = -16381;
- static constexpr int min_exponent10 = min_exponent * 301L / 1000L;
- static constexpr int max_exponent = 16384;
- static constexpr int max_exponent10 = max_exponent * 301L / 1000L;
- static constexpr bool has_infinity = true;
- static constexpr bool has_quiet_NaN = true;
- static constexpr bool has_signaling_NaN = false;
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable : 4996)
- #endif
- static constexpr float_denorm_style has_denorm = denorm_present;
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- static constexpr bool has_denorm_loss = true;
- static BOOST_MP_CXX14_CONSTEXPR number_type infinity() { return HUGE_VAL; /* conversion from double infinity OK */ }
- static BOOST_MP_CXX14_CONSTEXPR number_type quiet_NaN() { return number_type(NAN); }
- static BOOST_MP_CXX14_CONSTEXPR number_type signaling_NaN() { return 0; }
- static BOOST_MP_CXX14_CONSTEXPR number_type denorm_min() { return BOOST_MP_QUAD_DENORM_MIN; }
- static constexpr bool is_iec559 = true;
- static constexpr bool is_bounded = true;
- static constexpr bool is_modulo = false;
- static constexpr bool traps = false;
- static constexpr bool tinyness_before = false;
- static constexpr float_round_style round_style = round_to_nearest;
- };
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_specialized;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_digits10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_signed;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_integer;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_exact;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::radix;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_infinity;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_quiet_NaN;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_signaling_NaN;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm_loss;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_iec559;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_bounded;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_modulo;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::traps;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::tinyness_before;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::round_style;
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable : 4996)
- #endif
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm;
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- } // namespace std
- #endif
|