From cd0b414cd39cf8db7a03257295f90ae5a696db63 Mon Sep 17 00:00:00 2001 From: Zerg1996 Date: Fri, 7 Jun 2019 15:16:29 +0300 Subject: [PATCH 001/294] Multiply example #2 --- .../multiprecision/detail/default_ops.hpp | 10 +- .../multiprecision/detail/number_base.hpp | 3 +- .../boost/multiprecision/inverse_euclid.hpp | 103 + include/boost/multiprecision/jacobi.hpp | 82 + include/boost/multiprecision/mask_bits.hpp | 37 + .../boost/multiprecision/modular_inverse.hpp | 179 ++ .../multiprecision/montgomery_int/add.hpp | 573 ++++ .../multiprecision/montgomery_int/bitwise.hpp | 605 ++++ .../montgomery_int/comparison.hpp | 479 ++++ .../multiprecision/montgomery_int/divide.hpp | 477 ++++ .../montgomery_int/import_export.hpp | 298 ++ .../multiprecision/montgomery_int/inverse.hpp | 42 + .../multiprecision/montgomery_int/limits.hpp | 375 +++ .../montgomery_int/literals.hpp | 102 + .../multiprecision/montgomery_int/misc.hpp | 683 +++++ .../montgomery_int/modular_reduce.hpp | 94 + .../montgomery_int/montgomery_int.hpp | 2473 +++++++++++++++++ .../montgomery_int/montgomery_params.hpp | 159 ++ .../montgomery_int/multiply.hpp | 999 +++++++ .../multiprecision/montgomery_int/reduce.hpp | 113 + .../montgomery_int/serialize.hpp | 201 ++ .../multiprecision/montgomery_inverse.hpp | 114 + include/boost/multiprecision/pow_mod.hpp | 188 ++ include/boost/multiprecision/prime.hpp | 363 +++ include/boost/multiprecision/reduce_below.hpp | 29 + include/boost/multiprecision/ressol.hpp | 114 + test/zerg.cpp | 32 + 27 files changed, 8925 insertions(+), 2 deletions(-) create mode 100644 include/boost/multiprecision/inverse_euclid.hpp create mode 100644 include/boost/multiprecision/jacobi.hpp create mode 100644 include/boost/multiprecision/mask_bits.hpp create mode 100644 include/boost/multiprecision/modular_inverse.hpp create mode 100644 include/boost/multiprecision/montgomery_int/add.hpp create mode 100644 include/boost/multiprecision/montgomery_int/bitwise.hpp create mode 100644 include/boost/multiprecision/montgomery_int/comparison.hpp create mode 100644 include/boost/multiprecision/montgomery_int/divide.hpp create mode 100644 include/boost/multiprecision/montgomery_int/import_export.hpp create mode 100644 include/boost/multiprecision/montgomery_int/inverse.hpp create mode 100644 include/boost/multiprecision/montgomery_int/limits.hpp create mode 100644 include/boost/multiprecision/montgomery_int/literals.hpp create mode 100644 include/boost/multiprecision/montgomery_int/misc.hpp create mode 100644 include/boost/multiprecision/montgomery_int/modular_reduce.hpp create mode 100644 include/boost/multiprecision/montgomery_int/montgomery_int.hpp create mode 100644 include/boost/multiprecision/montgomery_int/montgomery_params.hpp create mode 100644 include/boost/multiprecision/montgomery_int/multiply.hpp create mode 100644 include/boost/multiprecision/montgomery_int/reduce.hpp create mode 100644 include/boost/multiprecision/montgomery_int/serialize.hpp create mode 100644 include/boost/multiprecision/montgomery_inverse.hpp create mode 100644 include/boost/multiprecision/pow_mod.hpp create mode 100644 include/boost/multiprecision/prime.hpp create mode 100644 include/boost/multiprecision/reduce_below.hpp create mode 100644 include/boost/multiprecision/ressol.hpp create mode 100644 test/zerg.cpp diff --git a/include/boost/multiprecision/detail/default_ops.hpp b/include/boost/multiprecision/detail/default_ops.hpp index 145ecc672..459092c7e 100644 --- a/include/boost/multiprecision/detail/default_ops.hpp +++ b/include/boost/multiprecision/detail/default_ops.hpp @@ -824,6 +824,15 @@ inline int eval_get_sign(const T& val) return val.compare(static_cast(0)); } +template +inline void assign_components_imp(T& result, const long long& v1, const U& v2, const mpl::int_&) +{ + result.m_params = v2; + result = v1; + eval_multiply(result, v2.R2().backend()); + //eval_multiply(result, v1); +} + template inline void assign_components_imp(T& result, const V& v1, const U& v2, const mpl::int_&) { @@ -837,7 +846,6 @@ template inline void assign_components_imp(T& result, const V& v1, const U& v2, const mpl::int_&) { typedef typename component_type >::type component_number_type; - component_number_type x(v1), y(v2); assign_components(result, x.backend(), y.backend()); } diff --git a/include/boost/multiprecision/detail/number_base.hpp b/include/boost/multiprecision/detail/number_base.hpp index cb2951570..685e0fe9c 100644 --- a/include/boost/multiprecision/detail/number_base.hpp +++ b/include/boost/multiprecision/detail/number_base.hpp @@ -1546,7 +1546,8 @@ enum number_category_type number_kind_floating_point = 1, number_kind_rational = 2, number_kind_fixed_point = 3, - number_kind_complex = 4 + number_kind_complex = 4, + number_kind_modulus = 5 }; template diff --git a/include/boost/multiprecision/inverse_euclid.hpp b/include/boost/multiprecision/inverse_euclid.hpp new file mode 100644 index 000000000..0ab37aff6 --- /dev/null +++ b/include/boost/multiprecision/inverse_euclid.hpp @@ -0,0 +1,103 @@ +#ifndef CRYPTO3_INVERSE_EUCLID_HPP +#define CRYPTO3_INVERSE_EUCLID_HPP + +#include + +namespace nil { + namespace crypto3 { + using namespace boost::multiprecision; + + template + inline Backend eval_inverse_euclid(const Backend &n, const Backend &mod) { + + typedef typename default_ops::double_precision_type::type double_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + + using default_ops::eval_is_zero; + using default_ops::eval_lt; + using default_ops::eval_eq; + using default_ops::eval_add; + using default_ops::eval_subtract; + using default_ops::eval_get_sign; + using default_ops::eval_right_shift; + using default_ops::eval_integer_modulus; + + if (eval_is_zero(mod)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("inverse_mod: arguments must be non-zero")); + } + if (eval_get_sign(mod) || eval_get_sign(n)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("inverse_mod: arguments must be non-negative")); + } + + if (eval_is_zero(n) || (!eval_integer_modulus(n, 2) && !eval_integer_modulus(mod, 2))) { + return 0; + } // fast fail checks + + number u = mod, v = n; + number a = 1, b = 0, c = 0, d = 1; + + while (!eval_is_zero(u)) { + const ui_type u_zero_bits = lsb(u); + eval_right_shift(u, u_zero_bits); + + for (std::size_t i = 0; i != u_zero_bits; ++i) { + if (eval_integer_modulus(a, 2) || eval_integer_modulus(b, 2)) { + eval_add(a, n); + eval_subtract(b, mod); + } + eval_right_shift(a, 1); + eval_right_shift(b, 1); + } + + const ui_type v_zero_bits = lsb(v); + eval_right_shift(v, v_zero_bits); + for (size_t i = 0; i != v_zero_bits; ++i) { + if (eval_integer_modulus(c, 2) || eval_integer_modulus(d, 2)) { + eval_add(c, n); + eval_subtract(d, mod); + } + eval_right_shift(c, 1); + eval_right_shift(d, 1); + } + + if (!eval_lt(u, v)) { + eval_subtract(u, v); + eval_subtract(a, c); + eval_subtract(b, d); + } else { + eval_subtract(v, u); + eval_subtract(c, a); + eval_subtract(d, b); + } + } + + if (!eval_eq(v, 1)) { + return 0; + } // no modular inverse + + while (eval_lt(d, 0)) { + eval_add(d, mod); + } + while (d >= mod) { + eval_subtract(d, mod); + } + + return d; + } + + /** + * Modular inversion using extended binary Euclidian algorithm + * @param x a positive integer + * @param modulus a positive integer + * @return y st (x*y) % modulus == 1 or 0 if no such value + * @note Non-const time + */ + template + inline number inverse_euclid(const number &n, + const number &mod) { + return number(eval_inverse_euclid(n.backend(), mod.backend())); + } + } +} + +#endif //CRYPTO3_INVERSE_EUCLID_HPP diff --git a/include/boost/multiprecision/jacobi.hpp b/include/boost/multiprecision/jacobi.hpp new file mode 100644 index 000000000..f11c90727 --- /dev/null +++ b/include/boost/multiprecision/jacobi.hpp @@ -0,0 +1,82 @@ +#ifndef CRYPTO3_JACOBI_HPP +#define CRYPTO3_JACOBI_HPP + +#include + +namespace nil { + namespace crypto3 { + using namespace boost::multiprecision; + + template + inline limb_type eval_jacobi(const Backend &a, const Backend &n) { + using default_ops::eval_is_zero; + using default_ops::eval_lt; + using default_ops::eval_lsb; + using default_ops::eval_gt; + using default_ops::eval_integer_modulus; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + using default_ops::eval_get_sign; + + if (eval_get_sign(a) < 0) { + BOOST_THROW_EXCEPTION(std::invalid_argument("jacobi: first argument must be non-negative")); + } + if (!eval_integer_modulus(n, 2) || eval_lt(n, 2)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("jacobi: second argument must be odd and > 1")); + } + + Backend x = a, y = n; + limb_type J = 1; + + while (eval_gt(y, 1)) { + eval_modulus(x, y); + + Backend yd2 = y; + eval_divide(yd2, 2); + + if (eval_gt(x, yd2)) { + eval_subtract(x, y, x); + if (eval_integer_modulus(y, 4) == 3) { + J = -J; + } + } + if (eval_is_zero(x)) { + return 0; + } + + size_t shifts = eval_lsb(x); + eval_right_shift(x, shifts); + if (eval_integer_modulus(shifts, 2)) { + limb_type y_mod_8 = eval_integer_modulus(y, 8); + if (y_mod_8 == 3 || y_mod_8 == 5) { + J = -J; + } + } + + if (eval_integer_modulus(x, 4) == 3 && eval_integer_modulus(y, 4) == 3) { + J = -J; + } + + std::swap(x, y); + } + return J; + } + + /** + * Compute the Jacobi symbol. If n is prime, this is equivalent + * to the Legendre symbol. + * @see http://mathworld.wolfram.com/JacobiSymbol.html + * + * @param a is a non-negative integer + * @param n is an odd integer > 1 + * @return (n / m) + */ + template + inline typename std::enable_if::value == number_kind_integer, limb_type>::type jacobi( + const number &a, const number &n) { + return number(eval_jacobi(a.backend(), n.backend())); + } + } +} + +#endif //CRYPTO3_JACOBI_HPP \ No newline at end of file diff --git a/include/boost/multiprecision/mask_bits.hpp b/include/boost/multiprecision/mask_bits.hpp new file mode 100644 index 000000000..e83140763 --- /dev/null +++ b/include/boost/multiprecision/mask_bits.hpp @@ -0,0 +1,37 @@ +#ifndef CRYPTO3_MASK_BITS_HPP +#define CRYPTO3_MASK_BITS_HPP + +#include +#include +#include + +namespace nil { + namespace crypto3 { + + template + void eval_mask_bits(Backend &val, Integer n) { + typedef typename boost::multiprecision::limb_type limb_type; + + typedef typename boost::multiprecision::detail::canonical::type ui_type; + static const ui_type zero = 0u; + + if (n == 0) { + val = zero; + return; + } + + const size_t top_word = n / Backend::limb_bits; + const limb_type mask = (limb_type(1) << (n % Backend::limb_bits)) - 1; + + if (top_word < val.size()) { + const size_t len = val.size() - (top_word + 1); + if (len > 0) { + //clear_mem(&val.limbs()[top_word + 1], len); #TODO return this + } + val.limbs()[top_word] &= mask; + } + } + } +} + +#endif //CRYPTO3_MASK_BITS_HPP diff --git a/include/boost/multiprecision/modular_inverse.hpp b/include/boost/multiprecision/modular_inverse.hpp new file mode 100644 index 000000000..11c8edb76 --- /dev/null +++ b/include/boost/multiprecision/modular_inverse.hpp @@ -0,0 +1,179 @@ +#ifndef CRYPTO3_MOD_INVERSE_HPP +#define CRYPTO3_MOD_INVERSE_HPP + +#include + +#include + +#include + +namespace nil { + namespace crypto3 { + using namespace boost::multiprecision; + + template + inline Backend eval_ct_inverse_mod_odd_modulus(const Backend &n, const Backend &mod) { + + typedef typename default_ops::double_precision_type::type double_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + + using default_ops::eval_is_zero; + using default_ops::eval_lt; + using default_ops::eval_eq; + using default_ops::eval_get_sign; + using default_ops::eval_integer_modulus; + using default_ops::eval_msb; + using default_ops::eval_add; + using default_ops::eval_multiply; + using default_ops::eval_multiply_add; + using default_ops::eval_multiply_subtract; + using default_ops::eval_right_shift; + + typedef cpp_int_backend<0, 0, Backend::integer_type, Backend::checked_type, + secure_allocator> secure_cpp_int_backend; + + if (eval_get_sign(n) < 0 || eval_get_sign(mod) < 0) { + BOOST_THROW_EXCEPTION(std::invalid_argument("ct_inverse_mod_odd_modulus: arguments must be " + "non-negative")); + } + + if (eval_lt(mod, 3) || !eval_integer_modulus(mod, 2)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("Bad modulus to ct_inverse_mod_odd_modulus")); + } + if (!eval_lt(n, mod)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("ct_inverse_mod_odd_modulus n >= mod not supported")); + } + + /* + This uses a modular inversion algorithm designed by Niels Möller + and implemented in Nettle. The same algorithm was later also + adapted to GMP in mpn_sec_invert. + + It can be easily implemented in a way that does not depend on + secret branches or memory lookups, providing resistance against + some forms of side channel attack. + + There is also a description of the algorithm in Appendix 5 of "Fast + Software Polynomial Multiplication on ARM Processors using the NEON Engine" + by Danilo Câmara, Conrado P. L. Gouvêa, Julio López, and Ricardo + Dahab in LNCS 8182 + https://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf + + Thanks to Niels for creating the algorithm, explaining some things + about it, and the reference to the paper. + */ + + secure_cpp_int_backend mp1, mp1o2; + eval_add(mod, 1); + eval_right_shift(mp1o2, mp1, 1); + + // todo allow this to be pre-calculated and passed in as arg + + const size_t mod_words = mod.size(); + CRYPTO3_ASSERT(mod_words > 0, "Not empty"); + + secure_cpp_int_backend a = n; + secure_cpp_int_backend b = mod; + secure_cpp_int_backend u = 1, v = 0; + + ct::poison(a.limbs(), a.size()); + ct::poison(b.limbs(), b.size()); + ct::poison(u.limbs(), u.size()); + ct::poison(v.limbs(), v.size()); + + // Only n.bits() + mod.bits() iterations are required, but avoid leaking the size of n + ui_type bits = 2ul * eval_msb(mod); + + while (bits--) { + const bool odd = eval_integer_modulus(a, 2); + eval_multiply_subtract(a, odd, b); + + const bool underflow = eval_get_sign(a) < 0; + eval_multiply_add(b, a, underflow); + + if (eval_get_sign(a) < 0) { + eval_multiply(a, -1); + } + + eval_right_shift(a, 1); + + if (underflow) { + std::swap(u, v); + } + + eval_multiply_subtract(u, odd, v); + eval_multiply_add(u, eval_get_sign(u) < 0, mod); + + eval_right_shift(u, 1); + eval_multiply_add(u, mp1o2, eval_integer_modulus(u, 2)); + } + + ct::unpoison(a.limbs(), a.size()); + ct::unpoison(b.limbs(), b.size()); + ct::unpoison(u.limbs(), u.size()); + ct::unpoison(v.limbs(), v.size()); + + CRYPTO3_ASSERT(eval_is_zero(a), "A is zero"); + + if (!eval_eq(b, 1)) { + return 0; + } + + return v; + } + + template + inline Backend eval_inverse_mod(const Backend &x, const Backend &mod) { + using default_ops::eval_is_zero; + using default_ops::eval_lt; + using default_ops::eval_get_sign; + + if (eval_is_zero(mod)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("eval_inverse_mod: zero division")); + } + if (eval_get_sign(mod) < 0 || eval_get_sign(x) < 0) { + BOOST_THROW_EXCEPTION(std::invalid_argument("eval_inverse_mod: arguments must be non-negative")); + } + + if (eval_is_zero(x) || + (!eval_is_zero(eval_integer_modulus(x, 2)) && !eval_is_zero(eval_integer_modulus(mod, 2)))) { + return 0; + } // fast fail checks + + if (!eval_is_zero(eval_integer_modulus(mod, 2)) && eval_lt(x, mod)) { + return ct_inverse_mod_odd_modulus(x, mod); + } + + return eval_inverse_euclid(x, mod); + } + + /** + * @brief Modular inversion + * @param x a positive integer + * @param mod a positive integer + * @return y st (x*y) % modulus == 1 or 0 if no such value + * @note Non-const time + */ + template + inline number inverse_mod(const number &x, + const number &mod) { + return eval_inverse_mod(x.backend(), mod.backend()); + } + + /** + * @brief Const time modular inversion + * + * @param n + * @param mod + * + * @note Requires the modulus be odd + */ + template + inline number ct_inverse_mod_odd_modulus( + const number &n, const number &mod) { + return number(eval_ct_inverse_mod_odd_modulus(n.backend(), mod.backend())); + } + } +} + +#endif //CRYPTO3_MOD_INVERSE_HPP diff --git a/include/boost/multiprecision/montgomery_int/add.hpp b/include/boost/multiprecision/montgomery_int/add.hpp new file mode 100644 index 000000000..ec274df11 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/add.hpp @@ -0,0 +1,573 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_ADD_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_ADD_HPP + +namespace boost { + namespace multiprecision { + namespace backends { + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) // conditional expression is constant +#endif + + +// +// Now the actual functions called by the front end, all of which forward to one of the above: +// + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_add(montgomery_int_backend &result, + const Backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + eval_add(result, result, o); + } + + template class Backend1, + template< unsigned, unsigned, cpp_integer_type, cpp_int_check_type, typename, typename> class Backend2, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, + class Allocator3, typename ParamsBackend3> + inline typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend1 >::value && !is_trivial_montgomery_int< + Backend2 >::value && + is_equal_montgomery_int_backend>::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_add(montgomery_int_backend &result, + const Backend1 &a, + const Backend2 &b) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (a.sign() != b.sign()) { + subtract_unsigned(result, a, b); + return; + } + add_unsigned(result, a, b); + eval_divide(result, result.m_params.p().backend()); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_add(montgomery_int_backend &result, + const limb_type &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (result.sign()) { + subtract_unsigned(result, result, o); + } else { + add_unsigned(result, result, o); + } + eval_divide(result, result.m_params.p().backend()); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_add(montgomery_int_backend &result, + const Backend &a, + const limb_type &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (a.sign()) { + subtract_unsigned(result, a, o); + } else { + add_unsigned(result, a, o); + } + eval_divide(result, result.m_params.p().backend()); + } + + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_add(montgomery_int_backend &result, + const signed_limb_type &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (o < 0) { + eval_subtract(result, static_cast(boost::multiprecision::detail::unsigned_abs(o))); + } else if (o > 0) { + eval_add(result, static_cast(o)); + } + eval_divide(result, result.m_params.p().backend()); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_add(montgomery_int_backend &result, + const Backend &a, + const signed_limb_type &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (o < 0) { + eval_subtract(result, a, static_cast + (boost::multiprecision::detail::unsigned_abs(o))); + } else if (o > 0) { + eval_add(result, a, static_cast + (o)); + } else if (&result != &a) { + result = a; + eval_divide(result, result.m_params.p().backend()); + } + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_subtract(montgomery_int_backend &result, + const limb_type &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (result.sign()) { + add_unsigned(result, result, o); + } else { + subtract_unsigned(result, result, o); + } + eval_divide(result, result.m_params.p().backend()); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_subtract(montgomery_int_backend &result, + const Backend &a, + const limb_type &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (a.sign()) { + add_unsigned(result, a, o); + } else { + subtract_unsigned(result, a, o); + } + eval_divide(result, result.m_params.p().backend()); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_subtract(montgomery_int_backend &result, + const signed_limb_type &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (o) { + if (o < 0) { + eval_add(result, static_cast(boost::multiprecision::detail::unsigned_abs(o))); + } else { + eval_subtract(result, static_cast(o)); + } + } + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_subtract(montgomery_int_backend &result, + const Backend &a, + const signed_limb_type &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (o) { + if (o < 0) { + eval_add(result, a, static_cast(boost::multiprecision::detail::unsigned_abs(o))); + } else { + eval_subtract(result, a, static_cast(o)); + } + } else if (&result != &a) { + result = a; + eval_divide(result, result.m_params.p().backend()); + } + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_increment(montgomery_int_backend &result) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + static const limb_type one = 1; + if (!result.sign() && (result.limbs()[0] < + montgomery_int_backend::max_limb_value)) { + ++result.limbs()[0]; + eval_divide(result, result.m_params.p().backend()); + } else if (result.sign() && result.limbs()[0]) { + --result.limbs()[0]; + eval_divide(result, result.m_params.p().backend()); + } else { + eval_add(result, one); + } + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_decrement(montgomery_int_backend &result) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + static const limb_type one = 1; + if (!result.sign() && result.limbs()[0]) { + --result.limbs()[0]; + eval_divide(result, result.m_params.p().backend()); + } else if (result.sign() && (result.limbs()[0] < + montgomery_int_backend::max_limb_value)) { + ++result.limbs()[0]; + eval_divide(result, result.m_params.p().backend()); + } else { + eval_subtract(result, one); + } + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_subtract(montgomery_int_backend &result, + const Backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + eval_subtract(result, result, o); + } + + template class Backend1, + template< unsigned, unsigned, cpp_integer_type, cpp_int_check_type, typename, typename> class Backend2, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, + class Allocator3, typename ParamsBackend3> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend1 >::value && + !is_trivial_montgomery_int< + Backend2 >::value && + is_equal_montgomery_int_backend>::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_subtract(montgomery_int_backend &result, + const Backend1 &a, + const Backend2 &b) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (a.sign() != b.sign()) { + add_unsigned(result, a, b); + eval_divide(result, result.m_params.p().backend()); + return; + } + subtract_unsigned(result, a, b); + eval_divide(result, result.m_params.p().backend()); + } + +// +// Simple addition and subtraction routine for trivial cpp_int's come last: +// +// One of the arguments is signed: +// + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + inline typename enable_if_c >::value && + is_trivial_montgomery_int< + montgomery_int_backend >::value && (is_signed_number< + montgomery_int_backend >::value || + is_signed_number< + montgomery_int_backend< + MinBits1, MaxBits1, + SignType1, Checked1, + Allocator1, ParamsBackend1> >::value) && + is_trivial_montgomery_int< + Backend >::value && + is_trivial_montgomery_int< + Backend >::value && (is_signed_number< + Backend >::value || + is_signed_number< + Backend< + MinBits1, MaxBits1, + SignType1, Checked1, + Allocator1, ParamsBackend1> >::value) && + is_equal_montgomery_int_backend>::value> + + ::type eval_add(montgomery_int_backend &result, + const Backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (result.sign() != o.sign()) { + if (*o.limbs() > *result.limbs()) { + *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), + typename montgomery_int_backend::checked_type()); + + result.negate(); + } else { + *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), + typename montgomery_int_backend::checked_type()); + } + } else { + *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), + typename montgomery_int_backend::checked_type()); + } + + result.normalize(); + eval_divide(result, result.m_params.p().backend()); + } + +// Simple version for two unsigned arguments: + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + is_trivial_montgomery_int< + montgomery_int_backend >::value && + is_unsigned_number< + montgomery_int_backend >::value && + is_unsigned_number< + montgomery_int_backend >::value && + is_trivial_montgomery_int< + Backend >::value && + is_trivial_montgomery_int< + Backend >::value && + is_unsigned_number< + Backend >::value && + is_unsigned_number< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_add(montgomery_int_backend &result, + const Backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), + typename montgomery_int_backend::checked_type()); + + result.normalize(); + eval_divide(result, result.m_params.p().backend()); + } + +// signed subtraction: + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + inline typename enable_if_c >::value && + is_trivial_montgomery_int< + montgomery_int_backend >::value && (is_signed_number< + montgomery_int_backend >::value || + is_signed_number< + montgomery_int_backend< + MinBits1, MaxBits1, + SignType1, Checked1, + Allocator1, ParamsBackend1> >::value) && + is_trivial_montgomery_int< + Backend >::value && + is_trivial_montgomery_int< + Backend >::value && (is_signed_number< + Backend >::value || + is_signed_number< + Backend< + MinBits1, MaxBits1, + SignType1, Checked1, + Allocator1, ParamsBackend1> >::value) && + is_equal_montgomery_int_backend>::value> + + ::type eval_subtract(montgomery_int_backend &result, + const Backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + if (result.sign() != o.sign()) { + *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), + typename montgomery_int_backend::checked_type()); + } else if (*result.limbs() < *o.limbs()) { + *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), + typename montgomery_int_backend::checked_type()); + + result.negate(); + } else { + *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), + typename montgomery_int_backend::checked_type()); + } + + result.normalize(); + eval_divide(result, result.m_params.p().backend()); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + is_trivial_montgomery_int< + montgomery_int_backend >::value && + is_unsigned_number< + montgomery_int_backend >::value && + is_unsigned_number< + montgomery_int_backend >::value && + is_trivial_montgomery_int< + Backend >::value && + is_trivial_montgomery_int< + Backend >::value && + is_unsigned_number< + Backend >::value && + is_unsigned_number< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_subtract(montgomery_int_backend &result, + const Backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), + typename montgomery_int_backend::checked_type()); + + result.normalize(); + eval_divide(result, result.m_params.p().backend()); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend>::value> + + ::type eval_subtract(montgomery_int_backend &result, + const Backend &o) + { + int x = 0; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend1>::value> + ::type eval_subtract(montgomery_int_backend &result, + const Backend1 &a, const Backend2 &b) + { + int x = 0; + } + + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + } + } +} // namespaces + +#endif \ No newline at end of file diff --git a/include/boost/multiprecision/montgomery_int/bitwise.hpp b/include/boost/multiprecision/montgomery_int/bitwise.hpp new file mode 100644 index 000000000..52e52704a --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/bitwise.hpp @@ -0,0 +1,605 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_BIT_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_BIT_HPP + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4319) +#endif + +namespace boost { + namespace multiprecision { + namespace backends { + + template + void is_valid_bitwise_op(montgomery_int_backend &result, + const montgomery_int_backend &o, + const mpl::int_ &) { + if (result.sign() || o.sign()) { + BOOST_THROW_EXCEPTION( + std::range_error("Bitwise operations on negative values results in undefined behavior.")); + } + } + + template + void is_valid_bitwise_op(montgomery_int_backend &, + const montgomery_int_backend &, + const mpl::int_ &) { + } + + template + void is_valid_bitwise_op( + const montgomery_int_backend &result, + const mpl::int_ &) { + if (result.sign()) { + BOOST_THROW_EXCEPTION( + std::range_error("Bitwise operations on negative values results in undefined behavior.")); + } + } + + template + void is_valid_bitwise_op( + const montgomery_int_backend &, + const mpl::int_ &) { + } + + template + void is_valid_bitwise_op(montgomery_int_backend &, + const mpl::int_ &) { + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_bitwise_and(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + bitwise_op(result, o, bit_and(), mpl::bool_ > >::is_signed || + std::numeric_limits< + number>>::is_signed>()); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_bitwise_or(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + bitwise_op(result, o, bit_or(), mpl::bool_ > >::is_signed || + std::numeric_limits< + number>>::is_signed>()); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_bitwise_xor(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + bitwise_op(result, o, bit_xor(), mpl::bool_ > >::is_signed || + std::numeric_limits< + number>>::is_signed>()); + } + +// +// Again for operands which are single limbs: +// + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + ::type eval_bitwise_and( + montgomery_int_backend &result, limb_type + l) BOOST_NOEXCEPT { + result.limbs()[0] &= l; + result.resize(1, 1); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_bitwise_or( + montgomery_int_backend &result, limb_type l) + + BOOST_NOEXCEPT { + result.limbs()[0] |= l; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_bitwise_xor( + montgomery_int_backend &result, limb_type l) + + BOOST_NOEXCEPT { + result.limbs()[0] ^= l; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_signed_number >::value && + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_complement(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), + "Attempt to take the complement of a signed type results in undefined behavior."); +// Increment and negate: + result = o; + eval_increment(result); + result.negate(); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_unsigned_number >::value && + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_complement(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + unsigned os = o.size(); + result.resize(UINT_MAX, os); + for (unsigned i = 0; i < os; ++i) { + result.limbs()[i] = ~o.limbs()[i]; + } + + for (unsigned i = os; i < result.size(); ++i) { + result.limbs()[i] = ~static_cast(0); + } + + result.normalize(); + } + + template + inline typename enable_if_c< + !is_trivial_montgomery_int >::value> + + ::type eval_left_shift(montgomery_int_backend &result, + double_limb_type s) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + is_valid_bitwise_op(result, + + typename montgomery_int_backend::checked_type() + + ); + if (!s) { + return; + } + +#if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT) + static const limb_type limb_shift_mask = montgomery_int_backend::limb_bits - 1; + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if((s & limb_shift_mask) == 0) + { + left_shift_limb(result, s); + } + else if((s & byte_shift_mask) == 0) + { + left_shift_byte(result, s); + } +#elif defined(BOOST_LITTLE_ENDIAN) + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & byte_shift_mask) == 0) { + left_shift_byte(result, s); + } +#else + static const limb_type limb_shift_mask = + montgomery_int_backend::limb_bits - 1; + if (( + s &limb_shift_mask + ) == 0) + { + left_shift_limb(result, s + ); + } +#endif + else { + left_shift_generic(result, s); + } +// +// We may have shifted off the end and have leading zeros: +// + result.normalize(); + } + template + inline typename enable_if_c >::value> + + ::type eval_right_shift( + montgomery_int_backend &result, + double_limb_type s) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + is_valid_bitwise_op(result, + + typename montgomery_int_backend::checked_type() + + ); + if (!s) { + return; + } + +#if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT) + static const limb_type limb_shift_mask = montgomery_int_backend::limb_bits - 1; + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if((s & limb_shift_mask) == 0) + right_shift_limb(result, s); + else if((s & byte_shift_mask) == 0) + right_shift_byte(result, s); +#elif defined(BOOST_LITTLE_ENDIAN) + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & byte_shift_mask) == 0) { + right_shift_byte(result, s); + } +#else + static const limb_type limb_shift_mask = + montgomery_int_backend::limb_bits - 1; + if ((s &limb_shift_mask) == 0) { + right_shift_limb(result, s); + } +#endif + else { + right_shift_generic(result, s); + } + } + + template + inline typename enable_if_c >::value> + + ::type eval_right_shift(montgomery_int_backend &result, + double_limb_type s) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + is_valid_bitwise_op(result, typename montgomery_int_backend::checked_type()); + if (!s) { + return; + } + + bool is_neg = result.sign(); + if (is_neg) { + eval_increment(result); + } + +#if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT) + static const limb_type limb_shift_mask = montgomery_int_backend::limb_bits - 1; + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if((s & limb_shift_mask) == 0) + right_shift_limb(result, s); + else if((s & byte_shift_mask) == 0) + right_shift_byte(result, s); +#elif defined(BOOST_LITTLE_ENDIAN) + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & byte_shift_mask) == 0) { + right_shift_byte(result, s); + } +#else + static const limb_type limb_shift_mask = + montgomery_int_backend::limb_bits - 1; + if ((s &limb_shift_mask) == 0) { + right_shift_limb(result, s); + } +#endif + else { + right_shift_generic(result, s); + } + if (is_neg) { + eval_decrement(result); + } + } + +// +// Over again for trivial cpp_int's: +// + template BOOST_MP_FORCEINLINE typename enable_if< + is_trivial_montgomery_int < montgomery_int_backend > > + + ::type eval_left_shift(montgomery_int_backend &result, T s) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + is_valid_bitwise_op(result,typename montgomery_int_backend::checked_type()); + *result.limbs() = detail::checked_left_shift(*result.limbs(), s, + typename montgomery_int_backend::checked_type()); + + result.normalize(); + } + + template BOOST_MP_FORCEINLINE typename enable_if< + is_trivial_montgomery_int < montgomery_int_backend > > + + ::type eval_right_shift(montgomery_int_backend &result, T s) + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { +// Nothing to check here... just make sure we don't invoke undefined behavior: + is_valid_bitwise_op(result, typename montgomery_int_backend::checked_type()); + *result.limbs() = (static_cast(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign + () ? ((--*result.limbs()) >> s) + 1 : *result.limbs()>> s); + + if (result.sign() && (*result.limbs() == 0)) { + result = static_cast(-1); + } + } + + template + inline typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + (is_signed_number >::value || + is_signed_number >::value)> + + ::type eval_complement(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), + "Attempt to take the complement of a signed type results in undefined behavior."); +// +// If we're not checked then emulate 2's complement behavior: +// + if (o.sign()) { + *result.limbs() = *o.limbs() - 1; + + result.sign(false); + } else { + *result.limbs() = 1 + *o.limbs(); + + result.sign(true); + } + result.normalize(); + } + + template + inline typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + is_unsigned_number >::value && + is_unsigned_number >::value> + + ::type eval_complement(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + *result.limbs() = ~*o.limbs(); + + result.normalize(); + } + + template + inline typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + is_unsigned_number >::value && + is_unsigned_number >::value> + + ::type eval_bitwise_and(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + *result.limbs() &= *o.limbs(); + } + + template + inline typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + (is_signed_number >::value || + is_signed_number >::value)> + + ::type eval_bitwise_and(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + is_valid_bitwise_op(result, o, + + typename montgomery_int_backend::checked_type() + + ); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if (result.sign() || o.sign()) { + static const unsigned m = static_unsigned_max::value, + static_unsigned_max::value>::value; + montgomery_int_backend t1(result); + montgomery_int_backend t2(o); + eval_bitwise_and(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if (s) { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } else { + *result.limbs() &= *o.limbs(); + } + } + + template + inline typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + is_unsigned_number >::value && + is_unsigned_number >::value> + + ::type eval_bitwise_or(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + *result.limbs() |= *o.limbs(); + } + + template + inline typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + (is_signed_number >::value || + is_signed_number >::value)> + + ::type eval_bitwise_or(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + is_valid_bitwise_op(result, o, + + typename montgomery_int_backend::checked_type() + + ); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if (result.sign() || o.sign()) { + static const unsigned m = static_unsigned_max::value, + static_unsigned_max::value>::value; + montgomery_int_backend t1(result); + montgomery_int_backend t2(o); + eval_bitwise_or(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if (s) { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } else { + *result.limbs() |= *o.limbs(); + result.normalize(); + } + } + + template + inline typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + is_unsigned_number >::value && + is_unsigned_number >::value> + + ::type eval_bitwise_xor(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + *result.limbs() ^= *o.limbs(); + } + + template + inline typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + (is_signed_number >::value || + is_signed_number >::value)> + + ::type eval_bitwise_xor(montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + is_valid_bitwise_op(result, o, typename montgomery_int_backend::checked_type()); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if (result.sign() || o.sign()) { + static const unsigned m = static_unsigned_max::value, + static_unsigned_max::value>::value; + montgomery_int_backend t1(result); + montgomery_int_backend t2(o); + eval_bitwise_xor(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if (s) { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } else { + *result.limbs() ^= *o.limbs(); + } + } + } + } +} // namespaces + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/include/boost/multiprecision/montgomery_int/comparison.hpp b/include/boost/multiprecision/montgomery_int/comparison.hpp new file mode 100644 index 000000000..b02c1cf80 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/comparison.hpp @@ -0,0 +1,479 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_COMPARISON_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_COMPARISON_HPP + +#include + +namespace boost { + namespace multiprecision { + + namespace backends { + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4018 4389 4996) +#endif + +// +// Start with non-trivial cpp_int's: +// + template class Backend, + unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, typename ParamsBackend> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_eq(const montgomery_int_backend &a, + const Backend &b) BOOST_NOEXCEPT { +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) + return (a.sign() == b.sign()) + && (a.size() == b.size()) + && std::equal(a.limbs(), a.limbs() + a.size(), + stdext::checked_array_iterator::const_limb_pointer>(b.limbs(), b.size())); +#else + return (a.sign() == b.sign()) && (a.size() == b.size()) && + std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); +#endif + } + + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_eq(const montgomery_int_backend &a, + const Backend &b) BOOST_NOEXCEPT { +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) + return (a.sign() == b.sign()) + && (a.size() == b.size()) + && std::equal(a.limbs(), a.limbs() + a.size(), stdext::checked_array_iterator::const_limb_pointer>(b.limbs(), b.size())); +#else + return (a.sign() == b.sign()) && (a.size() == b.size()) && + std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); +#endif + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_eq(const montgomery_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + return (a.sign() == false) && (a.size() == 1) && (*a.limbs() == b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_eq(const montgomery_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + return (a.sign() == (b < 0)) && (a.size() == 1) && + (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b)); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_eq(const montgomery_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + return (a.size() == 1) && (*a.limbs() == b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_eq(const montgomery_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + return (b < 0) ? eval_eq(a, + montgomery_int_backend(b)) : eval_eq( + a, static_cast(b)); // Use bit pattern of b for comparison + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_lt(const montgomery_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + if (a.sign()) { + return true; + } + if (a.size() > 1) { + return false; + } + return *a.limbs() < b; + } + + template + inline typename enable_if_c >::value, bool> + + ::type eval_lt(const montgomery_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + if ((b == 0) || (a.sign() != (b < 0))) { + return a.sign(); + } + if (a.sign()) { + if (a.size() > 1) { + return true; + } + return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b); + } else { + if (a.size() > 1) { + return false; + } + return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b); + } + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_lt(const montgomery_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + if (a.size() > 1) { + return false; + } + return *a.limbs() < b; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_lt(const montgomery_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + return (b < 0) ? a.compare(b) < 0 : eval_lt(a, + static_cast(b)); // Use bit pattern of b for comparison + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_gt(const montgomery_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + if (a.sign()) { + return false; + } + if (a.size() > 1) { + return true; + } + return *a.limbs() > b; + } + + template + inline typename enable_if_c >::value, bool> + + ::type eval_gt(const montgomery_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + if (b == 0) { + return !a.sign() && ((a.size() > 1) || *a.limbs()); + } + if (a.sign() != (b < 0)) { + return !a.sign(); + } + if (a.sign()) { + if (a.size() > 1) { + return false; + } + return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b); + } else { + if (a.size() > 1) { + return true; + } + return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b); + } + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_gt(const montgomery_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + if (a.size() > 1) { + return true; + } + return *a.limbs() > b; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_gt(const montgomery_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + return (b < 0) ? a.compare(b) > 0 : eval_gt(a, + static_cast(b)); // Use bit pattern of b for comparison. + } + + /*!template class Backend, + unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator, typename ParamsBackend> + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::value eval_eq(const montgomery_int_backend &a, + const montgomery_int_backend &b) BOOST_NOEXCEPT { + return (a.sign() == b.sign()) && (*a.limbs() == *b.limbs()); + }*/ + + +// +// And again for trivial cpp_ints: +// + template class Backend, + unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, typename ParamsBackend> + + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::value eval_eq(const montgomery_int_backend &a, + const Backend &b) BOOST_NOEXCEPT { + return (a.sign() == b.sign()) && (*a.limbs() == *b.limbs()); + } + + template class Backend, + unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, typename ParamsBackend> + + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + is_equal_montgomery_int_backend>::value> + + ::value eval_eq(const montgomery_int_backend &a, + const Backend &b) BOOST_NOEXCEPT { + return *a.limbs() == *b.limbs(); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_eq(const montgomery_int_backend &a, + U b) BOOST_NOEXCEPT { + return !a.sign() && (*a.limbs() == b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_eq(const montgomery_int_backend &a, + S b) BOOST_NOEXCEPT { + return (a.sign() == (b < 0)) && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b)); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_eq(const montgomery_int_backend &a, + U b) BOOST_NOEXCEPT { + return *a.limbs() == b; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_eq(const montgomery_int_backend &a, + S b) BOOST_NOEXCEPT { + typedef typename make_unsigned::type ui_type; + if (b < 0) { + montgomery_int_backend t(b); + return *a.limbs() == *t.limbs(); + } else { + return *a.limbs() == static_cast(b); + } + } + + template class Backend, + unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, typename ParamsBackend> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_lt(const montgomery_int_backend &a, + const Backend &b) BOOST_NOEXCEPT { + if (a.sign() != b.sign()) { + return a.sign(); + } + return a.sign() ? *a.limbs() > *b.limbs() : *a.limbs() < *b.limbs(); + } + + template class Backend, + unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, typename ParamsBackend> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_lt(const montgomery_int_backend &a, + const montgomery_int_backend &b) BOOST_NOEXCEPT { + return *a.limbs() < *b.limbs(); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_lt(const montgomery_int_backend &a, + U b) BOOST_NOEXCEPT { + if (a.sign()) { + return true; + } + return *a.limbs() < b; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_lt(const montgomery_int_backend &a, + S b) BOOST_NOEXCEPT { + if (a.sign() != (b < 0)) { + return a.sign(); + } + return a.sign() ? (*a.limbs() > boost::multiprecision::detail::unsigned_abs(b)) : (*a.limbs() < + boost::multiprecision::detail::unsigned_abs( + b)); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_lt(const montgomery_int_backend &a, + U b) BOOST_NOEXCEPT { + return *a.limbs() < b; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_lt(const montgomery_int_backend &a, + S b) BOOST_NOEXCEPT { + typedef typename make_unsigned::type ui_type; + if (b < 0) { + montgomery_int_backend t(b); + return *a.limbs() < *t.limbs(); + } else { + return *a.limbs() < static_cast(b); + } + } + + template class Backend, + unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, typename ParamsBackend> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_gt(const montgomery_int_backend &a, + const Backend &b) BOOST_NOEXCEPT { + if (a.sign() != b.sign()) { + return !a.sign(); + } + return a.sign() ? *a.limbs() < *b.limbs() : *a.limbs() > *b.limbs(); + } + + template class Backend, + unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, typename ParamsBackend> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + is_trivial_montgomery_int< + Backend >::value && + is_equal_montgomery_int_backend>::value> + + ::type eval_gt(const montgomery_int_backend &a, + const Backend &b) BOOST_NOEXCEPT { + return *a.limbs() > *b.limbs(); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_gt(const montgomery_int_backend &a, + U b) BOOST_NOEXCEPT { + if (a.sign()) { + return false; + } + return *a.limbs() > b; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_gt(const montgomery_int_backend &a, + S b) BOOST_NOEXCEPT { + if (a.sign() != (b < 0)) { + return !a.sign(); + } + return a.sign() ? (*a.limbs() < boost::multiprecision::detail::unsigned_abs(b)) : (*a.limbs() > + boost::multiprecision::detail::unsigned_abs( + b)); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_gt(const montgomery_int_backend &a, + U b) BOOST_NOEXCEPT { + return *a.limbs() > b; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && is_trivial_montgomery_int< + montgomery_int_backend >::value, bool> + + ::type eval_gt(const montgomery_int_backend &a, + S b) BOOST_NOEXCEPT { + typedef typename make_unsigned::type ui_type; + if (b < 0) { + montgomery_int_backend t(b); + return *a.limbs() > *t.limbs(); + } else { + return *a.limbs() > static_cast(b); + } + } + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + + } + } +} // namespaces + +#endif \ No newline at end of file diff --git a/include/boost/multiprecision/montgomery_int/divide.hpp b/include/boost/multiprecision/montgomery_int/divide.hpp new file mode 100644 index 000000000..e4a92048a --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/divide.hpp @@ -0,0 +1,477 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_DIV_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_DIV_HPP + +namespace boost { + namespace multiprecision { + namespace backends { + + template + + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int::value && + !is_trivial_montgomery_int::value> + + ::type eval_divide(montgomery_int_backend &result, + const Backend2 &a, + const Backend3 &b) { + montgomery_int_backend r; + bool s = a.sign() != b.sign(); + divide_unsigned_helper(&result, a, b, r); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int::value> + + ::type eval_divide(montgomery_int_backend &result, + const Backend2 &a, + limb_type &b) { + montgomery_int_backend r; + bool s = a.sign(); + divide_unsigned_helper(&result, a, b, r); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int::value> + + ::type eval_divide(montgomery_int_backend &result, + const Backend2 &a, + signed_limb_type &b) { + montgomery_int_backend r; + bool s = a.sign() != (b < 0); + divide_unsigned_helper(&result, a, + static_cast(boost::multiprecision::detail::unsigned_abs(b)), r); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int::value> + + ::type eval_divide(montgomery_int_backend &result, + const Backend2 &b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_divide(result, a, b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value> + + ::type eval_divide(montgomery_int_backend &result, + limb_type b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_divide(result, a, b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value> + + ::type eval_divide(montgomery_int_backend &result, + signed_limb_type b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_divide(result, a, b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int::value && + !is_trivial_montgomery_int::value> + + ::type eval_modulus(montgomery_int_backend &result, + const Backend2 &a, + const Backend3 &b) { + bool s = a.sign(); + divide_unsigned_helper( + static_cast * >(0), a, b, + result); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int::value> + + ::type eval_modulus(montgomery_int_backend &result, + const Backend2 &a, + limb_type b) { + bool s = a.sign(); + divide_unsigned_helper( + static_cast * >(0), a, b, + result); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int::value> + + ::type eval_modulus(montgomery_int_backend &result, + const Backend2 &a, + signed_limb_type b) { + bool s = a.sign(); + divide_unsigned_helper( + static_cast * >(0), a, + static_cast(boost::multiprecision::detail::unsigned_abs(b)), result); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int::value> + + ::type eval_modulus(montgomery_int_backend &result, + const Backend2 &b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_modulus(result, a, b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value> + + ::type eval_modulus(montgomery_int_backend &result, + limb_type b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_modulus(result, a, b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value> + + ::type eval_modulus(montgomery_int_backend &result, + signed_limb_type b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_modulus(result, a, b); + } + +// +// Over again for trivial cpp_int's: +// + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int::value && + (is_signed_number >::value || + is_signed_number::value)> + + ::type eval_divide(montgomery_int_backend &result, + const Backend &o) { + if (!*o.limbs()) { + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + } + *result.limbs() /= *o.limbs(); + result.sign(result.sign() != o.sign()); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int::value && + is_unsigned_number >::value && + is_unsigned_number::value> + + ::type eval_divide(montgomery_int_backend &result, + const Backend &o) { + if (!*o.limbs()) { + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + } + *result.limbs() /= *o.limbs(); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int::value> + + ::type eval_modulus(montgomery_int_backend &result, + const Backend &o) { + if (!*o.limbs()) { + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + } + *result.limbs() %= *o.limbs(); + result.sign(result.sign()); + } + /* + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_divide(montgomery_int_backend &result, + const montgomery_int_backend &a, + const montgomery_int_backend &b) { + montgomery_int_backend r; + bool s = a.sign() != b.sign(); + divide_unsigned_helper(&result, a, b, r); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_divide(montgomery_int_backend &result, + const montgomery_int_backend &a, + limb_type &b) { + montgomery_int_backend r; + bool s = a.sign(); + divide_unsigned_helper(&result, a, b, r); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_divide(montgomery_int_backend &result, + const montgomery_int_backend &a, + signed_limb_type &b) { + montgomery_int_backend r; + bool s = a.sign() != (b < 0); + divide_unsigned_helper(&result, a, + static_cast(boost::multiprecision::detail::unsigned_abs(b)), r); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_divide(montgomery_int_backend &result, + const montgomery_int_backend &b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_divide(result, a, b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value> + + ::type eval_divide(montgomery_int_backend &result, + limb_type b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_divide(result, a, b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value> + + ::type eval_divide(montgomery_int_backend &result, + signed_limb_type b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_divide(result, a, b); + } + --- + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_modulus(montgomery_int_backend &result, + const montgomery_int_backend &a, + const montgomery_int_backend &b) { + bool s = a.sign(); + divide_unsigned_helper( + static_cast * >(0), a, b, + result); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_modulus(montgomery_int_backend &result, + const montgomery_int_backend &a, + limb_type b) { + bool s = a.sign(); + divide_unsigned_helper( + static_cast * >(0), a, b, + result); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_modulus(montgomery_int_backend &result, + const montgomery_int_backend &a, + signed_limb_type b) { + bool s = a.sign(); + divide_unsigned_helper( + static_cast * >(0), a, + static_cast(boost::multiprecision::detail::unsigned_abs(b)), result); + result.sign(s); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int >::value> + + ::type eval_modulus(montgomery_int_backend &result, + const montgomery_int_backend &b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_modulus(result, a, b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value> + + ::type eval_modulus(montgomery_int_backend &result, + limb_type b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_modulus(result, a, b); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value> + + ::type eval_modulus(montgomery_int_backend &result, + signed_limb_type b) { + // There is no in place divide: + montgomery_int_backend a(result); + eval_modulus(result, a, b); + } + +// +// Over again for trivial cpp_int's: +// + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + (is_signed_number >::value || + is_signed_number >::value)> + + ::type eval_divide(montgomery_int_backend &result, + const montgomery_int_backend &o) { + if (!*o.limbs()) { + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + } + *result.limbs() /= *o.limbs(); + result.sign(result.sign() != o.sign()); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value && + is_unsigned_number >::value && + is_unsigned_number >::value> + + ::type eval_divide(montgomery_int_backend &result, + const montgomery_int_backend &o) { + if (!*o.limbs()) { + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + } + *result.limbs() /= *o.limbs(); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int >::value && + is_trivial_montgomery_int >::value> + + ::type eval_modulus(montgomery_int_backend &result, + const montgomery_int_backend &o) { + if (!*o.limbs()) { + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + } + *result.limbs() %= *o.limbs(); + result.sign(result.sign()); + } + */ + + } + } +} // namespaces + +#endif diff --git a/include/boost/multiprecision/montgomery_int/import_export.hpp b/include/boost/multiprecision/montgomery_int/import_export.hpp new file mode 100644 index 000000000..13d27aaa1 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/import_export.hpp @@ -0,0 +1,298 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_IMPORT_EXPORT_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_IMPORT_EXPORT_HPP + +//#include +//#include + +namespace boost { + namespace multiprecision { + + namespace detail { + template + montgomery_int_backend &eval_import_bits_generic(montgomery_int_backend &val, Iterator i, Iterator j, unsigned chunk_size = 0, + bool msv_first = true) { + montgomery_int_backend newval; + + typedef typename std::iterator_traits::value_type value_type; + typedef typename boost::make_unsigned::type unsigned_value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename boost::make_unsigned::type size_type; + typedef typename montgomery_int_backend::trivial_tag tag_type; + + if (!chunk_size) { + chunk_size = std::numeric_limits::digits; + } + + size_type limbs = std::distance(i, j); + size_type bits = limbs * chunk_size; + + detail::resize_to_bit_size(newval, static_cast(bits), tag_type()); + + difference_type bit_location = msv_first ? bits - chunk_size : 0; + difference_type bit_location_change = msv_first ? -static_cast(chunk_size) + : chunk_size; + + while (i != j) { + detail::assign_bits(newval, static_cast(*i), + static_cast(bit_location), chunk_size, tag_type()); + ++i; + bit_location += bit_location_change; + } + + newval.normalize(); + + val.swap(newval); + return val; + } + + template + inline typename boost::disable_if_c>::value, + montgomery_int_backend &>::type eval_import_bits_fast(montgomery_int_backend &val, T *i, T *j, unsigned chunk_size = 0) { + std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i)); + std::size_t limb_len = byte_len / sizeof(limb_type); + if (byte_len % sizeof(limb_type)) { + ++limb_len; + } + val.resize(static_cast(limb_len), + static_cast(limb_len)); // checked types may throw here if they're not large enough to hold the data! + val.limbs()[val.size() - 1] = 0u; + std::memcpy(val.limbs(), i, (std::min)(byte_len, val.size() * sizeof(limb_type))); + val.normalize(); // In case data has leading zeros. + return val; + } + + template + inline typename boost::enable_if_c>::value, + montgomery_int_backend &>::type eval_import_bits_fast(montgomery_int_backend &val, T *i, T *j, unsigned chunk_size = 0) { + std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i)); + std::size_t limb_len = byte_len / sizeof(val.limbs()[0]); + if (byte_len % sizeof(val.limbs()[0])) { + ++limb_len; + } + val.limbs()[0] = 0u; + val.resize(static_cast(limb_len), + static_cast(limb_len)); // checked types may throw here if they're not large enough to hold the data! + std::memcpy(val.limbs(), i, (std::min)(byte_len, val.size() * sizeof(val.limbs()[0]))); + val.normalize(); // In case data has leading zeros. + return val; + } + + template + number, + ExpressionTemplates> &import_bits_generic( + number, + ExpressionTemplates> &val, Iterator i, Iterator j, unsigned chunk_size = 0, + bool msv_first = true) { + typename number, + ExpressionTemplates>::backend_type newval; + + typedef typename std::iterator_traits::value_type value_type; + typedef typename boost::make_unsigned::type unsigned_value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename boost::make_unsigned::type size_type; + typedef typename montgomery_int_backend::trivial_tag tag_type; + + if (!chunk_size) { + chunk_size = std::numeric_limits::digits; + } + + size_type limbs = std::distance(i, j); + size_type bits = limbs * chunk_size; + + detail::resize_to_bit_size(newval, static_cast(bits), tag_type()); + + difference_type bit_location = msv_first ? bits - chunk_size : 0; + difference_type bit_location_change = msv_first ? -static_cast(chunk_size) + : chunk_size; + + while (i != j) { + detail::assign_bits(newval, static_cast(*i), + static_cast(bit_location), chunk_size, tag_type()); + ++i; + bit_location += bit_location_change; + } + + newval.normalize(); + + val.backend().swap(newval); + return val; + } + + template + inline typename boost::disable_if_c >::value, + number, + ExpressionTemplates> &> + + ::type import_bits_fast(number, + ExpressionTemplates> &val, T *i, T *j, unsigned chunk_size = 0) { + std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i)); + std::size_t limb_len = byte_len / sizeof(limb_type); + if (byte_len % sizeof(limb_type)) { + ++limb_len; + } + montgomery_int_backend &result = val.backend(); + result.resize(static_cast(limb_len), + static_cast(limb_len)); // checked types may throw here if they're not large enough to hold the data! + result.limbs()[result.size() - 1] = 0u; + std::memcpy(result.limbs(), i, (std::min)(byte_len, result.size() * sizeof(limb_type))); + result.normalize(); // In case data has leading zeros. + return val; + } + + template + inline typename boost::enable_if_c >::value, + number, + ExpressionTemplates> &> + + ::type import_bits_fast(number, + ExpressionTemplates> &val, T *i, T *j, unsigned chunk_size = 0) { + montgomery_int_backend &result = val.backend(); + std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i)); + std::size_t limb_len = byte_len / sizeof(result.limbs()[0]); + if (byte_len % sizeof(result.limbs()[0])) { + ++limb_len; + } + result.limbs()[0] = 0u; + result.resize(static_cast(limb_len), + static_cast(limb_len)); // checked types may throw here if they're not large enough to hold the data! + std::memcpy(result.limbs(), i, (std::min)(byte_len, result.size() * sizeof(result.limbs()[0]))); + result.normalize(); // In case data has leading zeros. + return val; + } + } + + template + inline montgomery_int_backend &eval_import_bits(montgomery_int_backend &val, Iterator i, Iterator j, unsigned chunk_size = 0, + bool msv_first = true) { + return detail::eval_import_bits_generic(val, i, j, chunk_size, msv_first); + } + + template + inline montgomery_int_backend &eval_import_bits(montgomery_int_backend &val, T *i, T *j, unsigned chunk_size = 0, bool msv_first = true) { +#ifdef BOOST_LITTLE_ENDIAN + if (((chunk_size % CHAR_BIT) == 0) && !msv_first) { + return detail::eval_import_bits_fast(val, i, j, chunk_size); + } +#endif + return detail::eval_import_bits_generic(val, i, j, chunk_size, msv_first); + } + + template + OutputIterator eval_export_bits(const montgomery_int_backend &val, OutputIterator out, unsigned chunk_size, + bool msv_first = true) { +#ifdef _MSC_VER + #pragma warning(push) +#pragma warning(disable:4244) +#endif + + typedef typename montgomery_int_backend::trivial_tag tag_type; + if (eval_is_zero(val)) { + *out = 0; + ++out; + return out; + } + unsigned bitcount = backends::eval_msb_imp(val) + 1; + unsigned chunks = bitcount / chunk_size; + if (bitcount % chunk_size) { + ++chunks; + } + + int bit_location = msv_first ? bitcount - chunk_size : 0; + int bit_step = msv_first ? -static_cast(chunk_size) : chunk_size; + while (bit_location % bit_step) { + ++bit_location; + } + + do { + *out = detail::extract_bits(val, bit_location, chunk_size, tag_type()); + ++out; + bit_location += bit_step; + } while ((bit_location >= 0) && (bit_location < (int) bitcount)); + + return out; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } + + template + inline number, + ExpressionTemplates> &import_bits( + number, + ExpressionTemplates> &val, Iterator i, Iterator j, unsigned chunk_size = 0, + bool msv_first = true) { + return detail::import_bits_generic(val, i, j, chunk_size, msv_first); + } + + template + inline number, + ExpressionTemplates> &import_bits( + number, + ExpressionTemplates> &val, T *i, T *j, unsigned chunk_size = 0, bool msv_first = true) { +#ifdef BOOST_LITTLE_ENDIAN + if (((chunk_size % CHAR_BIT) == 0) && !msv_first) { + return detail::import_bits_fast(val, i, j, chunk_size); + } +#endif + return detail::import_bits_generic(val, i, j, chunk_size, msv_first); + } + + template + OutputIterator export_bits(const number, + ExpressionTemplates> &val, OutputIterator out, unsigned chunk_size, bool msv_first = true) { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4244) +#endif + typedef typename montgomery_int_backend::trivial_tag tag_type; + if (!val) { + *out = 0; + ++out; + return out; + } + unsigned bitcount = boost::multiprecision::backends::eval_msb_imp(val.backend()) + 1; + unsigned chunks = bitcount / chunk_size; + if (bitcount % chunk_size) { + ++chunks; + } + + int bit_location = msv_first ? bitcount - chunk_size : 0; + int bit_step = msv_first ? -static_cast(chunk_size) : chunk_size; + while (bit_location % bit_step) { + ++bit_location; + } + + do { + *out = detail::extract_bits(val.backend(), bit_location, chunk_size, tag_type()); + ++out; + bit_location += bit_step; + } while ((bit_location >= 0) && (bit_location < (int) bitcount)); + + return out; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } + + } +} + + +#endif // CRYPTO3_MP_MONTGOMERY_INT_IMPORT_EXPORT_HPP + diff --git a/include/boost/multiprecision/montgomery_int/inverse.hpp b/include/boost/multiprecision/montgomery_int/inverse.hpp new file mode 100644 index 000000000..e94c2f627 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/inverse.hpp @@ -0,0 +1,42 @@ +// +// Created by Zerg1996 on 2019-05-07. +// + +#ifndef CRYPTO3_INVERSE_H +#define CRYPTO3_INVERSE_H + +namespace nil { + namespace crypto3 { + limb_type monty_inverse(limb_type a) + { + const limb_type MP_WORD_MAX = ~static_cast(0); + + if(a % 2 == 0) + throw std::invalid_argument("monty_inverse only valid for odd integers"); + + /* + * From "A New Algorithm for Inversion mod p^k" by Çetin Kaya Koç + * https://eprint.iacr.org/2017/411.pdf sections 5 and 7. + */ + + limb_type b = 1; + limb_type r = 0; + + for(size_t i = 0; i != CRYPTO3_MP_WORD_BITS; ++i) + { + const limb_type bi = b % 2; + r >>= 1; + r += bi << (CRYPTO3_MP_WORD_BITS - 1); + + b -= a * bi; + b >>= 1; + } + + // Now invert in addition space + r = (MP_WORD_MAX - r) + 1; + + return r; + } + } +} +#endif //CRYPTO3_INVERSE_H diff --git a/include/boost/multiprecision/montgomery_int/limits.hpp b/include/boost/multiprecision/montgomery_int/limits.hpp new file mode 100644 index 000000000..c47c6de11 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/limits.hpp @@ -0,0 +1,375 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_LIM_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_LIM_HPP + +namespace std { + + namespace detail { + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4307) +#endif + + template + inline boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> get_min(const boost::mpl::true_ &, const boost::mpl::true_ &) { + // Bounded and signed. + typedef boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> result_type; + typedef boost::multiprecision::number, + ExpressionTemplates> ui_type; + static const result_type val = -result_type(~ui_type(0)); + return val; + } + + template + inline boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> get_min(const boost::mpl::true_ &, const boost::mpl::false_ &) { + // Bounded and unsigned: + static const boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> val(0u); + return val; + } + + template + inline boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> get_min(const boost::mpl::false_ &, const boost::mpl::true_ &) { + // Unbounded and signed. + // There is no minimum value, just return 0: + static const boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> val(0u); + return val; + } + + template + inline boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> get_min(const boost::mpl::false_ &, const boost::mpl::false_ &) { + // Unbound and unsigned: + static const boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> val(0u); + return val; + } + + template + inline boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> get_max(const boost::mpl::true_ &, const boost::mpl::true_ &) { + // Bounded and signed. + typedef boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> result_type; + typedef boost::multiprecision::number, + ExpressionTemplates> ui_type; + static const result_type val = ~ui_type(0); + return val; + } + + template + inline boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> get_max(const boost::mpl::true_ &, const boost::mpl::false_ &) { + // Bound and unsigned: + typedef boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> result_type; + typedef boost::multiprecision::number, + ExpressionTemplates> ui_type; + static const result_type val = ~ui_type(0); + return val; + } + + template + inline boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> get_max(const boost::mpl::false_ &, const boost::mpl::true_ &) { + // Unbounded and signed. + // There is no maximum value, just return 0: + static const boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> val(0u); + return val; + } + + template + inline boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> get_max(const boost::mpl::false_ &, const boost::mpl::false_ &) { + // Unbound and unsigned: + static const boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> val(0u); + return val; + } + + } + + template + class numeric_limits, + ExpressionTemplates> > { + typedef boost::multiprecision::montgomery_int_backend backend_type; + typedef boost::multiprecision::number number_type; + + struct inititializer { + inititializer() { + (std::numeric_limits::max)(); + (std::numeric_limits::min)(); + } + + void do_nothing() const { + } + }; + + static const inititializer init; + + public: + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + + // + // Largest and smallest numbers are bounded only by available memory, set + // to zero: + // + static number_type (min)() { + init.do_nothing(); + return detail::get_min( + boost::multiprecision::backends::is_fixed_precision(), + boost::multiprecision::is_signed_number()); + } + + static number_type (max)() { + init.do_nothing(); + return detail::get_max( + boost::multiprecision::backends::is_fixed_precision(), + boost::multiprecision::is_signed_number()); + } + + static number_type lowest() { + return (min)(); + } + + BOOST_STATIC_CONSTEXPR int digits = + boost::multiprecision::backends::max_precision::value == UINT_MAX ? INT_MAX + : boost::multiprecision::backends::max_precision< + backend_type>::value; + BOOST_STATIC_CONSTEXPR int digits10 = (digits > INT_MAX / 301) ? (digits / 1000) * 301L : (digits * 301) / 1000; + BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 3; + BOOST_STATIC_CONSTEXPR bool is_signed = boost::multiprecision::is_signed_number::value; + BOOST_STATIC_CONSTEXPR bool is_integer = true; + BOOST_STATIC_CONSTEXPR bool is_exact = true; + BOOST_STATIC_CONSTEXPR int radix = 2; + + static number_type epsilon() { + return 0; + } + + static number_type round_error() { + return 0; + } + + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + + static number_type infinity() { + return 0; + } + + static number_type quiet_NaN() { + return 0; + } + + static number_type signaling_NaN() { + return 0; + } + + static number_type denorm_min() { + return 0; + } + + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = boost::multiprecision::backends::is_fixed_precision< + backend_type>::value; + BOOST_STATIC_CONSTEXPR bool is_modulo = ( + boost::multiprecision::backends::is_fixed_precision::value && + (Checked == boost::multiprecision::unchecked)); + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; + }; + + template const typename numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::inititializer numeric_limits, + ExpressionTemplates> >::init; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + + template BOOST_CONSTEXPR_OR_CONST int numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::digits; + + template BOOST_CONSTEXPR_OR_CONST int numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::digits10; + + template BOOST_CONSTEXPR_OR_CONST int numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::max_digits10; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::is_signed; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::is_integer; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::is_exact; + + template BOOST_CONSTEXPR_OR_CONST int numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::radix; + + template BOOST_CONSTEXPR_OR_CONST int numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::min_exponent; + + template BOOST_CONSTEXPR_OR_CONST int numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::min_exponent10; + template BOOST_CONSTEXPR_OR_CONST int numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::max_exponent; + + template BOOST_CONSTEXPR_OR_CONST int numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::max_exponent10; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::has_infinity; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::has_quiet_NaN; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::has_signaling_NaN; + + template BOOST_CONSTEXPR_OR_CONST float_denorm_style + numeric_limits, + ExpressionTemplates> >::has_denorm; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::has_denorm_loss; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::is_iec559; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::is_bounded; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::is_modulo; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::traps; + + template BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number< + boost::multiprecision::montgomery_int_backend, + ExpressionTemplates> >::tinyness_before; + + template BOOST_CONSTEXPR_OR_CONST float_round_style + numeric_limits, + ExpressionTemplates> >::round_style; + +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +} // namespace std + +#endif diff --git a/include/boost/multiprecision/montgomery_int/literals.hpp b/include/boost/multiprecision/montgomery_int/literals.hpp new file mode 100644 index 000000000..479e775ee --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/literals.hpp @@ -0,0 +1,102 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_LITERALS_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_LITERALS_HPP + +#include +#include + +namespace boost { + namespace multiprecision { + + namespace literals { + namespace detail { + + template + struct signed_montgomery_int_literal_result_type { + static constexpr unsigned bits = Digits * 4; + typedef boost::multiprecision::backends::montgomery_int_backend backend_type; + typedef number number_type; + }; + + template + struct unsigned_montgomery_int_literal_result_type { + static constexpr unsigned bits = Digits * 4; + typedef boost::multiprecision::backends::montgomery_int_backend backend_type; + typedef number number_type; + }; + + } + + template + constexpr typename boost::multiprecision::literals::detail::signed_montgomery_int_literal_result_type< + (sizeof...(STR)) - 2>::number_type operator "" _cppi() { + typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str::type pt; + return boost::multiprecision::literals::detail::make_backend_from_pack::backend_type>::value; + } + + template + constexpr typename boost::multiprecision::literals::detail::unsigned_montgomery_int_literal_result_type< + (sizeof...(STR)) - 2>::number_type operator "" _cppui() { + typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str::type pt; + return boost::multiprecision::literals::detail::make_backend_from_pack::backend_type>::value; + } + +#define BOOST_MP_DEFINE_SIZED_MNT_INT_LITERAL(Bits)\ +template \ +constexpr boost::multiprecision::number > operator "" BOOST_JOIN(_cppi, Bits)()\ +{\ + typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str::type pt;\ + return boost::multiprecision::literals::detail::make_backend_from_pack<\ + pt, \ + boost::multiprecision::backends::montgomery_int_backend \ + >::value;\ +}\ +template \ +constexpr boost::multiprecision::number > operator "" BOOST_JOIN(_cppui, Bits)()\ +{\ + typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str::type pt;\ + return boost::multiprecision::literals::detail::make_backend_from_pack<\ + pt, \ + boost::multiprecision::backends::montgomery_int_backend\ + >::value;\ +}\ + + + BOOST_MP_DEFINE_SIZED_MNT_INT_LITERAL(128) + + BOOST_MP_DEFINE_SIZED_MNT_INT_LITERAL(256) + + BOOST_MP_DEFINE_SIZED_MNT_INT_LITERAL(512) + + BOOST_MP_DEFINE_SIZED_MNT_INT_LITERAL(1024) + + } + +// +// Overload unary minus operator for constexpr use: +// + template + constexpr number, et_off> operator-( + const number, et_off> &a) { + return montgomery_int_backend(a.backend(), + boost::multiprecision::literals::detail::make_negate_tag()); + } + + template + constexpr number, et_off> operator-( + number, et_off> &&a) { + return montgomery_int_backend( + static_cast, + et_off> &>(a).backend(), boost::multiprecision::literals::detail::make_negate_tag()); + } + + } +} // namespaces + +#endif // CRYPTO3_MP_MONTGOMERY_INT_CORE_HPP + diff --git a/include/boost/multiprecision/montgomery_int/misc.hpp b/include/boost/multiprecision/montgomery_int/misc.hpp new file mode 100644 index 000000000..825202a37 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/misc.hpp @@ -0,0 +1,683 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_MISC_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_MISC_HPP + +#include // lsb etc +#include // gcd/lcm +#include + + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4702) +#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned +#endif + + +namespace boost { + namespace multiprecision { + namespace backends { + + + template< + class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + inline typename enable_if_c::value && !is_trivial_montgomery_int< + montgomery_int_backend >::value, void> + + ::type eval_convert_to(R *result, const montgomery_int_backend &backend) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + typedef mpl::int_ checked_type; + check_in_range(backend, checked_type()); + + *result = static_cast(backend.limbs()[0]); + unsigned shift = montgomery_int_backend::limb_bits; + for (unsigned i = 1; (i < backend.size()) && (shift < static_cast(std::numeric_limits::digits)); ++i) { + *result += static_cast(backend.limbs()[i]) << shift; + shift += montgomery_int_backend::limb_bits; + } + if (backend.sign()) { + check_is_negative(boost::is_signed()); + + *result = negate_integer(*result, boost::is_signed()); + } + } + + template + inline typename enable_if_c::value && !is_trivial_montgomery_int< + montgomery_int_backend >::value, void> + + ::type eval_convert_to(R *result, const montgomery_int_backend &backend) + + BOOST_MP_NOEXCEPT_IF(is_arithmetic::value) { + typename montgomery_int_backend::const_limb_pointer p = backend.limbs(); + unsigned shift = montgomery_int_backend::limb_bits; + *result = static_cast(*p); + for (unsigned i = 1; i < backend.size(); ++i) { + *result += static_cast(std::ldexp(static_cast(p[i]), shift)); + shift += montgomery_int_backend::limb_bits; + } + if (backend.sign()) { + *result = -*result; + } + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool> + + ::type eval_is_zero(const montgomery_int_backend &val) BOOST_NOEXCEPT { + return (val.size() == 1) && (val.limbs()[0] == 0); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value, int> + + ::type eval_get_sign(const montgomery_int_backend &val) BOOST_NOEXCEPT { + return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1; + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_abs(montgomery_int_backend &result, + const montgomery_int_backend &val) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + result = val; + result.sign(false); + } + +// +// Get the location of the least-significant-bit: +// + template + inline typename enable_if_c >::value, unsigned> + + ::type eval_lsb(const montgomery_int_backend &a) { + using default_ops::eval_get_sign; + if (eval_get_sign(a) == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (a.sign()) { + BOOST_THROW_EXCEPTION(std::range_error( + "Testing individual bits in negative values is not supported - results are undefined.")); + } + + // + // Find the index of the least significant limb that is non-zero: + // + unsigned index = 0; + while (!a.limbs()[index] && (index < a.size())) { + ++index; + } + // + // Find the index of the least significant bit within that limb: + // + unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]); + + return result + + index * montgomery_int_backend::limb_bits; + } + +// +// Get the location of the most-significant-bit: +// + template + inline typename enable_if_c >::value, unsigned> + + ::type eval_msb_imp(const montgomery_int_backend &a) { + // + // Find the index of the most significant bit that is non-zero: + // + return (a.size() - 1) * + montgomery_int_backend::limb_bits + + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]); + } + + template + inline typename enable_if_c >::value, unsigned> + + ::type eval_msb(const montgomery_int_backend &a) { + using default_ops::eval_get_sign; + if (eval_get_sign(a) == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (a.sign()) { + BOOST_THROW_EXCEPTION(std::range_error( + "Testing individual bits in negative values is not supported - results are undefined.")); + } + return eval_msb_imp(a); + } + + template + inline typename enable_if_c >::value, bool> + + ::type eval_bit_test(const montgomery_int_backend &val, + unsigned index) BOOST_NOEXCEPT { + unsigned offset = + index / montgomery_int_backend::limb_bits; + unsigned shift = + index % montgomery_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if (offset >= val.size()) { + return false; + } + return val.limbs()[offset] & mask ? true : false; + } + + template + inline typename enable_if_c >::value> + + ::type eval_bit_set(montgomery_int_backend &val, + unsigned index) { + unsigned offset = + index / montgomery_int_backend::limb_bits; + unsigned shift = + index % montgomery_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if (offset >= val.size()) { + unsigned os = val.size(); + val.resize(offset + 1, offset + 1); + if (offset >= val.size()) { + return; + } // fixed precision overflow + for (unsigned i = os; i <= offset; ++i) { + val.limbs()[i] = 0; + } + } + val.limbs()[offset] |= mask; + } + + template + inline typename enable_if_c >::value> + + ::type eval_bit_unset(montgomery_int_backend &val, + unsigned index) BOOST_NOEXCEPT { + unsigned offset = + index / montgomery_int_backend::limb_bits; + unsigned shift = + index % montgomery_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if (offset >= val.size()) { + return; + } + val.limbs()[offset] &= ~mask; + val.normalize(); + } + + template + inline typename enable_if_c >::value> + + ::type eval_bit_flip(montgomery_int_backend &val, + unsigned index) { + unsigned offset = + index / montgomery_int_backend::limb_bits; + unsigned shift = + index % montgomery_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if (offset >= val.size()) { + unsigned os = val.size(); + val.resize(offset + 1, offset + 1); + if (offset >= val.size()) { + return; + } // fixed precision overflow + for (unsigned i = os; i <= offset; ++i) { + val.limbs()[i] = 0; + } + } + val.limbs()[offset] ^= mask; + val.normalize(); + } + + template + inline typename enable_if_c >::value> + + ::type eval_qr(const montgomery_int_backend &x, + const montgomery_int_backend &y, + montgomery_int_backend &q, + montgomery_int_backend &r) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + divide_unsigned_helper(&q, x, y, r); + q.sign(x.sign() != y.sign()); + r.sign(x.sign()); + } + + template + inline typename enable_if_c >::value> + + ::type eval_qr(const montgomery_int_backend &x, + limb_type y, montgomery_int_backend &q, + montgomery_int_backend &r) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + divide_unsigned_helper(&q, x, y, r); + q.sign(x.sign()); + r.sign(x.sign()); + } + + template + inline typename enable_if_c::value>::type eval_qr( + const montgomery_int_backend &x, U y, + montgomery_int_backend &q, + montgomery_int_backend &r) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + using default_ops::eval_qr; + montgomery_int_backend t; + t = y; + eval_qr(x, t, q, r); + } + + template + inline typename enable_if_c::value && !is_trivial_montgomery_int< + montgomery_int_backend >::value, Integer> + + ::type eval_integer_modulus( + const montgomery_int_backend &x, Integer val) { + if ((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits::max)())) { + montgomery_int_backend d; + divide_unsigned_helper(static_cast *>(0), x, static_cast(val), d); + return d.limbs()[0]; + } else { + return default_ops::eval_integer_modulus(x, val); + } + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c::value && !is_trivial_montgomery_int< + montgomery_int_backend >::value, Integer> + + ::type eval_integer_modulus( + const montgomery_int_backend &x, Integer val) { + return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val)); + } + + template + inline typename enable_if_c >::value> + + ::type eval_gcd(montgomery_int_backend &result, + const montgomery_int_backend &a, + limb_type v) { + using default_ops::eval_lsb; + using default_ops::eval_is_zero; + using default_ops::eval_get_sign; + + int shift; + + montgomery_int_backend u(a); + + int s = eval_get_sign(u); + + /* GCD(0,x) := x */ + if (s < 0) { + u.negate(); + } else if (s == 0) { + result = v; + return; + } + if (v == 0) { + result = u; + return; + } + + /* Let shift := lg K, where K is the greatest power of 2 + dividing both u and v. */ + + unsigned us = eval_lsb(u); + unsigned vs = boost::multiprecision::detail::find_lsb(v); + shift = (std::min)(us, vs); + eval_right_shift(u, us); + if (vs) { + v >>= vs; + } + + do { + /* Now u and v are both odd, so diff(u, v) is even. + Let u = min(u, v), v = diff(u, v)/2. */ + if (u.size() <= 2) { + if (u.size() == 1) { + v = integer_gcd_reduce(*u.limbs(), v); + } else { + double_limb_type i; + i = u.limbs()[0] | + (static_cast(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); + v = static_cast(integer_gcd_reduce(i, static_cast(v))); + } + break; + } + eval_subtract(u, v); + us = eval_lsb(u); + eval_right_shift(u, us); + } while (true); + + result = v; + eval_left_shift(result, shift); + } + + template + inline typename enable_if_c::value && (sizeof(Integer) <= sizeof(limb_type)) && + !is_trivial_montgomery_int< + montgomery_int_backend >::value> + + ::type eval_gcd(montgomery_int_backend &result, + const montgomery_int_backend &a, + const Integer &v) { + eval_gcd(result, a, static_cast(v)); + } + + template + inline typename enable_if_c::value && (sizeof(Integer) <= sizeof(limb_type)) && + !is_trivial_montgomery_int< + montgomery_int_backend >::value> + + ::type eval_gcd(montgomery_int_backend &result, + const montgomery_int_backend &a, + const Integer &v) { + eval_gcd(result, a, static_cast(v < 0 ? -v : v)); + } + + template + inline typename enable_if_c >::value> + + ::type eval_gcd(montgomery_int_backend &result, + const montgomery_int_backend &a, + const montgomery_int_backend &b) { + using default_ops::eval_lsb; + using default_ops::eval_is_zero; + using default_ops::eval_get_sign; + + if (a.size() == 1) { + eval_gcd(result, b, *a.limbs()); + return; + } + if (b.size() == 1) { + eval_gcd(result, a, *b.limbs()); + return; + } + + int shift; + + montgomery_int_backend u(a), v(b); + + int s = eval_get_sign(u); + + /* GCD(0,x) := x */ + if (s < 0) { + u.negate(); + } else if (s == 0) { + result = v; + return; + } + s = eval_get_sign(v); + if (s < 0) { + v.negate(); + } else if (s == 0) { + result = u; + return; + } + + /* Let shift := lg K, where K is the greatest power of 2 + dividing both u and v. */ + + unsigned us = eval_lsb(u); + unsigned vs = eval_lsb(v); + shift = (std::min)(us, vs); + eval_right_shift(u, us); + eval_right_shift(v, vs); + + do { + /* Now u and v are both odd, so diff(u, v) is even. + Let u = min(u, v), v = diff(u, v)/2. */ + s = u.compare(v); + if (s > 0) { + u.swap(v); + } + if (s == 0) { + break; + } + if (v.size() <= 2) { + if (v.size() == 1) { + u = integer_gcd_reduce(*v.limbs(), *u.limbs()); + } else { + double_limb_type i, j; + i = v.limbs()[0] | + (static_cast(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); + j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | + (static_cast(u.limbs()[1]) + << sizeof(limb_type) * CHAR_BIT); + u = integer_gcd_reduce(i, j); + } + break; + } + eval_subtract(v, u); + vs = eval_lsb(v); + eval_right_shift(v, vs); + } while (true); + + result = u; + eval_left_shift(result, shift); + } + +// +// Now again for trivial backends: +// + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_gcd(montgomery_int_backend &result, + const montgomery_int_backend &a, + const montgomery_int_backend &b) BOOST_NOEXCEPT { + *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs()); + } + +// This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version: + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + (Checked1 == unchecked)> + + ::type eval_lcm(montgomery_int_backend &result, + const montgomery_int_backend &a, + const montgomery_int_backend &b) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + *result. + + limbs() = boost::integer::lcm(*a.limbs(), *b.limbs()); + + result. + + normalize(); // result may overflow the specified number of bits + } + + template< + class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + inline typename enable_if_c >::value && + is_signed_number >::value && boost::is_convertible< + typename montgomery_int_backend::local_limb_type, R>::value> + + ::type eval_convert_to(R *result, const montgomery_int_backend &val) { + typedef typename common_type::local_limb_type>::type common_type; + if (std::numeric_limits::is_specialized && (static_cast(*val.limbs()) > + static_cast((std::numeric_limits< + R>::max)()))) { + if (val.isneg()) { + if (static_cast(*val.limbs()) > + -static_cast((std::numeric_limits::min)())) { + conversion_overflow(typename montgomery_int_backend::checked_type()); + } + *result = (std::numeric_limits::min)(); + } else { + conversion_overflow(typename montgomery_int_backend::checked_type()); + *result = (std::numeric_limits::max)(); + } + } else { + *result = static_cast(*val.limbs()); + if (val.isneg()) { + check_is_negative(mpl::bool_::value || + (number_category::value == number_kind_floating_point)>()); + *result = negate_integer(*result, mpl::bool_::value || + (number_category::value == + number_kind_floating_point)>()); + } + } + } + + template< + class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + inline typename enable_if_c >::value && + is_unsigned_number< + montgomery_int_backend >::value && boost::is_convertible< + typename montgomery_int_backend::local_limb_type, R>::value> + + ::type eval_convert_to(R *result, const montgomery_int_backend &val) { + typedef typename common_type::local_limb_type>::type common_type; + if (std::numeric_limits::is_specialized && (static_cast(*val.limbs()) > + static_cast((std::numeric_limits< + R>::max)()))) { + conversion_overflow(typename montgomery_int_backend::checked_type()); + *result = (std::numeric_limits::max)(); + } else { + *result = static_cast(*val.limbs()); + } + } + + template + inline typename enable_if_c >::value, unsigned> + + ::type eval_lsb(const montgomery_int_backend &a) { + using default_ops::eval_get_sign; + if (eval_get_sign(a) == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (a.sign()) { + BOOST_THROW_EXCEPTION(std::range_error( + "Testing individual bits in negative values is not supported - results are undefined.")); + } + // + // Find the index of the least significant bit within that limb: + // + return boost::multiprecision::detail::find_lsb(*a.limbs()); + } + + template + inline typename enable_if_c >::value, unsigned> + + ::type eval_msb_imp(const montgomery_int_backend &a) { + // + // Find the index of the least significant bit within that limb: + // + return boost::multiprecision::detail::find_msb(*a.limbs()); + } + + template + inline typename enable_if_c >::value, unsigned> + + ::type eval_msb(const montgomery_int_backend &a) { + using default_ops::eval_get_sign; + if (eval_get_sign(a) == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (a.sign()) { + BOOST_THROW_EXCEPTION(std::range_error( + "Testing individual bits in negative values is not supported - results are undefined.")); + } + return eval_msb_imp(a); + } + + template + inline std::size_t hash_value(const montgomery_int_backend &val) BOOST_NOEXCEPT { + std::size_t result = 0; + for (unsigned i = 0; i < val.size(); ++i) { + boost::hash_combine(result, val.limbs()[i]); + } + boost::hash_combine(result, val.sign()); + return result; + } + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + + } + } +} // namespaces + +#endif diff --git a/include/boost/multiprecision/montgomery_int/modular_reduce.hpp b/include/boost/multiprecision/montgomery_int/modular_reduce.hpp new file mode 100644 index 000000000..1e7b2bdac --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/modular_reduce.hpp @@ -0,0 +1,94 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_MOD_REDC_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_MOD_REDC_HPP + +//#include + +#include +#include + +namespace boost { + namespace multiprecision { + namespace backends { + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) // conditional expression is constant +#endif + + template + inline void mod_redc(Backend &result, const Backend &mod) BOOST_MP_NOEXCEPT_IF ( + is_non_throwing_cpp_int::value) { + + using default_ops::eval_lt; + using default_ops::eval_gt; + using default_ops::eval_add; + using default_ops::eval_multiply; + using default_ops::eval_bit_set; + using nil::crypto3::eval_mask_bits; + using nil::crypto3::eval_reduce_below; + + const size_t x_sw = result.size(); + + Backend mod2 = mod; + eval_add(mod2, mod); + + if (result.size() < mod.size() || eval_lt(result, mod)) { + if (eval_lt(result, 0)) { + eval_add(result, mod); + return; + } // make positive + return; + } else if (eval_lt(result, mod2)) { + //secure_vector ws; + Backend t1; + + eval_import_bits(t1, result.limbs() + mod.size() - 1, result.limbs() + x_sw); + { + Backend p2; + eval_bit_set(p2, 2 * Backend::limb_bits * mod.size()); + eval_divide(p2, mod); + eval_multiply(t1, p2); + } + eval_right_shift(t1, (Backend::limb_bits * (mod.size() + 1))); + + eval_multiply(t1, mod); + + eval_mask_bits(t1, Backend::limb_bits * (mod.size() + 1)); + + eval_subtract(t1, result, t1); + +// t1.rev_sub(result.data(), std::min(x_sw, mod.size() + 1), ws); + + if (eval_lt(t1, 0)) { + Backend p2; + eval_bit_set(p2, Backend::limb_bits * (mod.size() + 1)); + eval_add(t1, p2); + } + + eval_reduce_below(t1, mod); + + if (eval_lt(result, 0)) { + eval_subtract(t1, mod, t1); + } + + result = t1; + return; + } else { + // too big, fall back to normal division + Backend t2; + divide_unsigned_helper(&result, result, mod, t2); + result = t2; + return; + } + + } + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + } + } +} // namespaces + +#endif diff --git a/include/boost/multiprecision/montgomery_int/montgomery_int.hpp b/include/boost/multiprecision/montgomery_int/montgomery_int.hpp new file mode 100644 index 000000000..04d428495 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/montgomery_int.hpp @@ -0,0 +1,2473 @@ + +#ifndef CRYPTO3_MP_MONTGOMERY_INT_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_HPP + +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef BOOST_MP_USER_DEFINED_LITERALS + +#include + +#endif + +#include +#include + + +namespace boost { + namespace multiprecision { + namespace backends { + + using boost::enable_if; + + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4307) // integral constant overflow (oveflow is in a branch not taken when it would overflow) +#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable:4702) // Unreachable code (reachability depends on template params) +#endif + + template>::type, typename ParamsBackend = cpp_int > + struct montgomery_int_backend; + + } // namespace backends + + namespace detail { + + template + struct is_byte_container > + : public boost::false_type { + }; + + } // namespace detail + + namespace backends { + + template + struct montgomery_int_base; +// +// Traits class determines the maximum and minimum precision values: +// + template + struct max_precision; + + template + struct max_precision > { + static const unsigned value = is_void::value ? static_unsigned_max::value + : (((MaxBits >= MinBits) && MaxBits) ? MaxBits + : UINT_MAX); + }; + + template + struct min_precision; + + template + struct min_precision > { + static const unsigned value = (is_void::value ? static_unsigned_max::value + : MinBits); + }; +// +// Traits class determines whether the number of bits precision requested could fit in a native type, +// we call this a "trivial" cpp_int: +// + template + struct is_trivial_montgomery_int { + static const bool value = false; + }; + + template + struct is_trivial_montgomery_int > { + typedef montgomery_int_backend self; + static const bool value = is_void::value && (max_precision::value <= + (sizeof(double_limb_type) * CHAR_BIT) - + (SignType == signed_packed ? 1 : 0)); + }; + + template + struct is_trivial_montgomery_int< + montgomery_int_base > { + static const bool value = true; + }; + + template + struct is_trivial_montgomery_int > { + typedef cpp_int_backend self; + static const bool value = is_void::value && (max_precision::value <= + (sizeof(double_limb_type) * CHAR_BIT) - + (SignType == signed_packed ? 1 : 0)); + }; + + template + struct is_trivial_montgomery_int< + cpp_int_base > { + static const bool value = true; + }; + + + + } // namespace backends +// +// Traits class to determine whether a montgomery_int_backend is signed or not: +// + template + struct is_unsigned_number > + : public mpl::bool_<(SignType == unsigned_magnitude) || (SignType == unsigned_packed)> { + }; + + namespace backends { + template + struct is_non_throwing_montgomery_int : public mpl::false_{}; + template + struct is_non_throwing_montgomery_int > : public mpl::true_ {}; + + // +// Traits class determines whether T should be implicitly convertible to U, or +// whether the constructor should be made explicit. The latter happens if we +// are losing the sign, or have fewer digits precision in the target type: +// + template + struct is_equal_montgomery_int_backend { + constexpr static const bool value = false; + }; + + template + struct is_equal_montgomery_int_backend> { + constexpr static const bool value = true; + }; + + template + struct is_equal_montgomery_int_backend> { + constexpr static const bool value = true; + }; + + template + struct is_equal_montgomery_int_field { + constexpr static const bool value = false; + }; + + template + struct is_equal_montgomery_int_field> { + constexpr static const bool value = true; + }; + + + template + struct is_implicit_cpp_int_conversion { + constexpr static const bool value = (is_signed_number::value || !is_signed_number::value) && + (!std::is_constructible, T>::value && !std::is_constructible, U>::value) && + (!std::is_constructible, T>::value && !std::is_constructible, U>::value); + }; + + template + struct is_implicit_cpp_int_conversion< + montgomery_int_backend, + montgomery_int_backend > { + typedef montgomery_int_backend t1; + typedef montgomery_int_backend t2; + static const bool value = (is_signed_number::value || !is_signed_number::value) && + (max_precision::value <= max_precision::value); + }; + +// +// Traits class to determine whether operations on a cpp_int may throw: +// + /* + template + struct is_non_throwing_cpp_int : public mpl::false_ { + }; + template + struct is_non_throwing_cpp_int > + : public mpl::true_ { + }; + */ +// +// Traits class, determines whether the cpp_int is fixed precision or not: +// + template + struct is_fixed_precision; + template + struct is_fixed_precision > + : public mpl::bool_ >::value != + UINT_MAX> { + }; + + + namespace detail { + + //inline void verify_new_size(unsigned new_size, unsigned min_size, const mpl::int_ &) { + // if (new_size < min_size) + // BOOST_THROW_EXCEPTION(std::overflow_error( + // "Unable to allocate sufficient storage for the value of the result: value overflows the maximum allowable magnitude.")); + //} + + //inline void verify_new_size(unsigned /*new_size*/, unsigned /*min_size*/, + // const mpl::int_ &) { + //} + + //template + //inline void verify_limb_mask(bool b, U limb, U mask, const mpl::int_ &) { + // // When we mask out "limb" with "mask", do we loose bits? If so it's an overflow error: + // if (b && (limb & ~mask)) + // BOOST_THROW_EXCEPTION(std::overflow_error( + // "Overflow in cpp_int arithmetic: there is insufficient precision in the target type to hold all of the bits of the result.")); + //} + + //template + //inline void verify_limb_mask(bool /*b*/, U /*limb*/, U /*mask*/, const mpl::int_ &) { + //} + + } + + +// +// Now define the various data layouts that are possible as partial specializations of the base class, +// starting with the default arbitrary precision signed integer type: +// + template + struct montgomery_int_base + : private Allocator::template rebind::other { + typedef typename Allocator::template rebind::other allocator_type; + typedef typename allocator_type::pointer limb_pointer; + typedef typename allocator_type::const_pointer const_limb_pointer; + typedef mpl::int_ checked_type; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT(!is_void::value); + + private: + struct limb_data { + unsigned capacity; + limb_pointer data; + }; + + public: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast(0u)); + BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast(1u) << (limb_bits - 1)); + BOOST_STATIC_CONSTANT(unsigned, + internal_limb_count = MinBits ? (MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0)) : ( + sizeof(limb_data) / sizeof(limb_type))); + BOOST_STATIC_CONSTANT(bool, variable = true); + + private: + union data_type { + limb_data ld; + limb_type la[internal_limb_count]; + limb_type first; + double_limb_type double_first; + + BOOST_CONSTEXPR data_type() : first(0) { + } + + BOOST_CONSTEXPR data_type(limb_type i) : first(i) { + } + + BOOST_CONSTEXPR data_type(signed_limb_type i) : first( + i < 0 ? static_cast(boost::multiprecision::detail::unsigned_abs(i)) : i) { + } + +#ifdef BOOST_LITTLE_ENDIAN + + BOOST_CONSTEXPR data_type(double_limb_type i) : double_first(i) { + } + + BOOST_CONSTEXPR data_type(signed_double_limb_type i) : double_first( + i < 0 ? static_cast(boost::multiprecision::detail::unsigned_abs(i)) : i) { + } + +#endif + }; + + data_type m_data; + unsigned m_limbs; + bool m_sign, m_internal; + public: + // + // Direct construction: + // + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(limb_type i) BOOST_NOEXCEPT + : m_data(i), m_limbs(1), m_sign(false), m_internal(true) { + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(signed_limb_type i) BOOST_NOEXCEPT + : m_data(i), m_limbs(1), m_sign(i < 0), m_internal(true) { + } + +#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE) + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(double_limb_type i) BOOST_NOEXCEPT + : m_data(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false), m_internal(true) { + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(signed_double_limb_type i) BOOST_NOEXCEPT + : m_data(i), + m_limbs(i < 0 ? (static_cast(boost::multiprecision::detail::unsigned_abs(i)) > + static_cast(max_limb_value) ? 2 : 1) : (i > max_limb_value + ? 2 : 1)), + m_sign(i < 0), m_internal(true) { + } + +#endif + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_MP_FORCEINLINE allocator_type &allocator() BOOST_NOEXCEPT { + return *this; + } + + BOOST_MP_FORCEINLINE const allocator_type &allocator() const BOOST_NOEXCEPT { + return *this; + } + + BOOST_MP_FORCEINLINE unsigned size() const BOOST_NOEXCEPT { + return m_limbs; + } + + BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { + return m_internal ? m_data.la : m_data.ld.data; + } + + BOOST_MP_FORCEINLINE const_limb_pointer limbs() const BOOST_NOEXCEPT { + return m_internal ? m_data.la : m_data.ld.data; + } + + BOOST_MP_FORCEINLINE unsigned capacity() const BOOST_NOEXCEPT { + return m_internal ? internal_limb_count : m_data.ld.capacity; + } + + BOOST_MP_FORCEINLINE bool sign() const BOOST_NOEXCEPT { + return m_sign; + } + + void sign(bool b) BOOST_NOEXCEPT { + m_sign = b; + // Check for zero value: + if (m_sign && (m_limbs == 1)) { + if (limbs()[0] == 0) { + m_sign = false; + } + } + } + + void resize(unsigned new_size, unsigned min_size) { + static const unsigned max_limbs = MaxBits / (CHAR_BIT * sizeof(limb_type)) + + ((MaxBits % (CHAR_BIT * sizeof(limb_type))) ? 1 : 0); + // We never resize beyond MaxSize: + if (new_size > max_limbs) { + new_size = max_limbs; + } + detail::verify_new_size(new_size, min_size, checked_type()); + // See if we have enough capacity already: + unsigned cap = capacity(); + if (new_size > cap) { + // Allocate a new buffer and copy everything over: + cap = (std::min)((std::max)(cap * 4, new_size), max_limbs); + limb_pointer pl = allocator().allocate(cap); + std::memcpy(pl, limbs(), size() * sizeof(limbs()[0])); + if (!m_internal) { + allocator().deallocate(limbs(), capacity()); + } else { + m_internal = false; + } + m_limbs = new_size; + m_data.ld.capacity = cap; + m_data.ld.data = pl; + } else { + m_limbs = new_size; + } + } + + BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT { + limb_pointer p = limbs(); + while ((m_limbs - 1) && !p[m_limbs - 1]) { + --m_limbs; + } + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base() BOOST_NOEXCEPT + : m_data(), m_limbs(1), m_sign(false), m_internal(true) { + } + + BOOST_MP_FORCEINLINE montgomery_int_base(const montgomery_int_base &o) : allocator_type(o), m_limbs(0), + m_internal(true) { + resize(o.size(), o.size()); + std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0])); + m_sign = o.m_sign; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + montgomery_int_base(montgomery_int_base &&o) : allocator_type(static_cast(o)), + m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal) { + if (m_internal) { + std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0])); + } else { + m_data.ld = o.m_data.ld; + o.m_limbs = 0; + o.m_internal = true; + } + } + + montgomery_int_base &operator=(montgomery_int_base &&o) BOOST_NOEXCEPT { + if (!m_internal) { + allocator().deallocate(m_data.ld.data, m_data.ld.capacity); + } + *static_cast(this) = static_cast(o); + m_limbs = o.m_limbs; + m_sign = o.m_sign; + m_internal = o.m_internal; + if (m_internal) { + std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0])); + } else { + m_data.ld = o.m_data.ld; + o.m_limbs = 0; + o.m_internal = true; + } + return *this; + } + +#endif + + BOOST_MP_FORCEINLINE ~montgomery_int_base() BOOST_NOEXCEPT { + if (!m_internal) { + allocator().deallocate(limbs(), capacity()); + } + } + + void assign(const montgomery_int_base &o) { + if (this != &o) { + static_cast(*this) = static_cast(o); + m_limbs = 0; + resize(o.size(), o.size()); + std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0])); + m_sign = o.m_sign; + } + } + + BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT { + m_sign = !m_sign; + // Check for zero value: + if (m_sign && (m_limbs == 1)) { + if (limbs()[0] == 0) { + m_sign = false; + } + } + } + + BOOST_MP_FORCEINLINE bool isneg() const BOOST_NOEXCEPT { + return m_sign; + } + + BOOST_MP_FORCEINLINE void do_swap(montgomery_int_base &o) BOOST_NOEXCEPT { + std::swap(m_data, o.m_data); + std::swap(m_sign, o.m_sign); + std::swap(m_internal, o.m_internal); + std::swap(m_limbs, o.m_limbs); + } + + protected: + template + void check_in_range(const A &) BOOST_NOEXCEPT { + } + }; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + + template const unsigned montgomery_int_base::limb_bits; + template const limb_type montgomery_int_base::max_limb_value; + template const limb_type montgomery_int_base::sign_bit_mask; + template const unsigned montgomery_int_base::internal_limb_count; + template const bool montgomery_int_base::variable; + +#endif + + template + struct montgomery_int_base + : private Allocator::template rebind::other { + // + // There is currently no support for unsigned arbitrary precision arithmetic, largely + // because it's not clear what subtraction should do: + // + BOOST_STATIC_ASSERT_MSG(((sizeof(Allocator) == 0) && !is_void::value), + "There is curently no support for unsigned arbitrary precision integers."); + }; + +// +// Fixed precision (i.e. no allocator), signed-magnitude type with limb-usage count: +// + template + struct montgomery_int_base { + typedef limb_type *limb_pointer; + typedef const limb_type *const_limb_pointer; + typedef mpl::int_ checked_type; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT_MSG(MinBits > sizeof(double_limb_type) * CHAR_BIT, + "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); + + public: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast(0u)); + BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast(1u) << (limb_bits - 1)); + BOOST_STATIC_CONSTANT(unsigned, + internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0)); + BOOST_STATIC_CONSTANT(bool, variable = false); + BOOST_STATIC_CONSTANT(limb_type, + upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) - 1 + : (~limb_type(0))); + BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, + "A fixed precision integer type must have at least 2 limbs"); + + private: + union data_type { + limb_type m_data[internal_limb_count]; + limb_type m_first_limb; + double_limb_type m_double_first_limb; + + BOOST_CONSTEXPR data_type() : m_first_limb(0) { + } + + BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) { + } + + BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) { + } + +#if defined(BOOST_MP_USER_DEFINED_LITERALS) + + template + BOOST_CONSTEXPR data_type(literals::detail::value_pack) : m_data{VALUES...} { + } + +#endif + } m_wrapper; + + boost::uint16_t m_limbs; + bool m_sign; + + public: + // + // Direct construction: + // + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(limb_type i) BOOST_NOEXCEPT + : m_wrapper(i), m_limbs(1), m_sign(false) { + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(signed_limb_type i) BOOST_NOEXCEPT + : m_wrapper( + limb_type(i < 0 ? static_cast(-static_cast(i)) : i)), + m_limbs(1), m_sign(i < 0) { + } + +#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE) + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(double_limb_type i) BOOST_NOEXCEPT + : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false) { + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(signed_double_limb_type i) BOOST_NOEXCEPT + : m_wrapper(double_limb_type( + i < 0 ? static_cast(boost::multiprecision::detail::unsigned_abs(i)) : i)), + m_limbs(i < 0 ? (static_cast(boost::multiprecision::detail::unsigned_abs(i)) > + max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)), m_sign(i < 0) { + } + +#endif +#if defined(BOOST_MP_USER_DEFINED_LITERALS) + + template + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack i) + : m_wrapper(i), m_limbs(sizeof...(VALUES)), m_sign(false) { + } + + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack<> i) : m_wrapper(i), m_limbs(1), + m_sign(false) { + } + + BOOST_CONSTEXPR montgomery_int_base(const montgomery_int_base &a, const literals::detail::negate_tag &) + : m_wrapper(a.m_wrapper), m_limbs(a.m_limbs), + m_sign((a.m_limbs == 1) && (*a.limbs() == 0) ? false : !a.m_sign) { + } + +#endif + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_MP_FORCEINLINE unsigned size() const BOOST_NOEXCEPT { + return m_limbs; + } + + BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { + return m_wrapper.m_data; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs() const BOOST_NOEXCEPT { + return m_wrapper.m_data; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign() const BOOST_NOEXCEPT { + return m_sign; + } + + BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT { + m_sign = b; + // Check for zero value: + if (m_sign && (m_limbs == 1)) { + if (limbs()[0] == 0) { + m_sign = false; + } + } + } + + BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_MP_NOEXCEPT_IF( + (Checked == unchecked)) { + m_limbs = static_cast((std::min)(new_size, internal_limb_count)); + detail::verify_new_size(m_limbs, min_size, checked_type()); + } + + BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) { + limb_pointer p = limbs(); + detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count - 1], + upper_limb_mask, checked_type()); + p[internal_limb_count - 1] &= upper_limb_mask; + while ((m_limbs - 1) && !p[m_limbs - 1]) { + --m_limbs; + } + if ((m_limbs == 1) && (!*p)) { + m_sign = false; + } // zero is always unsigned + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base() BOOST_NOEXCEPT : m_wrapper(limb_type(0u)), + m_limbs(1), m_sign(false) { + } + // Not defaulted, it breaks constexpr support in the Intel compiler for some reason: + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(const montgomery_int_base &o) BOOST_NOEXCEPT + : m_wrapper(o.m_wrapper), m_limbs(o.m_limbs), m_sign(o.m_sign) { + } + // Defaulted functions: + //~montgomery_int_base() BOOST_NOEXCEPT {} + + void assign(const montgomery_int_base &o) BOOST_NOEXCEPT { + if (this != &o) { + m_limbs = o.m_limbs; + std::memcpy(limbs(), o.limbs(), o.size() * sizeof(o.limbs()[0])); + m_sign = o.m_sign; + } + } + + BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT { + m_sign = !m_sign; + // Check for zero value: + if (m_sign && (m_limbs == 1)) { + if (limbs()[0] == 0) { + m_sign = false; + } + } + } + + BOOST_MP_FORCEINLINE bool isneg() const BOOST_NOEXCEPT { + return m_sign; + } + + BOOST_MP_FORCEINLINE void do_swap(montgomery_int_base &o) BOOST_NOEXCEPT { + for (unsigned i = 0; i < (std::max)(size(), o.size()); ++i) { + std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]); + } + std::swap(m_sign, o.m_sign); + std::swap(m_limbs, o.m_limbs); + } + + protected: + template + void check_in_range(const A &) BOOST_NOEXCEPT { + } + }; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + + template const unsigned montgomery_int_base::limb_bits; + template const limb_type montgomery_int_base::max_limb_value; + template const limb_type montgomery_int_base::sign_bit_mask; + template const unsigned montgomery_int_base::internal_limb_count; + template const bool montgomery_int_base::variable; + +#endif + +// +// Fixed precision (i.e. no allocator), unsigned type with limb-usage count: +// + template + struct montgomery_int_base { + typedef limb_type *limb_pointer; + typedef const limb_type *const_limb_pointer; + typedef mpl::int_ checked_type; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT_MSG(MinBits > sizeof(double_limb_type) * CHAR_BIT, + "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); + + public: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast(0u)); + BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast(1u) << (limb_bits - 1)); + BOOST_STATIC_CONSTANT(unsigned, + internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0)); + BOOST_STATIC_CONSTANT(bool, variable = false); + BOOST_STATIC_CONSTANT(limb_type, + upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) - 1 + : (~limb_type(0))); + BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, + "A fixed precision integer type must have at least 2 limbs"); + + private: + union data_type { + limb_type m_data[internal_limb_count]; + limb_type m_first_limb; + double_limb_type m_double_first_limb; + + BOOST_CONSTEXPR data_type() : m_first_limb(0) { + } + + BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) { + } + + BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) { + } + +#if defined(BOOST_MP_USER_DEFINED_LITERALS) + + template + BOOST_CONSTEXPR data_type(literals::detail::value_pack) : m_data{VALUES...} { + } + +#endif + } m_wrapper; + + limb_type m_limbs; + + public: + // + // Direct construction: + // + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(limb_type i) BOOST_NOEXCEPT + : m_wrapper(i), m_limbs(1) { + } + + BOOST_MP_FORCEINLINE montgomery_int_base(signed_limb_type i) BOOST_MP_NOEXCEPT_IF( + (Checked == unchecked)) + : m_wrapper( + limb_type(i < 0 ? static_cast(-static_cast(i)) : i)), + m_limbs(1) { + if (i < 0) { + negate(); + } + } + +#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE) + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(double_limb_type i) BOOST_NOEXCEPT + : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1) { + } + + BOOST_MP_FORCEINLINE montgomery_int_base(signed_double_limb_type i) BOOST_MP_NOEXCEPT_IF( + (Checked == unchecked)) + : m_wrapper(double_limb_type( + i < 0 ? static_cast(boost::multiprecision::detail::unsigned_abs(i)) : i)), + m_limbs(i < 0 ? (static_cast(boost::multiprecision::detail::unsigned_abs(i)) > + max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)) { + if (i < 0) { + negate(); + } + } + +#endif +#if defined(BOOST_MP_USER_DEFINED_LITERALS) + + template + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack i) + : m_wrapper(i), m_limbs(sizeof...(VALUES)) { + } + + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack<>) : m_wrapper( + static_cast(0u)), m_limbs(1) { + } + +#endif + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_MP_FORCEINLINE unsigned size() const BOOST_NOEXCEPT { + return m_limbs; + } + + BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { + return m_wrapper.m_data; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs() const BOOST_NOEXCEPT { + return m_wrapper.m_data; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign() const BOOST_NOEXCEPT { + return false; + } + + BOOST_MP_FORCEINLINE void sign(bool b) BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) { + if (b) { + negate(); + } + } + + BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_MP_NOEXCEPT_IF( + (Checked == unchecked)) { + m_limbs = (std::min)(new_size, internal_limb_count); + detail::verify_new_size(m_limbs, min_size, checked_type()); + } + + BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) { + limb_pointer p = limbs(); + detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count - 1], + upper_limb_mask, checked_type()); + p[internal_limb_count - 1] &= upper_limb_mask; + while ((m_limbs - 1) && !p[m_limbs - 1]) { + --m_limbs; + } + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base() BOOST_NOEXCEPT + : m_wrapper(limb_type(0u)), m_limbs(1) { + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(const montgomery_int_base &o) BOOST_NOEXCEPT + : m_wrapper(o.m_wrapper), m_limbs(o.m_limbs) { + } + // Defaulted functions: + //~montgomery_int_base() BOOST_NOEXCEPT {} + + BOOST_MP_FORCEINLINE void assign(const montgomery_int_base &o) BOOST_NOEXCEPT { + if (this != &o) { + m_limbs = o.m_limbs; + std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0])); + } + } + + private: + void check_negate(const mpl::int_ &) { + BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned number.")); + } + + void check_negate(const mpl::int_ &) { + } + + public: + void negate() BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) { + // Not so much a negate as a complement - this gets called when subtraction + // would result in a "negative" number: + unsigned i; + if ((m_limbs == 1) && (m_wrapper.m_data[0] == 0)) { + return; + } // negating zero is always zero, and always OK. + check_negate(checked_type()); + for (i = m_limbs; i < internal_limb_count; ++i) { + m_wrapper.m_data[i] = 0; + } + m_limbs = internal_limb_count; + for (i = 0; i < internal_limb_count; ++i) { + m_wrapper.m_data[i] = ~m_wrapper.m_data[i]; + } + normalize(); + eval_increment(static_cast & >(*this)); + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg() const BOOST_NOEXCEPT { + return false; + } + + BOOST_MP_FORCEINLINE void do_swap(montgomery_int_base &o) BOOST_NOEXCEPT { + for (unsigned i = 0; i < (std::max)(size(), o.size()); ++i) { + std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]); + } + std::swap(m_limbs, o.m_limbs); + } + + protected: + template + void check_in_range(const A &) BOOST_NOEXCEPT { + } + }; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + + template const unsigned montgomery_int_base::limb_bits; + template const limb_type montgomery_int_base::max_limb_value; + template const limb_type montgomery_int_base::sign_bit_mask; + template const unsigned montgomery_int_base::internal_limb_count; + template const bool montgomery_int_base::variable; + +#endif +// +// Traits classes to figure out a native type with N bits, these vary from boost::uint_t only +// because some platforms have native integer types longer than boost::long_long_type, "really boost::long_long_type" anyone?? +// + /* + template + struct trivial_limb_type_imp { + typedef double_limb_type type; + }; + + template + struct trivial_limb_type_imp { + typedef typename boost::uint_t::least type; + }; + + template + struct trivial_limb_type : public trivial_limb_type_imp { + }; + */ + +// +// Backend for fixed precision signed-magnitude type which will fit entirely inside a "double_limb_type": +// + template + struct montgomery_int_base { + typedef typename trivial_limb_type::type local_limb_type; + typedef local_limb_type *limb_pointer; + typedef const local_limb_type *const_limb_pointer; + typedef mpl::int_ checked_type; + protected: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = (MinBits < limb_bits) ? local_limb_type( + (local_limb_type(~local_limb_type(0))) >> (limb_bits - MinBits)) : local_limb_type( + ~local_limb_type(0))); + private: + local_limb_type m_data; + bool m_sign; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT_MSG(MinBits <= sizeof(double_limb_type) * CHAR_BIT, + "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); + protected: + template + typename boost::disable_if_c::value || (std::numeric_limits::is_specialized && + (std::numeric_limits::digits <= + (int) MinBits))>::type check_in_range( + T val, const mpl::int_ &) { + typedef typename common_type::type, local_limb_type>::type common_type; + + if (static_cast(boost::multiprecision::detail::unsigned_abs(val)) > + static_cast(limb_mask)) + BOOST_THROW_EXCEPTION(std::range_error( + "The argument to a cpp_int constructor exceeded the largest value it can represent.")); + } + + template + typename boost::disable_if_c::value || (std::numeric_limits::is_specialized && + (std::numeric_limits::digits <= + (int) MinBits))>::type check_in_range( + T val, const mpl::int_ &) { + using std::abs; + typedef typename common_type::type common_type; + + if (static_cast(abs(val)) > static_cast(limb_mask)) + BOOST_THROW_EXCEPTION(std::range_error( + "The argument to a cpp_int constructor exceeded the largest value it can represent.")); + } + + template + void check_in_range(T, const mpl::int_ &) BOOST_NOEXCEPT { + } + + template + void check_in_range(T val) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().check_in_range(std::declval(), + checked_type()))) { + check_in_range(val, checked_type()); + } + + public: + // + // Direct construction: + // + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(SI i, typename boost::enable_if_c< + is_signed::value && (Checked == unchecked)>::type const * = 0) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().check_in_range(std::declval()))) + : m_data(i < 0 ? static_cast( + static_cast::type>(boost::multiprecision::detail::unsigned_abs(i)) & + limb_mask) : static_cast(i & limb_mask)), m_sign(i < 0) { + } + + template + BOOST_MP_FORCEINLINE montgomery_int_base(SI i, typename boost::enable_if_c< + is_signed::value && (Checked == checked)>::type const * = 0) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().check_in_range(std::declval()))) + : m_data(i < 0 ? (static_cast( + static_cast::type>(boost::multiprecision::detail::unsigned_abs(i)) & + limb_mask)) : static_cast(i & limb_mask)), m_sign(i < 0) { + check_in_range(i); + } + + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(UI i, typename boost::enable_if_c< + is_unsigned::value && (Checked == unchecked)>::type const * = 0) BOOST_NOEXCEPT + : m_data(static_cast(i) & limb_mask), m_sign(false) { + } + + template + BOOST_MP_FORCEINLINE montgomery_int_base(UI i, typename boost::enable_if_c< + is_unsigned::value && (Checked == checked)>::type const * = 0) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().check_in_range(std::declval()))) + : m_data(static_cast(i) & limb_mask), m_sign(false) { + check_in_range(i); + } + + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(F i, typename boost::enable_if_c< + is_floating_point::value && (Checked == unchecked)>::type const * = 0) BOOST_NOEXCEPT + : m_data(static_cast(std::fabs(i)) & limb_mask), m_sign(i < 0) { + } + + template + BOOST_MP_FORCEINLINE montgomery_int_base(F i, typename boost::enable_if_c< + is_floating_point::value && (Checked == checked)>::type const * = 0) + : m_data(static_cast(std::fabs(i)) & limb_mask), m_sign(i < 0) { + check_in_range(i); + } + +#if defined(BOOST_MP_USER_DEFINED_LITERALS) + + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack<>) BOOST_NOEXCEPT + : m_data(static_cast(0u)), m_sign(false) { + } + + template + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack) BOOST_NOEXCEPT + : m_data(static_cast(a)), m_sign(false) { + } + + template + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack) BOOST_NOEXCEPT + : m_data(static_cast(a) | (static_cast(b) << bits_per_limb)), + m_sign(false) { + } + + BOOST_CONSTEXPR montgomery_int_base(const montgomery_int_base &a, + const literals::detail::negate_tag &) BOOST_NOEXCEPT + : m_data(a.m_data), m_sign(a.m_data ? !a.m_sign : false) { + } + +#endif + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned size() const BOOST_NOEXCEPT { + return 1; + } + + BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { + return &m_data; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs() const BOOST_NOEXCEPT { + return &m_data; + } + + BOOST_MP_FORCEINLINE bool sign() const BOOST_NOEXCEPT { + return m_sign; + } + + BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT { + m_sign = b; + // Check for zero value: + if (m_sign && !m_data) { + m_sign = false; + } + } + + BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) { + detail::verify_new_size(2, min_size, checked_type()); + } + + BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) { + if (!m_data) { + m_sign = false; + } // zero is always unsigned + detail::verify_limb_mask(true, m_data, limb_mask, checked_type()); + m_data &= limb_mask; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base() BOOST_NOEXCEPT : m_data(0), m_sign(false) { + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(const montgomery_int_base &o) BOOST_NOEXCEPT + : m_data(o.m_data), m_sign(o.m_sign) { + } + //~montgomery_int_base() BOOST_NOEXCEPT {} + BOOST_MP_FORCEINLINE void assign(const montgomery_int_base &o) BOOST_NOEXCEPT { + m_data = o.m_data; + m_sign = o.m_sign; + } + + BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT { + m_sign = !m_sign; + // Check for zero value: + if (m_data == 0) { + m_sign = false; + } + } + + BOOST_MP_FORCEINLINE bool isneg() const BOOST_NOEXCEPT { + return m_sign; + } + + BOOST_MP_FORCEINLINE void do_swap(montgomery_int_base &o) BOOST_NOEXCEPT { + std::swap(m_sign, o.m_sign); + std::swap(m_data, o.m_data); + } + }; + +// +// Backend for unsigned fixed precision (i.e. no allocator) type which will fit entirely inside a "double_limb_type": +// + template + struct montgomery_int_base { + typedef typename trivial_limb_type::type local_limb_type; + typedef local_limb_type *limb_pointer; + typedef const local_limb_type *const_limb_pointer; + private: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = limb_bits != MinBits ? static_cast( + static_cast(~local_limb_type(0)) >> (limb_bits - MinBits)) + : static_cast(~local_limb_type( + 0))); + + local_limb_type m_data; + + typedef mpl::int_ checked_type; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT_MSG(MinBits <= sizeof(double_limb_type) * CHAR_BIT, + "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); + protected: + template + typename boost::disable_if_c::is_specialized && + (std::numeric_limits::digits <= (int) MinBits)>::type check_in_range( + T val, const mpl::int_ &, const boost::false_type &) { + typedef typename common_type::type common_type; + + if (static_cast(val) > limb_mask) + BOOST_THROW_EXCEPTION(std::range_error( + "The argument to a cpp_int constructor exceeded the largest value it can represent.")); + } + + template + void check_in_range(T val, const mpl::int_ &, const boost::true_type &) { + typedef typename common_type::type common_type; + + if (static_cast(val) > limb_mask) + BOOST_THROW_EXCEPTION(std::range_error( + "The argument to a cpp_int constructor exceeded the largest value it can represent.")); + if (val < 0) + BOOST_THROW_EXCEPTION( + std::range_error("The argument to an unsigned cpp_int constructor was negative.")); + } + + template + BOOST_MP_FORCEINLINE void check_in_range(T, const mpl::int_ &, + const boost::integral_constant &) BOOST_NOEXCEPT { + } + + template + BOOST_MP_FORCEINLINE void check_in_range(T val) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().check_in_range(std::declval(), checked_type(), + is_signed()))) { + check_in_range(val, checked_type(), is_signed()); + } + + public: + // + // Direct construction: + // +#ifdef __MSVC_RUNTIME_CHECKS + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(SI i, typename boost::enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT + : m_data(i < 0 ? (1 + ~static_cast(-i & limb_mask)) & limb_mask : static_cast(i & limb_mask)) {} + template + BOOST_MP_FORCEINLINE montgomery_int_base(SI i, typename boost::enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval().check_in_range(std::declval()))) + : m_data(i < 0 ? 1 + ~static_cast(-i & limb_mask) : static_cast(i & limb_mask)) { check_in_range(i); } + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(UI i, typename boost::enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT + : m_data(static_cast(i & limb_mask)) {} + template + BOOST_MP_FORCEINLINE montgomery_int_base(UI i, typename boost::enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval().check_in_range(std::declval()))) + : m_data(static_cast(i & limb_mask)) { check_in_range(i); } +#else + + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(SI i, typename boost::enable_if_c< + is_signed::value && (Checked == unchecked)>::type const * = 0) BOOST_NOEXCEPT + : m_data( + i < 0 ? (1 + ~static_cast(-i)) & limb_mask : static_cast(i) & + limb_mask) { + } + + template + BOOST_MP_FORCEINLINE montgomery_int_base(SI i, typename boost::enable_if_c< + is_signed::value && (Checked == checked)>::type const * = 0) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().check_in_range(std::declval()))) + : m_data(i < 0 ? 1 + ~static_cast(-i) : static_cast(i)) { + check_in_range(i); + } + + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(UI i, typename boost::enable_if_c< + is_unsigned::value && (Checked == unchecked)>::type const * = 0) BOOST_NOEXCEPT + : m_data(static_cast(i) & limb_mask) { + } + + template + BOOST_MP_FORCEINLINE montgomery_int_base(UI i, typename boost::enable_if_c< + is_unsigned::value && (Checked == checked)>::type const * = 0) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().check_in_range(std::declval()))) + : m_data(static_cast(i)) { + check_in_range(i); + } + +#endif + + template + BOOST_MP_FORCEINLINE montgomery_int_base(F i, typename boost::enable_if< + is_floating_point >::type const * = 0) BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) + : m_data(static_cast(std::fabs(i)) & limb_mask) { + check_in_range(i); + if (i < 0) { + negate(); + } + } + +#if defined(BOOST_MP_USER_DEFINED_LITERALS) + + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack<>) BOOST_NOEXCEPT + : m_data(static_cast(0u)) { + } + + template + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack) BOOST_NOEXCEPT + : m_data(static_cast(a)) { + } + + template + BOOST_CONSTEXPR montgomery_int_base(literals::detail::value_pack) BOOST_NOEXCEPT + : m_data(static_cast(a) | (static_cast(b) << bits_per_limb)) { + } + +#endif + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned size() const BOOST_NOEXCEPT { + return 1; + } + + BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { + return &m_data; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs() const BOOST_NOEXCEPT { + return &m_data; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign() const BOOST_NOEXCEPT { + return false; + } + + BOOST_MP_FORCEINLINE void sign(bool b) BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) { + if (b) { + negate(); + } + } + + BOOST_MP_FORCEINLINE void resize(unsigned, unsigned min_size) { + detail::verify_new_size(2, min_size, checked_type()); + } + + BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) { + detail::verify_limb_mask(true, m_data, limb_mask, checked_type()); + m_data &= limb_mask; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base() BOOST_NOEXCEPT : m_data(0) { + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_base(const montgomery_int_base &o) BOOST_NOEXCEPT + : m_data(o.m_data) { + } + //~montgomery_int_base() BOOST_NOEXCEPT {} + BOOST_MP_FORCEINLINE void assign(const montgomery_int_base &o) BOOST_NOEXCEPT { + m_data = o.m_data; + } + + BOOST_MP_FORCEINLINE void negate() BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) { + if (Checked == checked) { + BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned type.")); + } + m_data = ~m_data; + ++m_data; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg() const BOOST_NOEXCEPT { + return false; + } + + BOOST_MP_FORCEINLINE void do_swap(montgomery_int_base &o) BOOST_NOEXCEPT { + std::swap(m_data, o.m_data); + } + }; + +// +// Traits class, lets us know whether type T can be directly converted to the base type, +// used to enable/disable constructors etc: +// + template + struct is_allowed_montgomery_int_base_conversion : public mpl::if_c< + is_same::value || is_same::value + #if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE) + || is_same::value || is_same::value + #endif + #if defined(BOOST_MP_USER_DEFINED_LITERALS) + || literals::detail::is_value_pack::value + #endif + || (is_trivial_montgomery_int < Base > ::value && is_arithmetic::value), mpl::true_, + mpl::false_>::type { + }; + +// +// Now the actual backend, normalising parameters passed to the base class: +// + /*!template + */ + template + struct montgomery_int_backend : public montgomery_int_base< + min_precision >::value, + max_precision >::value, + SignType, Checked, Allocator, ParamsBackend, is_trivial_montgomery_int< + montgomery_int_backend >::value> { + typedef montgomery_int_backend self_type; + typedef montgomery_int_base::value, max_precision::value, SignType, + Checked, Allocator, ParamsBackend, is_trivial_montgomery_int::value> base_type; + typedef mpl::bool_::value> trivial_tag; + public: + typedef typename mpl::if_, + mpl::list >::type signed_types; + typedef typename mpl::if_, mpl::list >::type unsigned_types; + typedef typename mpl::if_, + mpl::list >::type float_types; + typedef mpl::int_ checked_type; + + nil::crypto3::montgomery_params m_params; + + //montgomery_int_backend value() const { + void value() const { + //auto t = this->limbs(); + //auto x = redc(m_params, t); + //auto x = redc(*this); + //return redc(this); + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_backend() BOOST_NOEXCEPT { + + } + + //zerg + template + montgomery_int_backend(const cpp_int_backend &o, + const nil::crypto3::montgomery_params ¶ms) : base_type(o) { + m_params = params; + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_backend( + const montgomery_int_backend &o) BOOST_MP_NOEXCEPT_IF(boost::is_void::value) + : base_type(o) { + m_params = o.m_params; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_backend(montgomery_int_backend &&o) BOOST_NOEXCEPT + : base_type(static_cast(o)) { + } + +#endif + template + montgomery_int_backend(Arg i, const nil::crypto3::montgomery_params &p, typename boost::enable_if_c< + is_allowed_montgomery_int_base_conversion::value>::type const * = 0) BOOST_MP_NOEXCEPT_IF( + noexcept(base_type(std::declval()))) + : base_type(i) { + m_params = p; + } + // + // Direct construction from arithmetic type: + // + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_int_backend(Arg i, typename boost::enable_if_c< + is_allowed_montgomery_int_base_conversion::value>::type const * = 0) BOOST_MP_NOEXCEPT_IF( + noexcept(base_type(std::declval()))) + : base_type(i) { + } + + private: + template + void do_assign(const montgomery_int_backend &other, + mpl::true_ const &, mpl::true_ const &) { + // Assigning trivial type to trivial type: + this->check_in_range(*other.limbs()); + *this->limbs() = static_cast(*other.limbs()); + this->sign(other.sign()); + this->normalize(); + } + + template + void do_assign(const montgomery_int_backend &other, + mpl::true_ const &, mpl::false_ const &) { + // non-trivial to trivial narrowing conversion: + double_limb_type v = *other.limbs(); + if (other.size() > 1) { + v |= static_cast(other.limbs()[1]) << bits_per_limb; + if ((Checked == checked) && (other.size() > 2)) { + BOOST_THROW_EXCEPTION(std::range_error( + "Assignment of a cpp_int that is out of range for the target type.")); + } + } + *this = v; + this->sign(other.sign()); + this->normalize(); + } + + template + void do_assign(const montgomery_int_backend &other, + mpl::false_ const &, mpl::true_ const &) { + // trivial to non-trivial, treat the trivial argument as if it were an unsigned arithmetic type, then set the sign afterwards: + *this = static_cast< + typename boost::multiprecision::detail::canonical< + typename montgomery_int_backend::local_limb_type, + montgomery_int_backend >::type + >(*other.limbs()); + this->sign(other.sign()); + } + + template + void do_assign(const montgomery_int_backend &other, + mpl::false_ const &, mpl::false_ const &) { + // regular non-trivial to non-trivial assign: + this->resize(other.size(), other.size()); + std::memcpy(this->limbs(), other.limbs(), + (std::min)(other.size(), this->size()) * sizeof(this->limbs()[0])); + this->sign(other.sign()); + this->normalize(); + } + + public: + template + montgomery_int_backend( + const montgomery_int_backend &other, + typename boost::enable_if_c, + self_type>::value>::type * = 0) + : base_type() { + do_assign(other, mpl::bool_::value>(), mpl::bool_< + is_trivial_montgomery_int >::value>()); + } + + template + explicit montgomery_int_backend( + const montgomery_int_backend &other, + typename boost::disable_if_c, + self_type>::value>::type * = 0) + : base_type() { + do_assign(other, mpl::bool_::value>(), mpl::bool_< + is_trivial_montgomery_int >::value>()); + } + + template + montgomery_int_backend &operator=( + const montgomery_int_backend &other) { + do_assign(other, mpl::bool_::value>(), mpl::bool_< + is_trivial_montgomery_int >::value>()); + return *this; + } + +#ifdef BOOST_MP_USER_DEFINED_LITERALS + + BOOST_CONSTEXPR montgomery_int_backend(const montgomery_int_backend &a, + const literals::detail::negate_tag &tag) : base_type( + static_cast(a), tag) { + } + +#endif + + BOOST_MP_FORCEINLINE montgomery_int_backend &operator=( + const montgomery_int_backend &o) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().assign( + std::declval()))) { + this->assign(o); + m_params = o.m_params; + return *this; + } + /* + BOOST_MP_FORCEINLINE montgomery_int_backend &operator=( + const cpp_int &o) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().assign( + std::declval()))) { + //this->assign(o); + return *this; + } + */ +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + BOOST_MP_FORCEINLINE montgomery_int_backend &operator=(montgomery_int_backend &&o) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval() = std::declval())) { + *static_cast(this) = static_cast(o); + return *this; + } + +#endif + private: + template + typename boost::enable_if >::type do_assign_arithmetic(A val, + const mpl::true_ &) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().check_in_range(std::declval()))) { + this->check_in_range(val); + *this->limbs() = static_cast(val); + this->normalize(); + } + + template + typename boost::disable_if_c< + is_unsigned::value || !is_integral::value>::type do_assign_arithmetic(A val, + const mpl::true_ &) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().check_in_range(std::declval())) && + noexcept(std::declval().sign(true))) { + this->check_in_range(val); + *this->limbs() = (val < 0) + ? static_cast(boost::multiprecision::detail::unsigned_abs( + val)) : static_cast(val); + this->sign(val < 0); + this->normalize(); + } + + template + typename boost::enable_if_c::value>::type do_assign_arithmetic(A val, + const mpl::true_ &) { + this->check_in_range(val); + *this->limbs() = (val < 0) + ? static_cast(boost::multiprecision::detail::abs( + val)) : static_cast(val); + this->sign(val < 0); + this->normalize(); + } + + BOOST_MP_FORCEINLINE void do_assign_arithmetic(limb_type i, const mpl::false_ &) BOOST_NOEXCEPT { + this->resize(1, 1); + *this->limbs() = i; + this->sign(false); + } + + BOOST_MP_FORCEINLINE void do_assign_arithmetic(signed_limb_type i, + const mpl::false_ &) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().sign(true))) { + this->resize(1, 1); + *this->limbs() = static_cast(boost::multiprecision::detail::unsigned_abs(i)); + this->sign(i < 0); + } + + void do_assign_arithmetic(double_limb_type i, const mpl::false_ &) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type)); + BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2); + typename base_type::limb_pointer p = this->limbs(); +#ifdef __MSVC_RUNTIME_CHECKS + *p = static_cast(i & ~static_cast(0)); +#else + *p = static_cast(i); +#endif + p[1] = static_cast(i >> base_type::limb_bits); + this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1); + this->sign(false); + } + + void do_assign_arithmetic(signed_double_limb_type i, const mpl::false_ &) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().sign(true))) { + BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type)); + BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2); + bool s = false; + double_limb_type ui; + if (i < 0) { + s = true; + } + ui = static_cast(boost::multiprecision::detail::unsigned_abs(i)); + typename base_type::limb_pointer p = this->limbs(); +#ifdef __MSVC_RUNTIME_CHECKS + *p = static_cast(ui & ~static_cast(0)); +#else + *p = static_cast(ui); +#endif + p[1] = static_cast(ui >> base_type::limb_bits); + this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1); + this->sign(s); + } + + void do_assign_arithmetic(long double a, const mpl::false_ &) { + using default_ops::eval_add; + using default_ops::eval_subtract; + using std::frexp; + using std::ldexp; + using std::floor; + + if (a < 0) { + do_assign_arithmetic(-a, mpl::false_()); + this->sign(true); + return; + } + + if (a == 0) { + *this = static_cast(0u); + } + + if (a == 1) { + *this = static_cast(1u); + } + + BOOST_ASSERT(!(boost::math::isinf)(a)); + BOOST_ASSERT(!(boost::math::isnan)(a)); + + int e; + long double f, term; + *this = static_cast(0u); + + f = frexp(a, &e); + + static const limb_type shift = std::numeric_limits::digits; + + while (f) { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + eval_left_shift(*this, shift); + if (term > 0) { + eval_add(*this, static_cast(term)); + } else { + eval_subtract(*this, static_cast(-term)); + } + f -= term; + } + if (e > 0) { + eval_left_shift(*this, e); + } else if (e < 0) { + eval_right_shift(*this, -e); + } + } + + public: + template + BOOST_MP_FORCEINLINE typename boost::enable_if_c< + !boost::multiprecision::detail::is_byte_container::value, + montgomery_int_backend &>::type operator=(Arithmetic val) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval().do_assign_arithmetic(std::declval(), + trivial_tag()))) { + do_assign_arithmetic(val, trivial_tag()); + return *this; + } + + private: + void do_assign_string(const char *s, const mpl::true_ &) { + std::size_t n = s ? std::strlen(s) : 0; + *this = 0; + unsigned radix = 10; + bool isneg = false; + if (n && (*s == '-')) { + --n; + ++s; + isneg = true; + } + if (n && (*s == '0')) { + if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) { + radix = 16; + s += 2; + n -= 2; + } else { + radix = 8; + n -= 1; + } + } + if (n) { + unsigned val; + while (*s) { + if (*s >= '0' && *s <= '9') { + val = *s - '0'; + } else if (*s >= 'a' && *s <= 'f') { + val = 10 + *s - 'a'; + } else if (*s >= 'A' && *s <= 'F') { + val = 10 + *s - 'A'; + } else { + val = radix + 1; + } + if (val >= radix) { + BOOST_THROW_EXCEPTION( + std::runtime_error("Unexpected content found while parsing character string.")); + } + *this->limbs() = detail::checked_multiply(*this->limbs(), + static_cast(radix), checked_type()); + *this->limbs() = detail::checked_add(*this->limbs(), + static_cast(val), checked_type()); + ++s; + } + } + if (isneg) { + this->negate(); + } + } + + void do_assign_string(const char *s, const mpl::false_ &) { + using default_ops::eval_multiply; + using default_ops::eval_add; + std::size_t n = s ? std::strlen(s) : 0; + *this = static_cast(0u); + unsigned radix = 10; + bool isneg = false; + if (n && (*s == '-')) { + --n; + ++s; + isneg = true; + } + if (n && (*s == '0')) { + if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) { + radix = 16; + s += 2; + n -= 2; + } else { + radix = 8; + n -= 1; + } + } + // + // Exception guarantee: create the result in stack variable "result" + // then do a swap at the end. In the event of a throw, *this will + // be left unchanged. + // + montgomery_int_backend result; + if (n) { + if (radix == 16) { + while (*s == '0') { + ++s; + } + std::size_t bitcount = 4 * std::strlen(s); + limb_type val; + std::size_t limb, shift; + if (bitcount > 4) { + bitcount -= 4; + } else { + bitcount = 0; + } + std::size_t newsize = bitcount / (sizeof(limb_type) * CHAR_BIT) + 1; + result.resize(static_cast(newsize), + static_cast(newsize)); // will throw if this is a checked integer that cannot be resized + std::memset(result.limbs(), 0, result.size() * sizeof(limb_type)); + while (*s) { + if (*s >= '0' && *s <= '9') { + val = *s - '0'; + } else if (*s >= 'a' && *s <= 'f') { + val = 10 + *s - 'a'; + } else if (*s >= 'A' && *s <= 'F') { + val = 10 + *s - 'A'; + } else { + BOOST_THROW_EXCEPTION(std::runtime_error( + "Unexpected content found while parsing character string.")); + } + limb = bitcount / (sizeof(limb_type) * CHAR_BIT); + shift = bitcount % (sizeof(limb_type) * CHAR_BIT); + val <<= shift; + if (result.size() > limb) { + result.limbs()[limb] |= val; + } + ++s; + bitcount -= 4; + } + result.normalize(); + } else if (radix == 8) { + while (*s == '0') { + ++s; + } + std::size_t bitcount = 3 * std::strlen(s); + limb_type val; + std::size_t limb, shift; + if (bitcount > 3) { + bitcount -= 3; + } else { + bitcount = 0; + } + std::size_t newsize = bitcount / (sizeof(limb_type) * CHAR_BIT) + 1; + result.resize(static_cast(newsize), + static_cast(newsize)); // will throw if this is a checked integer that cannot be resized + std::memset(result.limbs(), 0, result.size() * sizeof(limb_type)); + while (*s) { + if (*s >= '0' && *s <= '7') { + val = *s - '0'; + } else { + BOOST_THROW_EXCEPTION(std::runtime_error( + "Unexpected content found while parsing character string.")); + } + limb = bitcount / (sizeof(limb_type) * CHAR_BIT); + shift = bitcount % (sizeof(limb_type) * CHAR_BIT); + if (result.size() > limb) { + result.limbs()[limb] |= (val << shift); + if (shift > sizeof(limb_type) * CHAR_BIT - 3) { + // Deal with the bits in val that overflow into the next limb: + val >>= (sizeof(limb_type) * CHAR_BIT - shift); + if (val) { + // If this is the most-significant-limb, we may need to allocate an extra one for the overflow: + if (limb + 1 == newsize) { + result.resize(static_cast(newsize + 1), + static_cast(newsize + 1)); + } + if (result.size() > limb + 1) { + result.limbs()[limb + 1] |= val; + } + } + } + } + ++s; + bitcount -= 3; + } + result.normalize(); + } else { + // Base 10, we extract blocks of size 10^9 at a time, that way + // the number of multiplications is kept to a minimum: + limb_type block_mult = max_block_10; + while (*s) { + limb_type block = 0; + for (unsigned i = 0; i < digits_per_block_10; ++i) { + limb_type val; + if (*s >= '0' && *s <= '9') { + val = *s - '0'; + } else + BOOST_THROW_EXCEPTION( + std::runtime_error("Unexpected character encountered in input.")); + block *= 10; + block += val; + if (!*++s) { + block_mult = block_multiplier(i); + break; + } + } + eval_multiply(result, block_mult); + eval_add(result, block); + } + } + } + if (isneg) { + result.negate(); + } + result.swap(*this); + } + + public: + montgomery_int_backend &operator=(const char *s) { + do_assign_string(s, trivial_tag()); + return *this; + } + + BOOST_MP_FORCEINLINE void swap(montgomery_int_backend &o) BOOST_NOEXCEPT { + this->do_swap(o); + } + + private: + std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::false_ &) const { + typedef typename mpl::if_c::type io_type; + if (this->sign() && (((f & std::ios_base::hex) == std::ios_base::hex) || + ((f & std::ios_base::oct) == std::ios_base::oct))) + BOOST_THROW_EXCEPTION( + std::runtime_error("Base 8 or 16 printing of negative numbers is not supported.")); + std::stringstream ss; + ss.flags(f & ~std::ios_base::showpos); + ss << static_cast(*this->limbs()); + std::string result; + if (this->sign()) { + result += '-'; + } else if (f & std::ios_base::showpos) { + result += '+'; + } + result += ss.str(); + return result; + } + + std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::true_ &) const { + // Even though we have only one limb, we can't do IO on it :-( + int base = 10; + if ((f & std::ios_base::oct) == std::ios_base::oct) { + base = 8; + } else if ((f & std::ios_base::hex) == std::ios_base::hex) { + base = 16; + } + std::string result; + + unsigned Bits = sizeof(typename base_type::local_limb_type) * CHAR_BIT; + + if (base == 8 || base == 16) { + if (this->sign()) + BOOST_THROW_EXCEPTION( + std::runtime_error("Base 8 or 16 printing of negative numbers is not supported.")); + limb_type shift = base == 8 ? 3 : 4; + limb_type mask = static_cast((1u << shift) - 1); + typename base_type::local_limb_type v = *this->limbs(); + result.assign(Bits / shift + (Bits % shift ? 1 : 0), '0'); + std::string::difference_type pos = result.size() - 1; + for (unsigned i = 0; i < Bits / shift; ++i) { + char c = '0' + static_cast(v & mask); + if (c > '9') { + c += 'A' - '9' - 1; + } + result[pos--] = c; + v >>= shift; + } + if (Bits % shift) { + mask = static_cast((1u << (Bits % shift)) - 1); + char c = '0' + static_cast(v & mask); + if (c > '9') { + c += 'A' - '9'; + } + result[pos] = c; + } + // + // Get rid of leading zeros: + // + std::string::size_type n = result.find_first_not_of('0'); + if (!result.empty() && (n == std::string::npos)) { + n = result.size() - 1; + } + result.erase(0, n); + if (f & std::ios_base::showbase) { + const char *pp = base == 8 ? "0" : "0x"; + result.insert(static_cast(0), pp); + } + } else { + result.assign(Bits / 3 + 1, '0'); + std::string::difference_type pos = result.size() - 1; + typename base_type::local_limb_type v(*this->limbs()); + bool neg = false; + if (this->sign()) { + neg = true; + } + while (v) { + result[pos] = (v % 10) + '0'; + --pos; + v /= 10; + } + std::string::size_type n = result.find_first_not_of('0'); + result.erase(0, n); + if (result.empty()) { + result = "0"; + } + if (neg) { + result.insert(static_cast(0), 1, '-'); + } else if (f & std::ios_base::showpos) { + result.insert(static_cast(0), 1, '+'); + } + } + return result; + } + + std::string do_get_string(std::ios_base::fmtflags f, const mpl::true_ &) const { +#ifdef BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO + return do_get_trivial_string(f, + mpl::bool_::value>()); +#else + return do_get_trivial_string(f, mpl::bool_()); +#endif + } + + std::string do_get_string(std::ios_base::fmtflags f, const mpl::false_ &) const { + using default_ops::eval_get_sign; + int base = 10; + if ((f & std::ios_base::oct) == std::ios_base::oct) { + base = 8; + } else if ((f & std::ios_base::hex) == std::ios_base::hex) { + base = 16; + } + std::string result; + + unsigned Bits = this->size() * base_type::limb_bits; + + if (base == 8 || base == 16) { + if (this->sign()) + BOOST_THROW_EXCEPTION( + std::runtime_error("Base 8 or 16 printing of negative numbers is not supported.")); + limb_type shift = base == 8 ? 3 : 4; + limb_type mask = static_cast((1u << shift) - 1); + montgomery_int_backend t(*this); + result.assign(Bits / shift + ((Bits % shift) ? 1 : 0), '0'); + std::string::difference_type pos = result.size() - 1; + for (unsigned i = 0; i < Bits / shift; ++i) { + char c = '0' + static_cast(t.limbs()[0] & mask); + if (c > '9') { + c += 'A' - '9' - 1; + } + result[pos--] = c; + eval_right_shift(t, shift); + } + if (Bits % shift) { + mask = static_cast((1u << (Bits % shift)) - 1); + char c = '0' + static_cast(t.limbs()[0] & mask); + if (c > '9') { + c += 'A' - '9'; + } + result[pos] = c; + } + // + // Get rid of leading zeros: + // + std::string::size_type n = result.find_first_not_of('0'); + if (!result.empty() && (n == std::string::npos)) { + n = result.size() - 1; + } + result.erase(0, n); + if (f & std::ios_base::showbase) { + const char *pp = base == 8 ? "0" : "0x"; + result.insert(static_cast(0), pp); + } + } else { + result.assign(Bits / 3 + 1, '0'); + std::string::difference_type pos = result.size() - 1; + montgomery_int_backend t(*this); + redc(t); + montgomery_int_backend r; + bool neg = false; + if (t.sign()) { + t.negate(); + neg = true; + } + if (this->size() == 1) { + result = boost::lexical_cast(t.limbs()[0]); + } else { + montgomery_int_backend block10; + block10 = max_block_10; + while (eval_get_sign(t) != 0) { + montgomery_int_backend t2; + divide_unsigned_helper(&t2, t, block10, r); + t = t2; + limb_type v = r.limbs()[0]; + for (unsigned i = 0; i < digits_per_block_10; ++i) { + char c = '0' + v % 10; + v /= 10; + result[pos] = c; + if (pos-- == 0) { + break; + } + } + } + } + std::string::size_type n = result.find_first_not_of('0'); + result.erase(0, n); + if (result.empty()) { + result = "0"; + } + if (neg) { + result.insert(static_cast(0), 1, '-'); + } else if (f & std::ios_base::showpos) { + result.insert(static_cast(0), 1, '+'); + } + } + return result; + } + + public: + std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f) const { + return do_get_string(f, trivial_tag()); + } + + private: + template + void construct_from_container(const Container &c, const mpl::false_ &) { + // + // We assume that c is a sequence of (unsigned) bytes with the most significant byte first: + // + unsigned newsize = static_cast(c.size() / sizeof(limb_type)); + if (c.size() % sizeof(limb_type)) { + ++newsize; + } + if (newsize) { + this->resize(newsize, newsize); // May throw + std:x:memset(this->limbs(), 0, this->size()); + typename Container::const_iterator i(c.begin()), j(c.end()); + unsigned byte_location = static_cast(c.size() - 1); + while (i != j) { + unsigned limb = byte_location / sizeof(limb_type); + unsigned shift = (byte_location % sizeof(limb_type)) * CHAR_BIT; + if (this->size() > limb) { + this->limbs()[limb] |= static_cast(static_cast(*i)) << shift; + } + ++i; + --byte_location; + } + } + } + + template + void construct_from_container(const Container &c, const mpl::true_ &) { + // + // We assume that c is a sequence of (unsigned) bytes with the most significant byte first: + // + typedef typename base_type::local_limb_type local_limb_type; + *this->limbs() = 0; + if (c.size()) { + typename Container::const_iterator i(c.begin()), j(c.end()); + unsigned byte_location = static_cast(c.size() - 1); + while (i != j) { + unsigned limb = byte_location / sizeof(local_limb_type); + unsigned shift = (byte_location % sizeof(local_limb_type)) * CHAR_BIT; + if (limb == 0) { + this->limbs()[0] |= static_cast(static_cast(*i)) << shift; + } + ++i; + --byte_location; + } + } + } + + public: + template + montgomery_int_backend(const Container &c, typename boost::enable_if_c< + boost::multiprecision::detail::is_byte_container::value>::type const * = 0) { + // + // We assume that c is a sequence of (unsigned) bytes with the most significant byte first: + // + construct_from_container(c, trivial_tag()); + } + + template class Backend, + unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c>::value, int> + ::type compare_imp(const Backend &o, + const mpl::false_ &, const mpl::false_ &) const BOOST_NOEXCEPT { + if (this->sign() != o.sign()) { + return this->sign() ? -1 : 1; + } + + // Only do the compare if the same sign: + int result = compare_unsigned(o); + + if (this->sign()) { + result = -result; + } + return result; + } + + template class Backend, + unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c>::value, int> + + //template + ::type compare_imp(const Backend &o, + const mpl::true_ &, const mpl::false_ &) const { + Backend t(*this); + return t.compare(o); + } + + template class Backend, + unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c>::value, int> + ::type compare_imp(const Backend &o, + const mpl::false_ &, const mpl::true_ &) const { + Backend t(o); + return compare(t); + } + + template class Backend, + unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c>::value, int> + ::type compare_imp(const Backend &o, + const mpl::true_ &, const mpl::true_ &) const BOOST_NOEXCEPT { + if (this->sign()) { + if (o.sign()) { + return *this->limbs() < *o.limbs() ? 1 : (*this->limbs() > *o.limbs() ? -1 : 0); + } else { + return -1; + } + } else { + if (o.sign()) { + return 1; + } + return *this->limbs() < *o.limbs() ? -1 : (*this->limbs() > *o.limbs() ? 1 : 0); + } + } + + template class Backend, + unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c>::value, int> + ::type compare(const Backend &o) const BOOST_NOEXCEPT { + typedef mpl::bool_ >::value> t1; + typedef mpl::bool_ >::value> t2; + return compare_imp(o, t1(), t2()); + } + + template class Backend, + unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c>::value, int> + ::type compare_unsigned(const Backend &o) const BOOST_NOEXCEPT { + if (this->size() != o.size()) { + return this->size() > o.size() ? 1 : -1; + } + typename base_type::const_limb_pointer pa = this->limbs(); + typename base_type::const_limb_pointer pb = o.limbs(); + for (int i = this->size() - 1; i >= 0; --i) { + if (pa[i] != pb[i]) { + return pa[i] > pb[i] ? 1 : -1; + } + } + return 0; + } + + template class Backend, + unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> + BOOST_MP_FORCEINLINE typename enable_if_c>::value, int> + ::type compare_unsigned(const Backend &o) const BOOST_NOEXCEPT { + if (this->size() != o.size()) { + return this->size() > o.size() ? 1 : -1; + } + typename base_type::const_limb_pointer pa = this->limbs(); + typename base_type::const_limb_pointer pb = o.limbs(); + for (int i = this->size() - 1; i >= 0; --i) { + if (pa[i] != pb[i]) { + return pa[i] > pb[i] ? 1 : -1; + } + } + return 0; + } + + template + BOOST_MP_FORCEINLINE typename boost::enable_if, int>::type compare( + Arithmetic i) const { + // braindead version: + montgomery_int_backend t; + t = i; + return compare(t); + } + }; + + } // namespace backends + + namespace default_ops { + + template + struct double_precision_type; + + template + struct double_precision_type< + backends::montgomery_int_backend > { + typedef typename mpl::if_c >::value, + backends::montgomery_int_backend<(is_void::value ? 2 * backends::max_precision< + backends::montgomery_int_backend >::value : MinBits), 2 * backends::max_precision< + backends::montgomery_int_backend >::value, SignType, Checked,Allocator, ParamsBackend>, + backends::montgomery_int_backend >::type type; + }; + + + } + + template + struct expression_template_default< + backends::montgomery_int_backend > { + static const expression_template_option value = et_off; + }; + + using boost::multiprecision::backends::montgomery_int_backend; + + template + struct number_category > + : public mpl::int_ { + }; + + typedef number > montgomery_int; + typedef rational_adaptor > montgomery_rational_backend; + typedef number montgomery_rational; + +// Fixed precision unsigned types: + typedef number > umontgomery128_t; + typedef number > umontgomery256_t; + typedef number > umontgomery512_t; + typedef number > umontgomery1024_t; + +// Fixed precision signed types: + typedef number > montgomery128_t; + typedef number > montgomery256_t; + typedef number > montgomery512_t; + typedef number > montgomery1024_t; + +// Over again, but with checking enabled this time: + typedef number > checked_montgomery_int; + typedef rational_adaptor > checked_montgomery_rational_backend; + typedef number checked_cpp_rational; +// Fixed precision unsigned types: + typedef number > checked_umontgomery128_t; + typedef number > checked_umontgomery256_t; + typedef number > checked_umontgomery512_t; + typedef number > checked_umontgomery1024_t; + +// Fixed precision signed types: + typedef number > checked_montgomery128_t; + typedef number > checked_montgomery256_t; + typedef number > checked_montgomery512_t; + typedef number > checked_montgomery1024_t; + + +#ifdef BOOST_NO_SFINAE_EXPR + + namespace detail{ + + template + struct is_explicitly_convertible, montgomery_int_backend > : public mpl::true_ {}; + + } +#endif + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + } +} // namespaces + + +template +struct component_type, ExpressionTemplates> > +{ + typedef cpp_int type; +}; + +// +// Last of all we include the implementations of all the eval_* non member functions: +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_MP_USER_DEFINED_LITERALS + +//#include + +#endif + +#include +#include +#endif \ No newline at end of file diff --git a/include/boost/multiprecision/montgomery_int/montgomery_params.hpp b/include/boost/multiprecision/montgomery_int/montgomery_params.hpp new file mode 100644 index 000000000..485b75da2 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/montgomery_params.hpp @@ -0,0 +1,159 @@ +#ifndef CRYPTO3_MONTY_INT_H_ +#define CRYPTO3_MONTY_INT_H_ + +#include +#include + +using namespace boost::multiprecision; + +namespace nil { + namespace crypto3 { + + class modular_reducer; + + /** + * Parameters for Montgomery Reduction + */ + template + class montgomery_params { + public: + typedef NumberType number_type; + + /** + * Initialize a set of Montgomery reduction parameters. These values + * can be shared by all values in a specific Montgomery domain. + */ + + //work_only_with_cpp_int + template + explicit montgomery_params(const number &p, + const number &redc_module) { + + if (p < 0 || !(p % 2)) { + throw std::invalid_argument("montgomery_params invalid modulus"); + } + + m_p = p; + + m_mod = redc_module; + + m_p_words = m_p.backend().size(); + + m_p_dash = monty_inverse(m_p.backend().limbs()[0]); + + number_type r; + + boost::multiprecision::backends::eval_bit_set(r.backend(), m_p_words * CRYPTO3_MP_WORD_BITS); + + m_r1 = r; + mod_redc(m_r1.backend(), redc_module.backend()); + m_r2 = m_r1; + eval_multiply(m_r2.backend(), m_r1.backend()); + mod_redc(m_r2.backend(), redc_module.backend()); + m_r3 = m_r2; + eval_multiply(m_r3.backend(), m_r1.backend()); + mod_redc(m_r3.backend(), redc_module.backend()); + } + + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR montgomery_params() BOOST_NOEXCEPT { + + } + + template + explicit montgomery_params() { + + } + + /** + * Initialize a set of Montgomery reduction parameters. These values + * can be shared by all values in a specific Montgomery domain. + */ + template + explicit montgomery_params(const number &p) { + + if (p < 0 || !(p % 2)) { + throw std::invalid_argument("montgomery_params invalid modulus"); + } + + m_p = p; + + m_mod = p; + + m_p_words = m_p.backend().size(); + + m_p_dash = monty_inverse(m_p.backend().limbs()[0]); + + number_type r; + + boost::multiprecision::backends::eval_bit_set(r.backend(), m_p_words * CRYPTO3_MP_WORD_BITS); + + m_r1 = r; + mod_redc(m_r1.backend(), p.backend()); + m_r2 = m_r1; + eval_multiply(m_r2.backend(), m_r1.backend()); + mod_redc(m_r2.backend(), p.backend()); + m_r3 = m_r2; + eval_multiply(m_r3.backend(), m_r1.backend()); + mod_redc(m_r3.backend(), p.backend()); + } + + const number_type &mod() const { + return m_mod; + } + + const number_type &p() const { + return m_p; + } + + const number_type &R1() const { + return m_r1; + } + + const number_type &R2() const { + return m_r2; + } + + const number_type &R3() const { + return m_r3; + } + + + limb_type p_dash() const { + return m_p_dash; + } + + size_t p_words() const { + return m_p_words; + } + + + /* + operator number_type() { + return m_p; + }; + */ + + template + operator number() { + number x = 0; + return x; + }; + + private: + NumberType m_p; + NumberType m_r1; + NumberType m_r2; + NumberType m_r3; + limb_type m_p_dash; + size_t m_p_words; + NumberType m_mod; + }; + +/** +* The Montgomery representation of an integer +*/ + + } +} + +#endif diff --git a/include/boost/multiprecision/montgomery_int/multiply.hpp b/include/boost/multiprecision/montgomery_int/multiply.hpp new file mode 100644 index 000000000..cd8c70c72 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/multiply.hpp @@ -0,0 +1,999 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_MUL_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_MUL_HPP + +namespace boost { + namespace multiprecision { + namespace backends { + +#ifdef _MSC_VER + #pragma warning(push) +#pragma warning(disable:4127) // conditional expression is constant +#endif + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int::value > + ::type eval_multiply_helper( + montgomery_int_backend& result, + const Backend& a, + const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + if (!val) { + result = static_cast(0); + redc(result); + return; + } + if ((void *) &a != (void *) &result) { + result.resize(a.size(), a.size()); + } + double_limb_type carry = 0; + typename montgomery_int_backend::limb_pointer p = result.limbs(); + typename montgomery_int_backend::limb_pointer pe = + result.limbs() + result.size(); + typename Backend::const_limb_pointer pa = a.limbs(); + while (p != pe) { + carry += static_cast + (*pa) * static_cast + (val); +#ifdef __MSVC_RUNTIME_CHECKS + *p = static_cast(carry & ~static_cast(0)); +#else + *p = static_cast(carry); +#endif + carry >>= montgomery_int_backend::limb_bits; + ++p, ++pa; + } + if (carry) { + unsigned i = result.size(); + result.resize(i + 1, i + 1); + if (result.size() > i) { + result.limbs()[i] = static_cast(carry); + } + } + result.sign(a.sign()); + if (!montgomery_int_backend::variable) { + result.normalize(); + } + redc(result); + } + +// +// resize_for_carry forces a resize of the underlying buffer only if a previous request +// for "required" elements could possibly have failed, *and* we have checking enabled. +// This will cause an overflow error inside resize(): +// + template + inline void resize_for_carry( + montgomery_int_backend & /*result*/, + unsigned /*required*/) { + } + + template + inline void resize_for_carry( + montgomery_int_backend &result, + unsigned required) { + if (result.size() < required) { + result.resize(required, required); + } + } + + //SPLIT FOR 2 + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_montgomery_int::value && + !is_trivial_montgomery_int::value >::type + eval_multiply_helper( + montgomery_int_backend& result, + const Backend1& a, + const Backend2& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { +// Very simple long multiplication, only usable for small numbers of limb_type's +// but that's the typical use case for this type anyway: +// +// Special cases first: +// + unsigned as = a.size(); + unsigned bs = b.size(); + typename Backend1::const_limb_pointer pa = a.limbs(); + typename Backend2::const_limb_pointer pb = b.limbs(); + if (as == 1) { + bool s = b.sign() != a.sign(); + if (bs == 1) { + result = static_cast(*pa) * static_cast(*pb); + redc(result); + } else { + limb_type l = *pa; + eval_multiply_helper(result, b, l); + } + result.sign(s); + return; + } + if (bs == 1) { + bool s = b.sign() != a.sign(); + limb_type l = *pb; + eval_multiply_helper(result, a, l); + result.sign(s); + return; + } + + if ((void *) &result == (void *) &a) { + montgomery_int_backend t(a); + eval_multiply_helper(result, t, b); + return; + } + if ((void *) &result == (void *) &b) { + //montgomery_int_backend t(b); //TODO: fix it!!! Very bad if b - cpp_int + //eval_multiply_helper(result, a, t); + return; + } + + result.resize(as + bs, as + bs - 1); + typename montgomery_int_backend::limb_pointer pr = result.limbs(); + + static const double_limb_type limb_max = ~static_cast(0u); + static const double_limb_type double_limb_max = ~static_cast(0u); + BOOST_STATIC_ASSERT(double_limb_max - 2 * limb_max >= limb_max * limb_max); + + double_limb_type carry = 0; + std::memset(pr, 0, result.size() * sizeof(limb_type)); + for (unsigned i = 0; i < as; ++i) { + unsigned inner_limit = montgomery_int_backend::variable ? bs : (std::min)(result.size() - i, bs); + unsigned j; + for (j = 0; j < inner_limit; ++j) { + BOOST_ASSERT(i + j < result.size()); +#if (!defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || !BOOST_WORKAROUND(BOOST_GCC_VERSION, <= 50100) + BOOST_ASSERT(!std::numeric_limits::is_specialized || + ((std::numeric_limits::max)() - carry > static_cast + (montgomery_int_backend::max_limb_value) * static_cast + (montgomery_int_backend::max_limb_value))); +#endif + carry += static_cast + (pa[i]) * static_cast + (pb[j]); + BOOST_ASSERT(!std::numeric_limits::is_specialized || + ((std::numeric_limits::max)() - carry >= pr[i + j])); + carry += pr[i + j]; +#ifdef __MSVC_RUNTIME_CHECKS + pr[i + j] = static_cast(carry & ~static_cast(0)); +#else + pr[i + j] = static_cast + (carry); +#endif + carry >>= montgomery_int_backend::limb_bits; + BOOST_ASSERT(carry <= (montgomery_int_backend::max_limb_value)); + } + if (carry) { + resize_for_carry(result, i + j + 1); // May throw if checking is enabled + if (i + j < result.size()) +#ifdef __MSVC_RUNTIME_CHECKS + pr[i + j] = static_cast(carry & ~static_cast(0)); +#else + { + pr[i + j] = static_cast(carry); + } +#endif + } + carry = 0; + } + result.normalize(); + +// +// Set the sign of the result: +// + result.sign(a.sign() != b.sign()); + redc(result); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int::value >::type + eval_multiply_helper( + montgomery_int_backend& result, + const Backend& a) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + eval_multiply_helper(result, result, a); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c>::value>::type + eval_multiply(montgomery_int_backend& result, const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + { + eval_multiply_helper(result, result, val); + } + + template + + BOOST_MP_FORCEINLINE typename enable_if_c>::value && + !is_trivial_montgomery_int::value >::type + eval_multiply_helper( + montgomery_int_backend& result, + const Backend& a, + const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + if (val <= (std::numeric_limits::max)()) { + eval_multiply_helper(result, a, static_cast + (val)); + } else { +#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE) + montgomery_int_backend t(val); +#else + montgomery_int_backend t; + t = val; +#endif + eval_multiply_helper(result, a, t); + } + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_multiply(montgomery_int_backend &result, + const double_limb_type &val) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + eval_multiply_helper(result, result, val); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int::value >::type + eval_multiply_helper( + montgomery_int_backend& result, + const Backend& a, + const signed_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + { + if (val > 0) { + eval_multiply_helper(result, a, static_cast(val)); + } else { + eval_multiply_helper(result, a, static_cast(boost::multiprecision::detail::unsigned_abs(val))); + result.negate(); + } + } + + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_multiply(montgomery_int_backend &result, + const signed_limb_type &val) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + eval_multiply_helper(result, result, val); + } + + template + inline typename enable_if_c >::value && !is_trivial_montgomery_int::value >::type + eval_multiply_helper( + montgomery_int_backend& result, + const Backend& a, + const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + { + if (val > 0) { + if (val <= (std::numeric_limits::max)()) { + eval_multiply_helper(result, a, static_cast(val)); + return; + } + } else if (val >= -static_cast((std::numeric_limits::max)())) { + eval_multiply_helper(result, a, static_cast(boost::multiprecision::detail::unsigned_abs(val))); + result.negate(); + + return; + } +#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE) + montgomery_int_backend t(val); +#else + montgomery_int_backend t; + t = val; +#endif + eval_multiply_helper(result, a, t); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_multiply(montgomery_int_backend &result, + const signed_double_limb_type &val) + + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + montgomery_int_backend >::value)) { + eval_multiply_helper(result, result, val); + } + +// +// Now over again for trivial cpp_int's: +// + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_trivial_montgomery_int::value + && (is_signed_number>::value + || is_signed_number::value) + >::type + eval_multiply_helper( + montgomery_int_backend& result, + const Backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), + typename montgomery_int_backend::checked_type()); + + result.sign(result.sign() != o.sign()); + result.normalize(); + redc(result); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int >::value + && is_unsigned_number >::value + && is_trivial_montgomery_int::value + && is_unsigned_number::value + >::type + eval_multiply_helper( + montgomery_int_backend& result, + const Backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), + typename montgomery_int_backend::checked_type()); + + result.normalize(); + redc(result); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_trivial_montgomery_int::value + && (is_signed_number >::value + || is_signed_number::value) + >::type + eval_multiply_helper( + montgomery_int_backend& result, + const Backend& a, + const Backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), + typename montgomery_int_backend::checked_type()); + + result.sign(a.sign() != b.sign()); + result.normalize(); + redc(result); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_unsigned_number>::value + && is_trivial_montgomery_int::value + && is_unsigned_number::value + >::type + eval_multiply_helper( + montgomery_int_backend& result, + const Backend& a, + const Backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + { + *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), + typename montgomery_int_backend::checked_type()); + + result.normalize(); + redc(result); + } + +// +// Special routines for multiplying two integers to obtain a multiprecision result: +// + template + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value + >::type + eval_multiply( + montgomery_int_backend& result, + signed_double_limb_type a, signed_double_limb_type b) + { + static const signed_double_limb_type mask = ~static_cast(0); + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + bool s = false; + double_limb_type w, x, y, z; + if (a < 0) { + a = -a; + s = true; + } + if (b < 0) { + b = -b; + s = !s; + } + w = a & mask; + x = a >> limb_bits; + y = b & mask; + z = b >> limb_bits; + + result.resize(4, 4); + limb_type *pr = result.limbs(); + + double_limb_type carry = w * y; +#ifdef __MSVC_RUNTIME_CHECKS + pr[0] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + carry += w * z + x * y; + pr[1] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + carry += x * z; + pr[2] = static_cast(carry & ~static_cast(0)); + pr[3] = static_cast(carry >> limb_bits); +#else + pr[0] = static_cast(carry); + carry >>= limb_bits; + carry += w * z + x * y; + pr[1] = static_cast(carry); + carry >>= limb_bits; + carry += x * z; + pr[2] = static_cast(carry); + pr[3] = static_cast(carry >> limb_bits); +#endif + result.sign(s); + result.normalize(); + redc(result); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c >::value> + + ::type eval_multiply(montgomery_int_backend &result, + double_limb_type a, double_limb_type b) { + static const signed_double_limb_type mask = ~static_cast(0); + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + + double_limb_type w, x, y, z; + w = a & mask; + x = a >> limb_bits; + y = b & mask; + z = b >> limb_bits; + + result.resize(4, 4); + limb_type *pr = result.limbs(); + + double_limb_type carry = w * y; +#ifdef __MSVC_RUNTIME_CHECKS + pr[0] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + carry += w * z; + pr[1] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + pr[2] = static_cast(carry & ~static_cast(0)); + carry = x * y + pr[1]; + pr[1] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + carry += pr[2] + x * z; + pr[2] = static_cast(carry & ~static_cast(0)); + pr[3] = static_cast(carry >> limb_bits); +#else + pr[0] = static_cast(carry); + carry >>= limb_bits; + carry += w * z; + pr[1] = static_cast(carry); + carry >>= limb_bits; + pr[2] = static_cast(carry); + carry = x * y + pr[1]; + pr[1] = static_cast(carry); + carry >>= limb_bits; + carry += pr[2] + x * z; + pr[2] = static_cast(carry); + pr[3] = static_cast(carry >> limb_bits); +#endif + result.sign(false); + result.normalize(); + redc(result); + } + + template + + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value + && is_trivial_montgomery_int::value + && is_trivial_montgomery_int::value> + ::type eval_multiply_helper(montgomery_int_backend& result, + Backend const& a, + Backend const& b) + { + typedef typename boost::multiprecision::detail::canonical< + typename Backend::local_limb_type, + montgomery_int_backend >::type canonical_type; + eval_multiply_helper(result, static_cast(*a.limbs()), static_cast(*b.limbs())); + result.sign(a.sign() != b.sign()); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_signed::value && (sizeof(SI) <= sizeof(signed_double_limb_type) / 2)> + ::type eval_multiply(montgomery_int_backend &result, SI a, SI b) + { + result = static_cast(a) * static_cast(b); + redc(result); + } + + template + BOOST_MP_FORCEINLINE typename enable_if_c< + is_unsigned::value && (sizeof(UI) <= sizeof(signed_double_limb_type) / 2)> + ::type eval_multiply(montgomery_int_backend &result, UI a, UI b) + { + result = static_cast(a) * static_cast(b); + redc(result); + } + + //====================================================// + //====================================================// + //====================================================// + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + is_equal_montgomery_int_field>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, a, val); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + is_equal_montgomery_int_backend >::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, a, val); + } + + +// +// resize_for_carry forces a resize of the underlying buffer only if a previous request +// for "required" elements could possibly have failed, *and* we have checking enabled. +// This will cause an overflow error inside resize(): +// + + template class Backend1, + template< unsigned, unsigned, cpp_integer_type, cpp_int_check_type, typename, typename> class Backend2, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, + class Allocator3, typename ParamsBackend3> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int>::value && + is_equal_montgomery_int_field>::value && + is_equal_montgomery_int_field>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend1& a, + const Backend2& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + eval_multiply_helper(result, a, b); + } + + template class Backend1, + template< unsigned, unsigned, cpp_integer_type, cpp_int_check_type, typename> class Backend2, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, + class Allocator3> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int>::value && + is_equal_montgomery_int_field>::value&& + is_equal_montgomery_int_backend>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend1& a, + const Backend2& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + eval_multiply_helper(result, a, b); + } + + template class Backend1, + template< unsigned, unsigned, cpp_integer_type, cpp_int_check_type, typename, typename> class Backend2, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, + class Allocator3, typename ParamsBackend3> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int>::value && + is_equal_montgomery_int_field>::value && + is_equal_montgomery_int_backend>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend1& a, + const Backend2& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + eval_multiply_helper(result, a, b); + } + + template class Backend1, + template< unsigned, unsigned, cpp_integer_type, cpp_int_check_type, typename> class Backend2, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, + class Allocator3> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + !is_trivial_montgomery_int>::value && + is_equal_montgomery_int_backend>::value && + is_equal_montgomery_int_backend>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend1& a, + const Backend2& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + eval_multiply_helper(result, a, b); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int>::value && + is_equal_montgomery_int_field>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + eval_multiply(result, result, a); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int>::value && + is_equal_montgomery_int_backend>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + eval_multiply(result, result, a); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + + BOOST_MP_FORCEINLINE typename enable_if_c>::value && + !is_trivial_montgomery_int>::value && + is_equal_montgomery_int_field>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, a, val); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2> + + BOOST_MP_FORCEINLINE typename enable_if_c>::value && + !is_trivial_montgomery_int>::value && + is_equal_montgomery_int_backend>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, a, val); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + is_equal_montgomery_int_field>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const signed_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + { + eval_multiply_helper(result, a, val); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2> + BOOST_MP_FORCEINLINE typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + is_equal_montgomery_int_backend>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const signed_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + { + eval_multiply_helper(result, a, val); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + inline typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + is_equal_montgomery_int_field>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + { + eval_multiply_helper(result, a, val); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2> + inline typename enable_if_c >::value && + !is_trivial_montgomery_int >::value && + is_equal_montgomery_int_backend>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + { + eval_multiply_helper(result, a, val); + } + +// +// Now over again for trivial cpp_int's: +// + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_trivial_montgomery_int>::value + && (is_signed_number>::value + || is_signed_number>::value) && + is_equal_montgomery_int_field>::value + >::type + eval_multiply( + montgomery_int_backend& result, + const Backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + eval_multiply_helper(result, o); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_trivial_montgomery_int>::value + && (is_signed_number>::value + || is_signed_number>::value) && + is_equal_montgomery_int_backend>::value> + ::type eval_multiply( + montgomery_int_backend& result, + const Backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + + { + eval_multiply_helper(result, o); + } + + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int >::value + && is_unsigned_number >::value + && is_trivial_montgomery_int >::value + && is_unsigned_number >::value + && is_equal_montgomery_int_field>::value + >::type + eval_multiply( + montgomery_int_backend& result, + const Backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, o); + } + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int >::value + && is_unsigned_number >::value + && is_trivial_montgomery_int >::value + && is_unsigned_number >::value + && is_equal_montgomery_int_backend>::value + >::type + eval_multiply( + montgomery_int_backend& result, + const Backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, o); + } + + /*! + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_trivial_montgomery_int >::value + && (is_signed_number >::value + || is_signed_number>::value) + >::type + eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const Backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, a, b); + } + + emplate class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_trivial_montgomery_int >::value + && (is_signed_number >::value + || is_signed_number>::value) + >::type + eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const Backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, a, b); + } + + emplate class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_trivial_montgomery_int >::value + && (is_signed_number >::value + || is_signed_number>::value) + >::type + eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const Backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, a, b); + } + + emplate class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_trivial_montgomery_int >::value + && (is_signed_number >::value + || is_signed_number>::value) + >::type + eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const Backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int >::value)) + { + eval_multiply_helper(result, a, b); + } + ----------- + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1> + BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_montgomery_int>::value + && is_unsigned_number>::value + && is_trivial_montgomery_int>::value + && is_unsigned_number>::value + >::type + eval_multiply( + montgomery_int_backend& result, + const Backend& a, + const Backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_montgomery_int>::value)) + { + eval_multiply_helper(result, a, b); + } + + + template class Backend, + unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, + class Allocator1, typename ParamsBackend1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, + class Allocator2, typename ParamsBackend2> + + BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int >::value + && is_trivial_montgomery_int >::value + && is_trivial_montgomery_int>::value + >::type + eval_multiply( + montgomery_int_backend& result, + Backend const& a, + Backend const& b) + { + eval_multiply_helper(result, a, b); + } + + */ +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + } + } +} // namespaces + +#endif \ No newline at end of file diff --git a/include/boost/multiprecision/montgomery_int/reduce.hpp b/include/boost/multiprecision/montgomery_int/reduce.hpp new file mode 100644 index 000000000..58bef4cdd --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/reduce.hpp @@ -0,0 +1,113 @@ +#include + +#include +#include +#include +#include +#include + +//#include +//#include + +#ifndef CRYPTO3_MP_MONTGOMERY_INT_REDC_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_REDC_HPP + +namespace boost { + namespace multiprecision { + namespace backends { + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) // conditional expression is constant +#endif + template + inline void redc(MontgomeryBackend &result) BOOST_MP_NOEXCEPT_IF ( + is_non_throwing_montgomery_int::value) { + + using default_ops::eval_multiply_add; + using default_ops::eval_lt; + + typedef cpp_int_backend cpp_three_int_backend; + typename MontgomeryBackend::allocator_type alloc; + + const size_t p_size = result.m_params.p_words(); + const limb_type p_dash = result.m_params.p_dash(); + const size_t z_size = 2 * (result.m_params.p_words() + 1); + + + container::vector z(result.size(), 0); + + eval_export_bits(result, z.rbegin(), MontgomeryBackend::limb_bits); + + z.resize(z_size, 0); + + if (result.size() < z_size) { + result.resize(z_size, z_size); + } + + cpp_three_int_backend w(z[0]); + + result.limbs()[0] = w.limbs()[0] * p_dash; + + eval_multiply_add(w, result.limbs()[0], result.m_params.p().backend().limbs()[0]); + eval_right_shift(w, MontgomeryBackend::limb_bits); + + for (size_t i = 1; i != p_size; ++i) { + for (size_t j = 0; j < i; ++j) { + eval_multiply_add(w, result.limbs()[j], result.m_params.p().backend().limbs()[i - j]); + } + + eval_add(w, z[i]); + + result.limbs()[i] = w.limbs()[0] * p_dash; + + eval_multiply_add(w, result.limbs()[i], result.m_params.p().backend().limbs()[0]); + + eval_right_shift(w, MontgomeryBackend::limb_bits); + } + + for (size_t i = 0; i != p_size; ++i) { + for (size_t j = i + 1; j != p_size; ++j) { + eval_multiply_add(w, result.limbs()[j], result.m_params.p().backend().limbs()[p_size + i - j]); + } + + eval_add(w, z[p_size + i]); + + result.limbs()[i] = w.limbs()[0]; + + eval_right_shift(w, MontgomeryBackend::limb_bits); + } + + eval_add(w, z[z_size - 1]); + + result.limbs()[p_size] = w.limbs()[0]; + result.limbs()[p_size + 1] = w.limbs()[1]; + + + if (result.size() != p_size + 1) { + result.resize(p_size + 1, p_size + 1); + } + result.normalize(); + + //if (!eval_lt(result, result.m_params.p().backend())) { + //eval_subtract(result, result.m_params.p().backend()); + //} + + + //nil::crypto3::ct::conditional_copy_mem(borrow, result.limbs(), ws.begin(), ws.begin() + (result.m_params.p_words() + 1), (result.m_params.p_words() + 1)); + //clear_mem(result.m_params.limbs() + result.m_params.p_words(), z_size - result.m_params.p_words() - 2); + + // This check comes after we've used it but that's ok here + //nil::crypto3::ct::unpoison(&borrow, 1); + + } + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + } + } +} // namespaces + +#endif \ No newline at end of file diff --git a/include/boost/multiprecision/montgomery_int/serialize.hpp b/include/boost/multiprecision/montgomery_int/serialize.hpp new file mode 100644 index 000000000..442ee9bc0 --- /dev/null +++ b/include/boost/multiprecision/montgomery_int/serialize.hpp @@ -0,0 +1,201 @@ +#ifndef CRYPTO3_MP_MONTGOMERY_INT_SERIALIZE_HPP +#define CRYPTO3_MP_MONTGOMERY_INT_SERIALIZE_HPP + +namespace boost { + + namespace archive { + + class binary_oarchive; + + class binary_iarchive; + + } + + namespace serialization { + + namespace mp = boost::multiprecision; + + namespace montgomery_int_detail { + + using namespace boost::multiprecision; + using namespace boost::multiprecision::backends; + + template + struct is_binary_archive : public mpl::false_ { + }; + template<> + struct is_binary_archive : public mpl::true_ { + }; + template<> + struct is_binary_archive : public mpl::true_ { + }; + +// +// We have 8 serialization methods to fill out (and test), they are all permutations of: +// Load vs Store. +// Trivial or non-trivial cpp_int type. +// Binary or not archive. +// + template + void do_serialize(Archive &ar, Int &val, mpl::false_ const &, mpl::false_ const &, mpl::false_ const &) { + // Load. + // Non-trivial. + // Non binary. + + bool s; + ar & s; + std::size_t limb_count; + std::size_t byte_count; + ar & byte_count; + limb_count = byte_count / sizeof(limb_type) + ((byte_count % sizeof(limb_type)) ? 1 : 0); + val.resize(limb_count, limb_count); + limb_type *pl = val.limbs(); + for (std::size_t i = 0; i < limb_count; ++i) { + pl[i] = 0; + for (std::size_t j = 0; (j < sizeof(limb_type)) && byte_count; ++j) { + unsigned char byte; + ar & byte; + pl[i] |= static_cast(byte) << (j * CHAR_BIT); + --byte_count; + } + } + if (s != val.sign()) { + val.negate(); + } + val.normalize(); + } + + template + void do_serialize(Archive &ar, Int &val, mpl::true_ const &, mpl::false_ const &, mpl::false_ const &) { + // Store. + // Non-trivial. + // Non binary. + + bool s = val.sign(); + ar & s; + limb_type *pl = val.limbs(); + std::size_t limb_count = val.size(); + std::size_t byte_count = limb_count * sizeof(limb_type); + ar & byte_count; + + for (std::size_t i = 0; i < limb_count; ++i) { + limb_type l = pl[i]; + for (std::size_t j = 0; j < sizeof(limb_type); ++j) { + unsigned char byte = static_cast((l >> (j * CHAR_BIT)) & ((1u << CHAR_BIT) - 1)); + ar & byte; + } + } + } + + template + void do_serialize(Archive &ar, Int &val, mpl::false_ const &, mpl::true_ const &, mpl::false_ const &) { + // Load. + // Trivial. + // Non binary. + bool s; + typename Int::local_limb_type l = 0; + ar & s; + std::size_t byte_count; + ar & byte_count; + for (std::size_t i = 0; i < byte_count; ++i) { + unsigned char b; + ar & b; + l |= static_cast(b) << (i * CHAR_BIT); + } + *val.limbs() = l; + if (s != val.sign()) { + val.negate(); + } + } + + template + void do_serialize(Archive &ar, Int &val, mpl::true_ const &, mpl::true_ const &, mpl::false_ const &) { + // Store. + // Trivial. + // Non binary. + bool s = val.sign(); + typename Int::local_limb_type l = *val.limbs(); + ar & s; + std::size_t limb_count = sizeof(l); + ar & limb_count; + for (std::size_t i = 0; i < limb_count; ++i) { + unsigned char b = static_cast( + static_cast(l >> (i * CHAR_BIT)) & + static_cast((1u << CHAR_BIT) - 1)); + ar & b; + } + } + + template + void do_serialize(Archive &ar, Int &val, mpl::false_ const &, mpl::false_ const &, mpl::true_ const &) { + // Load. + // Non-trivial. + // Binary. + bool s; + std::size_t c; + ar & s; + ar & c; + val.resize(c, c); + ar.load_binary(val.limbs(), c * sizeof(limb_type)); + if (s != val.sign()) { + val.negate(); + } + val.normalize(); + } + + template + void do_serialize(Archive &ar, Int &val, mpl::true_ const &, mpl::false_ const &, mpl::true_ const &) { + // Store. + // Non-trivial. + // Binary. + bool s = val.sign(); + std::size_t c = val.size(); + ar & s; + ar & c; + ar.save_binary(val.limbs(), c * sizeof(limb_type)); + } + + template + void do_serialize(Archive &ar, Int &val, mpl::false_ const &, mpl::true_ const &, mpl::true_ const &) { + // Load. + // Trivial. + // Binary. + bool s; + ar & s; + ar.load_binary(val.limbs(), sizeof(*val.limbs())); + if (s != val.sign()) { + val.negate(); + } + } + + template + void do_serialize(Archive &ar, Int &val, mpl::true_ const &, mpl::true_ const &, mpl::true_ const &) { + // Store. + // Trivial. + // Binary. + bool s = val.sign(); + ar & s; + ar.save_binary(val.limbs(), sizeof(*val.limbs())); + } + + } + + template< + typename Archive, unsigned MinBits, unsigned MaxBits, mp::cpp_integer_type SignType, mp::cpp_int_check_type Checked, + class Allocator, typename ParamsBackend> + void serialize(Archive &ar, mp::montgomery_int_backend &val, + const unsigned int /*version*/) { + + typedef typename Archive::is_saving save_tag; + typedef mpl::bool_ >::value> trivial_tag; + typedef typename montgomery_int_detail::is_binary_archive::type binary_tag; + + // Just dispatch to the correct method: + montgomery_int_detail::do_serialize(ar, val, save_tag(), trivial_tag(), binary_tag()); + } + + } +} // namespaces + +#endif // CRYPTO3_MP_MONTGOMERY_INT_SERIALIZE_HPP \ No newline at end of file diff --git a/include/boost/multiprecision/montgomery_inverse.hpp b/include/boost/multiprecision/montgomery_inverse.hpp new file mode 100644 index 000000000..4e26c5711 --- /dev/null +++ b/include/boost/multiprecision/montgomery_inverse.hpp @@ -0,0 +1,114 @@ +#ifndef CRYPTO3_MONTGOMERY_INVERSE_HPP +#define CRYPTO3_MONTGOMERY_INVERSE_HPP + +#include + +namespace nil { + namespace crypto3 { + template + inline Backend eval_almost_montgomery_inverse(Backend &result, const Backend &a, const Backend &b) { + typedef typename default_ops::double_precision_type::type double_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + + using default_ops::eval_is_zero; + using default_ops::eval_lt; + using default_ops::eval_gt; + using default_ops::eval_eq; + using default_ops::eval_get_sign; + using default_ops::eval_integer_modulus; + using default_ops::eval_right_shift; + using default_ops::eval_left_shift; + + ui_type k = 0; + + Backend u = b, v = a, r = 0, s = 1; + + while (eval_gt(v, 0)) { + if (!(eval_integer_modulus(u, 2))) { + eval_right_shift(u, 1); + eval_left_shift(s, 1); + } else if (!eval_integer_modulus(v, 2)) { + eval_right_shift(v, 1); + eval_left_shift(r, 1); + } else if (eval_gt(u, v)) { + eval_subtract(u, v); + eval_right_shift(u, 1); + eval_add(r, s); + eval_left_shift(s, 1); + } else { + eval_subtract(v, u); + eval_right_shift(v, 1); + eval_add(s, r); + eval_left_shift(r, 1); + } + + ++k; + } + + if (!eval_lt(r, b)) { + eval_subtract(r, b); + } + + eval_subtract(result, b, r); + + return k; + } + + /*! + * @brief Sets result to a^-1 * 2^k mod a with n <= k <= 2n + * + * "The Montgomery Modular Inverse - Revisited" Çetin Koç, E. Savas + * https://citeseerx.ist.psu.edu/viewdoc/citations?doi=10.1.1.75.8377 + * + * A const time implementation of this algorithm is described in + * "Constant Time Modular Inversion" Joppe W. Bos + * http://www.joppebos.com/files/CTInversion.pdf + * + * @note Non-const time + * + * @param result + * @param a + * @param b + * @return a^-1 * 2^k mod b + */ + template + inline number almost_montgomery_inverse( + number &result, const number &a, + const number &b) { + return number( + eval_almost_montgomery_inverse(result.backend(), a.backend(), b.backend())); + } + + /** + * Call almost_montgomery_inverse and correct the result to a^-1 mod b + */ + template + inline Backend eval_normalized_montgomery_inverse(const Backend &a, const Backend &p) { + using default_ops::eval_integer_modulus; + using default_ops::eval_add; + using default_ops::eval_right_shift; + + Backend r, k = eval_almost_montgomery_inverse(r, a, p); + + for (size_t i = 0; i != k; ++i) { + if (eval_integer_modulus(r, 2)) { + eval_add(r, p); + } + eval_right_shift(r, 1); + } + + return r; + } + + /** + * @brief Call almost_montgomery_inverse and correct the result to a^-1 mod b + */ + template + inline number normalized_montgomery_inverse( + const number &a, const number &p) { + return number(eval_normalized_montgomery_inverse(a.backend(), p.backend())); + } + } +} + +#endif //CRYPTO3_MONTGOMERY_INVERSE_HPP \ No newline at end of file diff --git a/include/boost/multiprecision/pow_mod.hpp b/include/boost/multiprecision/pow_mod.hpp new file mode 100644 index 000000000..ad5e3ebdf --- /dev/null +++ b/include/boost/multiprecision/pow_mod.hpp @@ -0,0 +1,188 @@ +#ifndef CRYPTO3_POWER_MOD_H_ +#define CRYPTO3_POWER_MOD_H_ + +#include + +namespace nil { + namespace crypto3 { + + using namespace boost::multiprecision; + +/** +* Modular Exponentiator Interface +*/ + class modular_exponentiator { + public: + + virtual void set_base(const cpp_int &) = 0; + + virtual void set_exponent(const cpp_int &) = 0; + + virtual cpp_int execute() const = 0; + + virtual modular_exponentiator *copy() const = 0; + + modular_exponentiator() = default; + + modular_exponentiator(const modular_exponentiator &) = default; + + modular_exponentiator &operator=(const modular_exponentiator &) = default; + + virtual ~modular_exponentiator() = default; + }; + +/** +* Modular Exponentiator Proxy +*/ + class power_mod { + public: + + enum usage_hints { + NO_HINTS = 0x0000, + + BASE_IS_FIXED = 0x0001, BASE_IS_SMALL = 0x0002, BASE_IS_LARGE = 0x0004, BASE_IS_2 = 0x0008, + + EXP_IS_FIXED = 0x0100, EXP_IS_SMALL = 0x0200, EXP_IS_LARGE = 0x0400 + }; + +/* +* Try to choose a good window size +*/ + static size_t window_bits(size_t exp_bits, size_t base_bits, power_mod::usage_hints hints); + +/** +* @param modulus the modulus +* @param hints Passed to set_modulus if modulus > 0 +* @param disable_montgomery_arith Disables use of Montgomery +* representation. Likely only useful for testing. +*/ + void set_modulus(const cpp_int &modulus, usage_hints hints = NO_HINTS, + bool disable_montgomery_arith = false) const; + +/** +* Set the base +*/ + void set_base(const cpp_int &base) const; + +/** +* Set the exponent +*/ + void set_exponent(const cpp_int &exponent) const; + +/** +* All three of the above functions must have already been called. +* @return result of g^x%p +*/ + cpp_int execute() const; + + power_mod &operator=(const power_mod &); + +/** +* @param modulus Optionally call set_modulus +* @param hints Passed to set_modulus if modulus > 0 +* @param disable_montgomery_arith Disables use of Montgomery +* representation. Likely only useful for testing. +*/ + power_mod(const cpp_int &modulus = 0, usage_hints hints = NO_HINTS, bool disable_montgomery_arith = false); + + power_mod(const power_mod &); + + virtual ~power_mod() = default; + + private: + mutable std::unique_ptr m_core; + }; + +/** +* Fixed Exponent Modular Exponentiator Proxy +*/ + class fixed_exponent_power_mod final : public power_mod { + public: + + cpp_int operator()(const cpp_int &b) const { + set_base(b); + return execute(); + } + + fixed_exponent_power_mod() = default; + + fixed_exponent_power_mod(const cpp_int &exponent, const cpp_int &modulus, usage_hints hints = NO_HINTS); + + }; + +/** +* Fixed Base Modular Exponentiator Proxy +*/ + class fixed_base_power_mod final : public power_mod { + public: + + cpp_int operator()(const cpp_int &e) const { + set_exponent(e); + return execute(); + } + + fixed_base_power_mod() = default; + + fixed_base_power_mod(const cpp_int &base, const cpp_int &modulus, usage_hints hints = NO_HINTS); + + }; + + /** + * Modular exponentation + * @param base an integer base + * @param exp a positive exponent + * @param mod a positive modulus + * @return (b^x) % m + */ + template + inline Backend eval_power_mod(const Backend &base, const Backend &exp, const Backend &mod) { + using default_ops::eval_is_zero; + using default_ops::eval_lt; + using default_ops::eval_eq; + using default_ops::eval_integer_modulus; + using default_ops::eval_get_sign; + + if (eval_get_sign(mod) < 0 || eval_eq(mod, 1)) { + return 0; + } + + if (eval_is_zero(base) || eval_is_zero(mod)) { + if (eval_is_zero(exp)) { + return 1; + } + return 0; + } + + class power_mod pow_mod(mod); + + /* + * Calling set_base before set_exponent means we end up using a + * minimal window. This makes sense given that here we know that any + * precomputation is wasted. + */ + + if (eval_get_sign(base) < 0) { + pow_mod.set_base(-base); + pow_mod.set_exponent(exp); + if (!(eval_integer_modulus(exp, 2))) { + return pow_mod.execute(); + } else { + return (mod - pow_mod.execute()); + } + } else { + pow_mod.set_base(base); + pow_mod.set_exponent(exp); + return pow_mod.execute(); + } + } + + template + inline number power_mod(const number &base, + const number &exp, + const number &mod) { + return number(eval_power_mod(base.backend(), exp.backend(), mod.backend())); + } + } +} + +#endif diff --git a/include/boost/multiprecision/prime.hpp b/include/boost/multiprecision/prime.hpp new file mode 100644 index 000000000..99cfbaa57 --- /dev/null +++ b/include/boost/multiprecision/prime.hpp @@ -0,0 +1,363 @@ +#ifndef CRYPTO3_NUMBER_THEORY_H_ +#define CRYPTO3_NUMBER_THEORY_H_ + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +namespace nil { + namespace crypto3 { + + using namespace boost::multiprecision; + + namespace detail { + /* + * Check if this size is allowed by FIPS 186-3 + */ + bool fips186_3_valid_size(size_t pbits, size_t qbits) { + if (qbits == 160) { + return (pbits == 1024); + } + + if (qbits == 224) { + return (pbits == 2048); + } + + if (qbits == 256) { + return (pbits == 2048 || pbits == 3072); + } + + return false; + } + + /** + * The size of the PRIMES[] array + */ + const size_t PRIME_TABLE_SIZE = 6541; + + /** + * A const array of all primes less than 65535 + */ + extern const uint16_t PRIMES[]; + } + + /** + * Compute -input^-1 mod 2^MP_WORD_BITS. Returns zero if input + * is even. If input is odd, input and 2^n are relatively prime + * and an inverse exists. + */ + template + typename std::enable_if::value == number_kind_integer, Word>::type monty_inverse( + Word input) { + if (input == 0) { + BOOST_THROW_EXCEPTION(std::invalid_argument("monty_inverse: divide by zero")); + } + + Word b = input; + Word x2 = 1, x1 = 0, y2 = 0, y1 = 1; + + // First iteration, a = n+1 + Word q = bigint_divop(1, 0, b); + Word r = (MP_WORD_MAX - q * b) + 1; + Word x = x2 - q * x1; + Word y = y2 - q * y1; + + Word a = b; + b = r; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + + while (b > 0) { + q = a / b; + r = a - q * b; + x = x2 - q * x1; + y = y2 - q * y1; + + a = b; + b = r; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + + const Word check = y2 * input; + CRYPTO3_ASSERT_EQUAL(check, 1, "monty_inverse result is inverse of input"); + + // Now invert in addition space + y2 = (MP_WORD_MAX - y2) + 1; + + return y2; + } + + /** + * Randomly generate a prime + * @param rng a random number generator + * @param bits how large the resulting prime should be in bits + * @param coprime a positive integer that (prime - 1) should be coprime to + * @param equiv a non-negative number that the result should be + equivalent to modulo equiv_mod + * @param equiv_mod the modulus equiv should be checked against + * @param prob use test so false positive is bounded by 1/2**prob + * @return random prime with the specified criteria + */ + template + number random_prime(UniformRandomNumberGenerator &rng, size_t bits, + const number &coprime = 0, + std::size_t equiv = 1, std::size_t modulo = 2, + std::size_t prob = 128) { + if (coprime < 0) { + BOOST_THROW_EXCEPTION(std::invalid_argument("random_prime: coprime must be >= 0")); + } + if (modulo == 0) { + BOOST_THROW_EXCEPTION(std::invalid_argument("random_prime: Invalid modulo value")); + } + + equiv %= modulo; + + if (equiv == 0) { + BOOST_THROW_EXCEPTION(std::invalid_argument("random_prime Invalid value for equiv/modulo")); + } + + // Handle small values: + if (bits <= 1) { + BOOST_THROW_EXCEPTION( + std::invalid_argument("random_prime: Can't make a prime of " + std::to_string(bits) + " bits")); + } else if (bits == 2) { + return ((rng.next_byte() % 2) ? 2 : 3); + } else if (bits == 3) { + return ((rng.next_byte() % 2) ? 5 : 7); + } else if (bits == 4) { + return ((rng.next_byte() % 2) ? 11 : 13); + } else if (bits <= 16) { + for (;;) { + size_t idx = make_uint16(rng.next_byte(), rng.next_byte()) % detail::PRIME_TABLE_SIZE; + uint16_t small_prime = detail::PRIMES[idx]; + + if (high_bit(small_prime) == bits) { + return small_prime; + } + } + } + + secure_vector sieve(detail::PRIME_TABLE_SIZE); + const size_t MAX_ATTEMPTS = 32 * 1024; + + while (true) { + cpp_int p(rng, bits); + + // Force lowest and two top bits on + bit_set(p, bits - 1); + bit_set(p, bits - 2); + bit_set(p, 0); + + // Force p to be equal to equiv mod modulo + p += (modulo - (p % modulo)) + equiv; + + for (size_t i = 0; i != sieve.size(); ++i) { + sieve[i] = static_cast(p % detail::PRIMES[i]); + } + + size_t counter = 0; + while (true) { + ++counter; + + if (counter > MAX_ATTEMPTS) { + break; // don't try forever, choose a new starting point + } + + p += modulo; + + if (msb(p) > bits) { + break; + } + + // Now that p is updated, update the sieve + for (size_t i = 0; i != sieve.size(); ++i) { + sieve[i] = (sieve[i] + modulo) % detail::PRIMES[i]; + } + + bool passes_sieve = true; + for (size_t i = 0; passes_sieve && (i != sieve.size()); ++i) { + /* + In this case, p is a multiple of PRIMES[i] + */ + if (sieve[i] == 0) { + passes_sieve = false; + } + + /* + In this case, 2*p+1 will be a multiple of PRIMES[i] + + So if generating a safe prime, we want to avoid this value + because 2*p+1 will not be useful. Since the check is cheap to + do and doesn't seem to affect the overall distribution of the + generated primes overmuch it's used in all cases. + + See "Safe Prime Generation with a Combined Sieve" M. Wiener + https://eprint.iacr.org/2003/186.pdf + */ + if (sieve[i] == (detail::PRIMES[i] - 1) / 2) { + passes_sieve = false; + } + } + + if (!passes_sieve) { + continue; + } + + if (coprime > 0 && gcd(p - 1, coprime) != 1) { + continue; + } + + if (miller_rabin_test(p, prob, rng)) { + return p; + } + } + } + } + + /** + * Return a 'safe' prime, of the form p=2*q+1 with q prime + * @param rng a random number generator + * @param bits is how long the resulting prime should be + * @return prime randomly chosen from safe primes of length bits + */ + template + number random_safe_prime(UniformRandomNumberGenerator &rng, std::size_t bits) { + if (bits <= 64) { + BOOST_THROW_EXCEPTION(std::invalid_argument( + "random_safe_prime: Can't make a prime of " + std::to_string(bits) + " bits")); + } + + cpp_int q, p; + for (;;) { + /* + Generate q == 2 (mod 3) + + Otherwise [q == 1 (mod 3) case], 2*q+1 == 3 (mod 3) and not prime. + */ + q = random_prime(rng, bits - 1, 1, 2, 3, 8); + p = (q << 1) + 1; + + if (miller_rabin_test(p, 128, rng)) { + // We did only a weak check before, go back and verify q before returning + if (miller_rabin_test(q, 128, rng)) { + return p; + } + } + + } + } + + /** + * @brief Generate DSA parameters using the FIPS 186 kosherizer + * + * @tparam Hasher + * @tparam UniformRandomNumberGenerator + * + * @param rng a random number generator + * @param p_out where the prime p will be stored + * @param q_out where the prime q will be stored + * @param pbits how long p will be in bits + * @param qbits how long q will be in bits + * @param seed_c the seed used to generate the parameters + * @param offset optional offset from seed to start searching at + * @return true if seed generated a valid DSA parameter set, otherwise + false. p_out and q_out are only valid if true was returned. + */ + template class hash::sha, std::size_t PBits, std::size_t QBits, + typename Backend, expression_template_option ExpressionTemplates, typename UniformRandomNumberGenerator> + bool generate_dsa_primes(number &q_out, const std::vector &seed_c, + size_t offset = 0, UniformRandomNumberGenerator &rng, Hasher &hasher) { + if (!detail::fips186_3_valid_size(PBits, QBits)) { + BOOST_THROW_EXCEPTION(std::invalid_argument( + "FIPS 186-3 does not allow DSA domain parameters of " + std::to_string(PBits) + "/" + + std::to_string(QBits) + " bits long")); + } + + if (seed_c.size() * 8 < QBits) { + BOOST_THROW_EXCEPTION(std::invalid_argument( + "Generating a DSA parameter set with a " + std::to_string(QBits) + + " bit long q requires a seed at least as many bits long")); + } + + const std::string hash_name = "SHA-" + std::to_string(QBits); + std::unique_ptr hash(HashFunction::create_or_throw(hash_name)); + + const size_t HASH_SIZE = hash->output_length(); + + class Seed final { + public: + explicit Seed(const std::vector &s) : m_seed(s) { + } + + const std::vector &value() const { + return m_seed; + } + + Seed &operator++() { + for (size_t j = m_seed.size(); j > 0; --j) { + if (++m_seed[j - 1]) { + break; + } + } + return (*this); + } + + private: + std::vector m_seed; + }; + + Seed seed(seed_c); + + q_out.binary_decode(hash->process(seed.value())); + bit_set(q_out, QBits - 1); + bit_set(q_out, 0); + + if (!miller_rabin_test(q_out, 126, rng)) { + return false; + } + + const size_t n = (PBits - 1) / (HASH_SIZE * 8), b = (PBits - 1) % (HASH_SIZE * 8); + + cpp_int X; + std::vector V(HASH_SIZE * (n + 1)); + + for (size_t j = 0; j != 4 * PBits; ++j) { + for (size_t k = 0; k <= n; ++k) { + ++seed; + hash->update(seed.value()); + hash->final(&V[HASH_SIZE * (n - k)]); + } + + if (j >= offset) { + X.binary_decode(&V[HASH_SIZE - 1 - b / 8], V.size() - (HASH_SIZE - 1 - b / 8)); + bit_set(X, PBits - 1); + + p_out = X - (X % (2 * q_out) - 1); + + if (p_out.bits() == PBits && miller_rabin_test(p_out, 126, rng)) { + return true; + } + } + } + return false; + } + } +} + +#endif \ No newline at end of file diff --git a/include/boost/multiprecision/reduce_below.hpp b/include/boost/multiprecision/reduce_below.hpp new file mode 100644 index 000000000..68cc8d3e2 --- /dev/null +++ b/include/boost/multiprecision/reduce_below.hpp @@ -0,0 +1,29 @@ +#ifndef CRYPTO3_REDUCE_BELOW_HPP +#define CRYPTO3_REDUCE_BELOW_HPP + +namespace nil { + namespace crypto3 { + using namespace boost::multiprecision; + + template + void eval_reduce_below(Backend &val, const Backend &mod) { + using default_ops::eval_lt; + + if (eval_lt(mod, 0)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("reduce_below modulus must be positive")); + } + + while (eval_lt(mod, val)) { + eval_subtract(val, mod); + } + } + + template + number reduce_below(number &val, + const number &mod) { + return number(eval_reduce_below(val.backend(), mod.backend())); + } + } +} + +#endif //CRYPTO3_REDUCE_BELOW_HPP diff --git a/include/boost/multiprecision/ressol.hpp b/include/boost/multiprecision/ressol.hpp new file mode 100644 index 000000000..ff2644118 --- /dev/null +++ b/include/boost/multiprecision/ressol.hpp @@ -0,0 +1,114 @@ +#ifndef CRYPTO3_RESSOL_HPP +#define CRYPTO3_RESSOL_HPP + +#include +#include + +namespace nil { + namespace crypto3 { + /** + * Compute the square root of x modulo a prime using the + * Shanks-Tonnelli algorithm + * + * @param x the input + * @param p the prime + * @return y such that (y*y)%p == x, or -1 if no such integer + */ + template + inline Backend eval_ressol(const Backend &a, const Backend &p) { + using default_ops::eval_is_zero; + using default_ops::eval_lt; + using default_ops::eval_gt; + using default_ops::eval_eq; + using default_ops::eval_integer_modulus; + using default_ops::eval_subtract; + using default_ops::eval_get_sign; + using default_ops::eval_right_shift; + using default_ops::eval_bit_set; + using default_ops::eval_lsb; + + if (eval_is_zero(a)) { + return Backend(0); + } else if (eval_get_sign(a) < 0) { + BOOST_THROW_EXCEPTION(std::invalid_argument("ressol: value to solve for must be positive")); + } else if (!eval_lt(a, p)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("ressol: value to solve for must be less than p")); + } + + if (eval_eq(p, 2)) { + return a; + } else if (!eval_gt(p, 1)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("ressol: prime must be > 1 a")); + } else if (eval_integer_modulus(p, 2)) { + BOOST_THROW_EXCEPTION(std::invalid_argument("ressol: invalid prime")); + } + + if (eval_jacobi(a, p) != 1) { // not a quadratic residue + return Backend(-1); + } + + if (eval_integer_modulus(p, 4) == 3) { + return power_mod(a, ((p + 1) >> 2), p); + } + + size_t s = eval_lsb(p - 1); + + Backend q = p; + + eval_right_shift(p, s); + eval_subtract(q, 1); + eval_right_shift(q, 1); + + modular_reducer mod_p(p); + + Backend r = eval_power_mod(a, q, p); + Backend n = mod_p.multiply(a, mod_p.square(r)); + r = mod_p.multiply(r, a); + + if (eval_eq(n, 1)) { + return r; + } + + // find random non quadratic residue z + Backend z = 2; + while (eval_jacobi(z, p) == 1) { // while z quadratic residue + ++z; + } + + Backend c = eval_power_mod(z, (q << 1) + 1, p); + + while (eval_gt(n, 1)) { + q = n; + + size_t i = 0; + while (q != 1) { + q = mod_p.square(q); + ++i; + + if (i >= s) { + return -Backend(1); + } + } + + Backend p2; + eval_bit_set(p2, s - i - 1); + + c = power_mod(c, p2, p); + r = mod_p.multiply(r, c); + c = mod_p.square(c); + n = mod_p.multiply(n, c); + s = i; + } + + return r; + } + + template + inline number ressol(const number &a, + const number &p) { + return number(eval_ressol(a.backend(), p.backend())); + } + } +} + +#endif //CRYPTO3_RESSOL_HPP \ No newline at end of file diff --git a/test/zerg.cpp b/test/zerg.cpp new file mode 100644 index 000000000..8f846d119 --- /dev/null +++ b/test/zerg.cpp @@ -0,0 +1,32 @@ +// +// Created by Zerg1996 on 2019-04-27. +// + +//#include +#include +#include +#include +#include + + +int main() +{ + + using namespace boost::multiprecision; + using default_ops::eval_msb; + + cpp_int a(7); + nil::crypto3::montgomery_params tt(a); + std::cout << "-----" << std::endl; + //montgomery_int x(9299, tt); + //montgomery_int x2(1315541, tt); + montgomery_int x(3, tt); + std::cout << "X1:" << x << std::endl; + //montgomery_int x2(b, tt); + montgomery_int x2(6, tt); + std::cout << "X2:" << x2 << std::endl; + + x = x * x2; + std::cout << "Mult:" << x << std::endl; + return 0; +} From c33c1d216d433953a676309578eb9974fdb59ae6 Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Tue, 11 Jun 2019 20:37:04 +0300 Subject: [PATCH 002/294] Initial CMake build system implementation done #10 --- .gitmodules | 3 + CMakeLists.txt | 74 +++++ cmake/modules | 1 + test/CMakeLists.txt | 656 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 734 insertions(+) create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 160000 cmake/modules create mode 100644 test/CMakeLists.txt diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..9a8fc2247 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "cmake/modules"] + path = cmake/modules + url = https://github.com/BoostCMake/cmake_modules.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..12d120d2d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,74 @@ +cmake_minimum_required(VERSION 3.5) + +if(${CMAKE_WORKSPACE_NAME} STREQUAL boost) + find_package(CM) + include(CMDeploy) + include(CMSetupVersion) + + cm_project(multiprecision WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME}) + + find_package(${CMAKE_WORKSPACE_NAME}_core) + find_package(${CMAKE_WORKSPACE_NAME}_static_assert) + find_package(${CMAKE_WORKSPACE_NAME}_predef) + find_package(${CMAKE_WORKSPACE_NAME}_mpl) + find_package(${CMAKE_WORKSPACE_NAME}_random) + find_package(${CMAKE_WORKSPACE_NAME}_functional) + find_package(${CMAKE_WORKSPACE_NAME}_assert) + find_package(${CMAKE_WORKSPACE_NAME}_type_traits) + find_package(${CMAKE_WORKSPACE_NAME}_smart_ptr) + find_package(${CMAKE_WORKSPACE_NAME}_rational) + find_package(${CMAKE_WORKSPACE_NAME}_lexical_cast) + find_package(${CMAKE_WORKSPACE_NAME}_integer) + find_package(${CMAKE_WORKSPACE_NAME}_array) + find_package(${CMAKE_WORKSPACE_NAME}_config) + find_package(${CMAKE_WORKSPACE_NAME}_throw_exception) + find_package(${CMAKE_WORKSPACE_NAME}_math) + + cm_setup_version(VERSION 1.60.0) + + add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE) + set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME multiprecision) + + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::core) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::static_assert) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::predef) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::mpl) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::random) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::functional) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::assert) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::type_traits) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::smart_ptr) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::rational) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::lexical_cast) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::integer) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::array) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::config) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::throw_exception) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::math) + +else() + cm_workspace(boost) + + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/share/modules/cmake") + + include(CMConfig) + include(CMSetupVersion) + + cm_project(multiprecision WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME}) + + find_package(Boost COMPONENTS REQUIRED random) + + cm_setup_version(VERSION 1.60.0) + + add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE) + set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME multiprecision) + + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${Boost_LIBS}) + +endif() + +cm_deploy(TARGETS ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} + INCLUDE ${CURRENT_SOURCES_DIR}/include + NAMESPACE ${CMAKE_WORKSPACE_NAME}::) + +add_subdirectory(test) \ No newline at end of file diff --git a/cmake/modules b/cmake/modules new file mode 160000 index 000000000..9a55c6454 --- /dev/null +++ b/cmake/modules @@ -0,0 +1 @@ +Subproject commit 9a55c6454510b153c3f0bee32df38119ddbe3f69 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 000000000..328ee81fb --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,656 @@ +include(CMTest) + +find_package(${CMAKE_WORKSPACE_NAME}_algorithm) +find_package(${CMAKE_WORKSPACE_NAME}_chrono) +find_package(${CMAKE_WORKSPACE_NAME}_exception) +find_package(${CMAKE_WORKSPACE_NAME}_timer) +find_package(${CMAKE_WORKSPACE_NAME}_numeric_ublas) +find_package(${CMAKE_WORKSPACE_NAME}_filesystem) +find_package(${CMAKE_WORKSPACE_NAME}_test) +find_package(${CMAKE_WORKSPACE_NAME}_serialization) +find_package(${CMAKE_WORKSPACE_NAME}_numeric_interval) + +cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision + ${CMAKE_WORKSPACE_NAME}::algorithm + ${CMAKE_WORKSPACE_NAME}::chrono + ${CMAKE_WORKSPACE_NAME}::exception + ${CMAKE_WORKSPACE_NAME}::timer + ${CMAKE_WORKSPACE_NAME}::numeric_ublas + ${CMAKE_WORKSPACE_NAME}::filesystem + ${CMAKE_WORKSPACE_NAME}::test + ${CMAKE_WORKSPACE_NAME}::serialization + ${CMAKE_WORKSPACE_NAME}::numeric_interval + ) + +# copyright John Maddock 2011 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt. + +# HACK: Workaround broken includes +file(GLOB TEST_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/*.ipp) +foreach(HEADER ${TEST_HEADERS}) + configure_file(${HEADER} ${CURRENT_TEST_SOURCES_DIR}/include/libs/multiprecision/test/${HEADER} @ONLY) +endforeach() + +add_library(multiprecision_test_settings INTERFACE) +target_include_directories(multiprecision_test_settings INTERFACE ${CURRENT_TEST_SOURCES_DIR}/include) +cm_test_link_libraries(multiprecision_test_settings) + +# We set these to make it easier to set up and test GMP and MPFR under Win32: +# Speed up compiles: +# We can't yet enable this - it breaks the STL in some tests... +#msvc,off:-RTCc +#msvc,off:_ALLOW_RTCc_IN_STL + +# add_library(no_eh_support STATIC no_eh_test_support.cpp) +# cm_mark_as_test(no_eh_support) +# target_link_libraries(no_eh_support boost_throw_exception) +# cm_target_link_test_libs(no_eh_support) + +try_compile(HAS_GMP ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_gmp.cpp CMAKE_FLAGS + "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") +try_compile(HAS_MPFR ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfr.cpp CMAKE_FLAGS + "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") +try_compile(HAS_TOMMATH ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_tommath.cpp CMAKE_FLAGS + "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") +try_compile(HAS_FLOAT128 ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_float128.cpp) +try_compile(HAS_MPFI ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfi.cpp CMAKE_FLAGS + "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") +try_compile(HAS_INTEL_QUAD ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_intel_quad.cpp CMAKE_FLAGS + "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") + +cm_test(NAME multiprecision_test_test_arithmetic_backend_concept SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_backend_concept.cpp) + +cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_1.cpp) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_2.cpp) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_3.cpp) + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_1 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_arithmetic_cpp_bin_float_1.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_2 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_arithmetic_cpp_bin_float_2.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_3 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_arithmetic_cpp_bin_float_3.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) +endif() + +if(HAS_GMP) + cm_test(NAME multiprecision_test_test_arithmetic_mpf_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpf_50.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpf.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_mpz_rat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz_rat.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_mpz_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz_br.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_mpq SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpq.cpp) +endif() + +if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_arithmetic_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr_50.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_mpfr_50_static SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr_50_static.cpp) +endif() + +if(HAS_TOMMATH) + cm_test(NAME multiprecision_test_test_arithmetic_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_tommath_rat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath_rat.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_tommath_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath_br.cpp) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_2.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_3.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_4.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_5.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_6.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_7 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_7.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_8 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_8.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_9 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_9.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_10 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_10.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_11 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_11.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_12 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_12.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_13 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_13.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_14 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_14.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_15 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_15.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_16 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_16.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_17 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_17.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_18 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_18.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_br.cpp) +endif() + +cm_test(NAME multiprecision_test_test_arithmetic_ab_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_1.cpp) +cm_test(NAME multiprecision_test_test_arithmetic_ab_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_2.cpp) +cm_test(NAME multiprecision_test_test_arithmetic_ab_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_3.cpp) + +cm_test(NAME multiprecision_test_test_cpp_dec_float_round SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_round.cpp) + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_arithmetic_logged_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_1.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_logged_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_2.cpp) + + cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr1.cpp) + cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr2.cpp) +endif() + +if(HAS_MPFI) + cm_test(NAME multiprecision_test_test_arithmetic_mpfi_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfi_50.cpp) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_numeric_limits_backend_concept SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_backend_concept PUBLIC -DTEST_BACKEND) +endif() + +if(HAS_GMP) + cm_test(NAME multiprecision_test_test_numeric_limits_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_mpf50 PUBLIC -DTEST_MPF_50) + + cm_test(NAME multiprecision_test_test_numeric_limits_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_mpf PUBLIC -DTEST_MPF) + + cm_test(NAME multiprecision_test_test_numeric_limits_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_mpz PUBLIC -DTEST_MPZ) + + cm_test(NAME multiprecision_test_test_numeric_limits_mpq SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_mpq PUBLIC -DTEST_MPQ) +endif() + +if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_numeric_limits_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_mpfr PUBLIC -DTEST_MPFR) + + cm_test(NAME multiprecision_test_test_numeric_limits_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_mpfr_50 PUBLIC -DTEST_MPFR_50) +endif() + +if(HAS_GMP) + cm_test(NAME multiprecision_test_test_numeric_limits_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_cpp_dec_float PUBLIC -TDEST_CPP_DEC_FLOAT) + + cm_test(NAME multiprecision_test_test_numeric_limits_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) +endif() + +if(HAS_TOMMATH) + cm_test(NAME multiprecision_test_test_numeric_limits_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_tommath PUBLIC -DTEST_TOMMATH) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + cm_test(NAME multiprecision_test_test_numeric_limits_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_cpp_int PUBLIC -DTEST_CPP_INT) +endif() + +if(HAS_MPFI) + cm_test(NAME multiprecision_test_test_numeric_limits_mpfi_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_mpfi_50 PUBLIC -DTEST_MPFI_50) +endif() + +if(HAS_FLOAT128) + cm_test(NAME multiprecision_test_test_numeric_limits_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_float128 PUBLIC -DTEST_FLOAT128) +endif() + +if((HAS_INTEL_QUAD) AND (HAS_FLOAT128)) + cm_test(NAME multiprecision_test_test_numeric_limits_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) + target_compile_definitions(multiprecision_test_test_numeric_limits_intel_quad PUBLIC -DTEST_FLOAT128) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set(LOCAL_SOURCES "") + # TODO: fix test. Reason error: [-fpermissive] + set(LOCAL_SOURCES test_log.cpp test_pow.cpp test_sinh.cpp test_sqrt.cpp test_cosh.cpp test_tanh.cpp test_sin.cpp + test_tan.cpp test_asin.cpp test_atan.cpp test_fpclassify.cpp) + foreach(FILE ${LOCAL_SOURCES}) + get_filename_component(NAME ${FILE} NAME_WE) + if(HAS_GMP) + cm_test(NAME multiprecision_test_${NAME}_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) + endif() + if(HAS_MPFR) + cm_test(NAME multiprecision_test_${NAME}_mpfr50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_mpfr50 PUBLIC -DTEST_MPFR_50) + endif() + if(HAS_MPFI) + cm_test(NAME multiprecision_test_${NAME}_mpfi50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_mpfi50 PUBLIC -DTEST_MPFI_50) + endif() + + cm_test(NAME multiprecision_test_${FILE}_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${FILE}_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) + + cm_test(NAME multiprecision_test_${NAME}_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) + + if(HAS_FLOAT128) + cm_test(NAME multiprecision_test_${NAME}_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_float128 PUBLIC -DTEST_FLOAT128) + endif() + + if(HAS_INTEL_QUAD) + cm_test(NAME multiprecision_test_${NAME}_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_intel_quad PUBLIC -DTEST_FLOAT128) + endif() + endforeach() +endif() + +if(HAS_GMP) + cm_test(NAME multiprecision_test_test_gmp_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_gmp_conversions.cpp) +endif() + +if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_mpfr_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfr_conversions.cpp) +endif() + +if(HAS_GMP) + cm_test(NAME multiprecision_test_test_constants_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) + target_compile_definitions(multiprecision_test_test_constants_mpf50 PUBLIC -DTEST_MPF_50) +endif() + +if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_constants_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) + target_compile_definitions(multiprecision_test_test_constants_mpfr_50 PUBLIC -DTEST_MPFR_50) +endif() + +cm_test(NAME multiprecision_test_test_constants_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) +target_compile_definitions(multiprecision_test_test_constants_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) + +if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_move_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(multiprecision_test_test_move_mpfr PUBLIC -DTEST_MPFR) +endif() + +if(HAS_GMP) + cm_test(NAME multiprecision_test_test_move_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(multiprecision_test_test_move_gmp PUBLIC -DTEST_GMP) +endif() + +if(HAS_TOMMATH) + cm_test(NAME multiprecision_test_test_move_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(multiprecision_test_test_move_tommath PUBLIC -DTEST_TOMMATH) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_move_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(multiprecision_test_test_move_cpp_int PUBLIC -DTEST_CPP_INT) +endif() + +cm_test(NAME multiprecision_test_test_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_test.cpp) + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_cpp_int_lit SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_lit.cpp) +endif() + +if((HAS_FLOAT128) AND (HAS_INTEL_QUAD)) + cm_test(NAME multiprecision_test_test_constexpr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constexpr.cpp COMPILE_ONLY) + target_compile_definitions(multiprecision_test_test_constexpr PUBLIC -DHAVE_FLOAT128) +endif() + +cm_test(NAME multiprecision_test_test_nothrow_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_int.cpp COMPILE_ONLY) +cm_test(NAME multiprecision_test_test_nothrow_cpp_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_rational.cpp COMPILE_ONLY) + +cm_test(NAME multiprecision_test_test_nothrow_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_bin_float.cpp COMPILE_ONLY) +cm_test(NAME multiprecision_test_test_nothrow_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_dec_float.cpp COMPILE_ONLY) + + +if(HAS_FLOAT128) + cm_test(NAME multiprecision_test_test_nothrow_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_float128.cpp COMPILE_ONLY) +endif() + +if(HAS_GMP) + cm_test(NAME multiprecision_test_test_nothrow_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_gmp.cpp COMPILE_ONLY) +endif() + +if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_nothrow_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_mpfr.cpp COMPILE_ONLY) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_cpp_bin_float_io_1 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_cpp_bin_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_bin_float_io_1 PUBLIC -DTEST1 -DTEST_CPP_BIN_FLOAT) + + cm_test(NAME multiprecision_test_test_cpp_bin_float_io_2 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_cpp_bin_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_bin_float_io_2 PUBLIC -DTEST2 -DTEST_CPP_BIN_FLOAT) + + if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_cpp_bin_float SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_cpp_bin_float.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_bin_float PUBLIC -DTEST_MPFR) + endif() + + cm_test(NAME multiprecision_test_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) + + if(HAS_GMP) + cm_test(NAME multiprecision_test_test_float_io_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_float_io_mpf PUBLIC -DTEST_MPF_50) + endif() + + if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_float_io_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_float_io_mpfr PUBLIC -DTEST_MPFR_50) + endif() + + if(HAS_MPFI) + cm_test(NAME multiprecision_test_test_float_io_mpfi SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_float_io_mpfi PUBLIC -DTEST_MPFI_50) + endif() + + if(HAS_FLOAT128) + cm_test(NAME multiprecision_test_test_float_io_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_float_io_float128 PUBLIC -DTEST_FLOAT128) + endif() + + if((HAS_INTEL_QUAD) AND (HAS_FLOAT128)) + cm_test(NAME multiprecision_test_test_float_io_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_float_io_intel_quad PUBLIC -DTEST_FLOAT128) + endif() + + if(HAS_TOMMATH) + cm_test(NAME multiprecision_test_test_int_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_int_io_tommath PUBLIC -DTEST_TOMMATH) + endif() + + if(HAS_GMP) + cm_test(NAME multiprecision_test_test_int_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_int_io_mpz PUBLIC -DTEST_MPZ) + endif() + + cm_test(NAME multiprecision_test_test_int_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_int_io_cpp_int PUBLIC -DTEST_CPP_INT) + + if(HAS_GMP) + cm_test(NAME multiprecision_test_test_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_int_1 PUBLIC -DTEST1) + + cm_test(NAME multiprecision_test_test_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_int_2 PUBLIC -DTEST2) + + cm_test(NAME multiprecision_test_test_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_int_3 PUBLIC -DTEST2) + endif() +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_checked_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_checked_cpp_int.cpp) +endif() + +if(HAS_GMP) + cm_test(NAME multiprecision_test_test_miller_rabin SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_miller_rabin.cpp) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + if(HAS_TOMMATH) + cm_test(NAME multiprecision_test_test_rational_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) + target_compile_definitions(multiprecision_test_test_rational_io_tommath PUBLIC -DTEST_TOMMATH) + endif() + + if(HAS_GMP) + cm_test(NAME multiprecision_test_test_rational_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) + target_compile_definitions(multiprecision_test_test_rational_io_mpz PUBLIC -DTEST_MPQ) + endif() + + cm_test(NAME multiprecision_test_test_rational_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) + target_compile_definitions(multiprecision_test_test_rational_io_cpp_int PUBLIC -DTEST_CPP_INT) +endif() + +if((HAS_GMP) AND (HAS_TOMMATH) AND (HAS_MPFR)) + cm_test(NAME multiprecision_test_test_generic_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_generic_conv.cpp) + target_compile_definitions(multiprecision_test_test_generic_conv PUBLIC -DTEST_GMP -DTEST_TOMMATH -DTEST_MPFR) + +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_rat_float_interconv_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(multiprecision_test_test_rat_float_interconv_1 PUBLIC TEST1) + + cm_test(NAME multiprecision_test_test_rat_float_interconv_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(multiprecision_test_test_rat_float_interconv_2 PUBLIC TEST2) + + cm_test(NAME multiprecision_test_test_rat_float_interconv_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(multiprecision_test_test_rat_float_interconv_3 PUBLIC TEST3) + + cm_test(NAME multiprecision_test_test_rat_float_interconv_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(multiprecision_test_test_rat_float_interconv_4 PUBLIC TEST4) +endif() + +if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_rat_float_interconv_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(multiprecision_test_test_rat_float_interconv_5 PUBLIC -DTEST5) + + cm_test(NAME multiprecision_test_test_rat_float_interconv_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(multiprecision_test_test_rat_float_interconv_6 PUBLIC -DTEST6) + + cm_test(NAME multiprecision_test_test_rat_float_interconv_7 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(multiprecision_test_test_rat_float_interconv_7 PUBLIC -DTEST7) + + cm_test(NAME multiprecision_test_test_rat_float_interconv_8 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) + target_compile_definitions(multiprecision_test_test_rat_float_interconv_8 PUBLIC -DTEST8) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_cpp_int_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_conv.cpp) + cm_test(NAME multiprecision_test_test_native_integer SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_native_integer.cpp) + cm_test(NAME multiprecision_test_test_mixed_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_int.cpp) + + if((HAS_GMP) AND (HAS_MPFR)) + cm_test(NAME multiprecision_test_test_mixed_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_float.cpp) + endif() +endif() + +if(HAS_MPFR) + cm_test(NAME multiprecision_test_include_test_mpfr_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/mpfr_include_test.cpp COMPILE_ONLY) +endif() +if(HAS_GMP) + cm_test(NAME multiprecision_test_include_test_gmp_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/gmp_include_test.cpp COMPILE_ONLY) +endif() +if(HAS_TOMMATH) + cm_test(NAME multiprecision_test_include_test_tommath_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/tommath_include_test.cpp COMPILE_ONLY) +endif() +cm_test(NAME multiprecision_test_include_test_cpp_int_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/cpp_int_include_test.cpp COMPILE_ONLY) +cm_test(NAME multiprecision_test_include_test_cpp_dec_float_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/cpp_dec_float_include_test.cpp COMPILE_ONLY) +cm_test(NAME multiprecision_test_ublas_interopinclude_test_cpp_bin_float_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/cpp_bin_float_include_test.cpp COMPILE_ONLY) + +cm_test(NAME multiprecision_test_ublas_interop_test1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test1.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test11.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test12.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test13.cpp) + +cm_test(NAME multiprecision_test_ublas_interop_test2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test2.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test21.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test22.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test23.cpp) +#run ublas_interop/test3.cpp ublas_interop/test31.cpp ublas_interop/test32.cpp ublas_interop/test33.cpp ; +cm_test(NAME multiprecision_test_ublas_interop_test4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test4.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test42.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test43.cpp) +cm_test(NAME multiprecision_test_ublas_interop_test5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test5.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test52.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test53.cpp) +cm_test(NAME multiprecision_test_ublas_interop_test6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test6.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test62.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test63.cpp) +#run ublas_interop/test7.cpp ublas_interop/test71.cpp ublas_interop/test72.cpp ublas_interop/test73.cpp ; + +cm_test(NAME multiprecision_test_ublas_interop_test1_et SOURCES + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test1.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test11.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test12.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test13.cpp) +target_include_directories(multiprecision_test_ublas_interop_test1_et PUBLIC -DTEST_ET=1) +cm_test(NAME multiprecision_test_ublas_interop_test2_et SOURCES + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test2.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test21.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test22.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test23.cpp) +target_include_directories(multiprecision_test_ublas_interop_test2_et PUBLIC -DTEST_ET=1) +#run ublas_interop/test3.cpp ublas_interop/test31.cpp ublas_interop/test32.cpp ublas_interop/test33.cpp ; +cm_test(NAME multiprecision_test_ublas_interop_test4_et SOURCES + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test4.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test42.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test43.cpp) +target_include_directories(multiprecision_test_ublas_interop_test4_et PUBLIC -DTEST_ET=1) +cm_test(NAME multiprecision_test_ublas_interop_test5_et SOURCES + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test5.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test52.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test53.cpp) +target_include_directories(multiprecision_test_ublas_interop_test5_et PUBLIC -DTEST_ET=1) +cm_test(NAME multiprecision_test_ublas_interop_test6_et SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test6.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test62.cpp + ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test63.cpp) +target_include_directories(multiprecision_test_ublas_interop_test6_et PUBLIC -DTEST_ET=1) + +#run ublas_interop/test7.cpp ublas_interop/test71.cpp ublas_interop/test72.cpp ublas_interop/test73.cpp ; +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_cpp_int_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_int_serial_1 PUBLIC -DTEST1) + cm_test(NAME multiprecision_test_test_cpp_int_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_int_serial_2 PUBLIC -DTEST2) + cm_test(NAME multiprecision_test_test_cpp_int_serial_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_int_serial_3 PUBLIC -DTEST3) + cm_test(NAME multiprecision_test_test_cpp_int_serial_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + target_compile_definitions(multiprecision_test_test_cpp_int_serial_4 PUBLIC -DTEST4) + cm_test(NAME multiprecision_test_test_cpp_int_deserial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_deserial.cpp) + cm_test(NAME multiprecision_test_test_cpp_rat_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_rat_serial.cpp) + cm_test(NAME multiprecision_test_test_adapt_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_adapt_serial.cpp) + cm_test(NAME multiprecision_test_test_cpp_dec_float_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_serial.cpp) + target_compile_definitions(multiprecision_test_test_cpp_dec_float_serial_1 PUBLIC -DTEST1) + cm_test(NAME multiprecision_test_test_cpp_dec_float_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_serial.cpp) + target_compile_definitions(multiprecision_test_test_cpp_dec_float_serial_2 PUBLIC -DTEST2) +endif() + +if(HAS_FLOAT128) + cm_test(NAME multiprecision_test_test_float128_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float128_serial.cpp) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_bin_dec_float_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_serial.cpp) + target_compile_definitions(multiprecision_test_test_bin_dec_float_serial_1 PUBLIC TEST1) + + cm_test(NAME multiprecision_test_test_bin_dec_float_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_serial.cpp) + target_compile_definitions(multiprecision_test_test_bin_dec_float_serial_2 PUBLIC TEST2) + + cm_test(NAME multiprecision_test_test_checked_mixed_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_checked_mixed_cpp_int.cpp) + cm_test(NAME multiprecision_test_test_mixed_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_bin_float.cpp) + cm_test(NAME multiprecision_test_test_mixed_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_dec_float.cpp) +endif() + +if(HAS_GMP) + cm_test(NAME multiprecision_test_test_mixed_mpf_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_mpf_float.cpp) +endif() +if(HAS_MPFR) + cm_test(NAME multiprecision_test_test_mixed_mpfr_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_mpfr_float.cpp) +endif() + +file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/*.cpp) +# reason error: right operand of shift expression ‘(1u << 63u)’ is >= than the precision of the left operand [-fpermissive] +set(TEST_FILES "") + +foreach(FILEB ${TEST_FILES}) + get_filename_component(NAME ${FILEB} NAME_WE) + if(HAS_MPFR) + cm_test(NAME multiprecision_test_math_${NAME}_mpfr SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_mpfr PRIVATE -DTEST_MPFR_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_mpfr PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) + endif() + + if(HAS_GMP) + cm_test(NAME multiprecision_test_math_${NAME}_mpf SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_mpf PRIVATE -DTEST_MPF_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_mpf PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) + endif() + + cm_test(NAME multiprecision_test_math_${NAME}_cpp_dec_float SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_cpp_dec_float PRIVATE -DTEST_CPP_DEC_FLOAT -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_cpp_dec_float PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) + + cm_test(NAME multiprecision_test_math_${NAME}_cpp_bin_float SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_cpp_bin_float PRIVATE -DTEST_CPP_BIN_FLOAT -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_cpp_bin_float PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) + + if(HAS_FLOAT128) + cm_test(NAME multiprecision_test_math_${NAME}_float128 SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_float128 PRIVATE -DTEST_FLOAT128 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_float128 PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) + endif() + + if((HAS_FLOAT128) AND (HAS_INTEL_QUAD)) + cm_test(NAME multiprecision_test_math_${NAME}_intel_quad SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_intel_quad PRIVATE -DTEST_FLOAT128 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_intel_quad PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) + endif() +endforeach() + +file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/high_prec/*.cpp) +# reason error: right operand of shift expression ‘(1u << 63u)’ is >= than the precision of the left operand [-fpermissive] +list(REMOVE_ITEM TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/high_prec/test_gamma.cpp) + +foreach(FILEB ${TEST_FILES}) + get_filename_component(NAME ${FILEB} NAME_WE) + cm_test(NAME multiprecision_test_math_high_prec_${NAME} SOURCES ${FILEB}) + if(HAS_MPFR) + target_compile_definitions(multiprecision_test_math_high_prec_${NAME} PRIVATE -DTEST_MPFR) + endif() + target_compile_definitions(multiprecision_test_math_high_prec_${NAME} PRIVATE -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE -DBOOST_ALL_NO_LIB) + target_include_directories(multiprecision_test_math_high_prec_${NAME} PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) +endforeach() + +file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/compile_fail/*.cpp) +foreach(FILEB ${TEST_FILES}) + get_filename_component(NAME ${FILEB} NAME_WE) + cm_test(NAME multiprecision_test_compile_fail_${NAME} SOURCES ${FILEB} COMPILE_ONLY WILL_FAIL) + if(HAS_GMP) + target_compile_definitions(multiprecision_test_compile_fail_${NAME} PUBLIC -DTEST_GMP) + endif() + if(HAS_MPFR) + target_compile_definitions(multiprecision_test_compile_fail_${NAME} PUBLIC -DTEST_MPFR) + endif() +endforeach() + +file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/concepts/*.cpp) +foreach(FILEB ${TEST_FILES}) + get_filename_component(NAME ${FILEB} NAME_WE) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_50 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_50 PUBLIC -DTEST_MPFR_50) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_6 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_6 PUBLIC -DTEST_MPFR_6) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_15 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_15 PUBLIC -DTEST_MPFR_15) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_17 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_17 PUBLIC -DTEST_MPFR_17) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_30 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_30 PUBLIC -DTEST_MPFR_30) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpf50 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) + + cm_test(NAME multiprecision_test_concepts_${NAME}_cpp_dec_float SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) + + cm_test(NAME multiprecision_test_concepts_${NAME}_cpp_bin_float SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) + + cm_test(NAME multiprecision_test_concepts_${NAME}_cpp_dec_float_no_et SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_cpp_dec_float_no_et PUBLIC -DTEST_CPP_DEC_FLOAT_NO_ET) + + cm_test(NAME multiprecision_test_concepts_${NAME}_backend_concept SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_backend_concept PUBLIC -DTEST_BACKEND) + + cm_test(NAME multiprecision_test_concepts_${NAME}_logged_adaptor SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_logged_adaptor PUBLIC -DTEST_LOGGED_ADAPTER) +endforeach() + +include_directories(${CMAKE_WORKSPACE_SOURCES_DIR}) \ No newline at end of file From c75790c047cbb7c2179f4f71616323f6c08ed4e6 Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Tue, 11 Jun 2019 21:23:59 +0300 Subject: [PATCH 003/294] Minor build system configuration updates. --- CMakeLists.txt | 9 +++++--- test/CMakeLists.txt | 51 ++++++++++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12d120d2d..092180975 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,10 @@ cmake_minimum_required(VERSION 3.5) +set(BOOST_CMAKE FALSE) + if(${CMAKE_WORKSPACE_NAME} STREQUAL boost) + set(BOOST_CMAKE TRUE) + find_package(CM) include(CMDeploy) include(CMSetupVersion) @@ -47,7 +51,7 @@ if(${CMAKE_WORKSPACE_NAME} STREQUAL boost) target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::math) else() - cm_workspace(boost) + cm_workspace(boost SOURCES_DIR "${CMAKE_CURRENT_LIST_DIR}") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/share/modules/cmake") @@ -64,11 +68,10 @@ else() set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME multiprecision) target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${Boost_LIBS}) - endif() cm_deploy(TARGETS ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INCLUDE ${CURRENT_SOURCES_DIR}/include NAMESPACE ${CMAKE_WORKSPACE_NAME}::) -add_subdirectory(test) \ No newline at end of file +#add_subdirectory(test) \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 328ee81fb..ab446ec73 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,26 +1,35 @@ include(CMTest) -find_package(${CMAKE_WORKSPACE_NAME}_algorithm) -find_package(${CMAKE_WORKSPACE_NAME}_chrono) -find_package(${CMAKE_WORKSPACE_NAME}_exception) -find_package(${CMAKE_WORKSPACE_NAME}_timer) -find_package(${CMAKE_WORKSPACE_NAME}_numeric_ublas) -find_package(${CMAKE_WORKSPACE_NAME}_filesystem) -find_package(${CMAKE_WORKSPACE_NAME}_test) -find_package(${CMAKE_WORKSPACE_NAME}_serialization) -find_package(${CMAKE_WORKSPACE_NAME}_numeric_interval) - -cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision - ${CMAKE_WORKSPACE_NAME}::algorithm - ${CMAKE_WORKSPACE_NAME}::chrono - ${CMAKE_WORKSPACE_NAME}::exception - ${CMAKE_WORKSPACE_NAME}::timer - ${CMAKE_WORKSPACE_NAME}::numeric_ublas - ${CMAKE_WORKSPACE_NAME}::filesystem - ${CMAKE_WORKSPACE_NAME}::test - ${CMAKE_WORKSPACE_NAME}::serialization - ${CMAKE_WORKSPACE_NAME}::numeric_interval - ) +if(BOOST_CMAKE) + cm_find_package(${CMAKE_WORKSPACE_NAME}_algorithm) + cm_find_package(${CMAKE_WORKSPACE_NAME}_chrono) + cm_find_package(${CMAKE_WORKSPACE_NAME}_exception) + cm_find_package(${CMAKE_WORKSPACE_NAME}_timer) + cm_find_package(${CMAKE_WORKSPACE_NAME}_numeric_ublas) + cm_find_package(${CMAKE_WORKSPACE_NAME}_filesystem) + cm_find_package(${CMAKE_WORKSPACE_NAME}_test) + cm_find_package(${CMAKE_WORKSPACE_NAME}_serialization) + cm_find_package(${CMAKE_WORKSPACE_NAME}_numeric_interval) + + cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision + ${CMAKE_WORKSPACE_NAME}::algorithm + ${CMAKE_WORKSPACE_NAME}::chrono + ${CMAKE_WORKSPACE_NAME}::exception + ${CMAKE_WORKSPACE_NAME}::timer + ${CMAKE_WORKSPACE_NAME}::numeric_ublas + ${CMAKE_WORKSPACE_NAME}::filesystem + ${CMAKE_WORKSPACE_NAME}::test + ${CMAKE_WORKSPACE_NAME}::serialization + ${CMAKE_WORKSPACE_NAME}::numeric_interval + ) +else() + cm_find_package(Boost COMPONENTS chrono timer exception filesystem + unit_test_framework serialization) + + cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision + ${Boost_LIBS} + ) +endif() # copyright John Maddock 2011 # Distributed under the Boost Software License, Version 1.0. From af6c85dea6c4fbf46e6facd9c15e41d409bd2d35 Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Wed, 12 Jun 2019 17:01:28 +0300 Subject: [PATCH 004/294] Minor build configuration updates. --- CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 092180975..f73956c8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,7 +67,7 @@ else() add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE) set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME multiprecision) - target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${Boost_LIBS}) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${Boost_LIBRARIES}) endif() cm_deploy(TARGETS ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ab446ec73..f1e9cea6d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -27,7 +27,7 @@ else() unit_test_framework serialization) cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision - ${Boost_LIBS} + ${Boost_LIBRARIES} ) endif() From 628a714f24a901577e4bc3f470de111ff435e58c Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Thu, 13 Jun 2019 16:26:49 +0300 Subject: [PATCH 005/294] Minor build configuration updates #2 --- CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 092180975..f73956c8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,7 +67,7 @@ else() add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE) set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME multiprecision) - target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${Boost_LIBS}) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${Boost_LIBRARIES}) endif() cm_deploy(TARGETS ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ab446ec73..f1e9cea6d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -27,7 +27,7 @@ else() unit_test_framework serialization) cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision - ${Boost_LIBS} + ${Boost_LIBRARIES} ) endif() From 6d12d33b3106b10e584aba13c59f431db598274b Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Thu, 13 Jun 2019 23:23:44 +0300 Subject: [PATCH 006/294] Minor build configuration updates #2 --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f73956c8b..b6d101e2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,8 +51,6 @@ if(${CMAKE_WORKSPACE_NAME} STREQUAL boost) target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE ${CMAKE_WORKSPACE_NAME}::math) else() - cm_workspace(boost SOURCES_DIR "${CMAKE_CURRENT_LIST_DIR}") - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/share/modules/cmake") include(CMConfig) From ecadf0fd038cec3fcd7ac6d39bd5c3ce23b96967 Mon Sep 17 00:00:00 2001 From: Zerg1996 Date: Fri, 14 Jun 2019 23:33:12 +0300 Subject: [PATCH 007/294] Add modules include --- CMakeLists.txt | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f73956c8b..2a329165f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,12 +2,18 @@ cmake_minimum_required(VERSION 3.5) set(BOOST_CMAKE FALSE) -if(${CMAKE_WORKSPACE_NAME} STREQUAL boost) - set(BOOST_CMAKE TRUE) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake" + "${CMAKE_CURRENT_LIST_DIR}/cmake/packages" + "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/share/modules/cmake") + +include(CMDeploy) +include(CMConfig) +include(CMSetupVersion) - find_package(CM) - include(CMDeploy) - include(CMSetupVersion) +cm_setup_version(VERSION 1.70.0) + +if ("${CMAKE_WORKSPACE_NAME}" STREQUAL boost) + set(BOOST_CMAKE TRUE) cm_project(multiprecision WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME}) @@ -28,8 +34,6 @@ if(${CMAKE_WORKSPACE_NAME} STREQUAL boost) find_package(${CMAKE_WORKSPACE_NAME}_throw_exception) find_package(${CMAKE_WORKSPACE_NAME}_math) - cm_setup_version(VERSION 1.60.0) - add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE) set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME multiprecision) @@ -53,17 +57,10 @@ if(${CMAKE_WORKSPACE_NAME} STREQUAL boost) else() cm_workspace(boost SOURCES_DIR "${CMAKE_CURRENT_LIST_DIR}") - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/share/modules/cmake") - - include(CMConfig) - include(CMSetupVersion) - cm_project(multiprecision WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME}) find_package(Boost COMPONENTS REQUIRED random) - cm_setup_version(VERSION 1.60.0) - add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INTERFACE) set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME multiprecision) @@ -74,4 +71,4 @@ cm_deploy(TARGETS ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INCLUDE ${CURRENT_SOURCES_DIR}/include NAMESPACE ${CMAKE_WORKSPACE_NAME}::) -#add_subdirectory(test) \ No newline at end of file +#add_subdirectory(test) From fb74f79c99c7fb5648206fa0a40915b064219b04 Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Sat, 15 Jun 2019 02:15:18 +0300 Subject: [PATCH 008/294] Dependencies lookup initial implementation. --- cmake/packages/FindGMP.cmake | 76 +++++++++++++++++++++++++++++++ cmake/packages/FindQuadmath.cmake | 49 ++++++++++++++++++++ cmake/packages/FindTomMath.cmake | 26 +++++++++++ 3 files changed, 151 insertions(+) create mode 100644 cmake/packages/FindGMP.cmake create mode 100644 cmake/packages/FindQuadmath.cmake create mode 100644 cmake/packages/FindTomMath.cmake diff --git a/cmake/packages/FindGMP.cmake b/cmake/packages/FindGMP.cmake new file mode 100644 index 000000000..6d1eb5776 --- /dev/null +++ b/cmake/packages/FindGMP.cmake @@ -0,0 +1,76 @@ +# Try to find the GMP library +# https://gmplib.org/ +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(GMP 6.0.0) +# to require version 6.0.0 to newer of GMP. +# +# Once done this will define +# +# GMP_FOUND - system has GMP lib with correct version +# GMP_INCLUDES - the GMP include directory +# GMP_LIBRARIES - the GMP library +# GMP_VERSION - GMP version +# +# Copyright (c) 2016 Jack Poulson, +# Redistribution and use is allowed according to the terms of the BSD license. + +find_path(GMP_INCLUDES NAMES gmp.h PATHS $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR}) + +# Set GMP_FIND_VERSION to 5.1.0 if no minimum version is specified +if(NOT GMP_FIND_VERSION) + if(NOT GMP_FIND_VERSION_MAJOR) + set(GMP_FIND_VERSION_MAJOR 5) + endif() + if(NOT GMP_FIND_VERSION_MINOR) + set(GMP_FIND_VERSION_MINOR 1) + endif() + if(NOT GMP_FIND_VERSION_PATCH) + set(GMP_FIND_VERSION_PATCH 0) + endif() + set(GMP_FIND_VERSION + "${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}") +endif() + +message("GMP_INCLUDES=${GMP_INCLUDES}") +if(GMP_INCLUDES) + # Since the GMP version macros may be in a file included by gmp.h of the form + # gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them. + file(GLOB GMP_HEADERS "${GMP_INCLUDES}/gmp.h" "${GMP_INCLUDES}/gmp-*.h") + foreach(gmp_header_filename ${GMP_HEADERS}) + file(READ "${gmp_header_filename}" _gmp_version_header) + string(REGEX MATCH + "define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match + "${_gmp_version_header}") + if(_gmp_major_version_match) + set(GMP_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)" + _gmp_minor_version_match "${_gmp_version_header}") + set(GMP_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _gmp_patchlevel_version_match "${_gmp_version_header}") + set(GMP_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + set(GMP_VERSION + ${GMP_MAJOR_VERSION}.${GMP_MINOR_VERSION}.${GMP_PATCHLEVEL_VERSION}) + endif() + endforeach() + + # Check whether found version exists and exceeds the minimum requirement + if(NOT GMP_VERSION) + set(GMP_VERSION_OK FALSE) + message(STATUS "GMP version was not detected") + elseif(${GMP_VERSION} VERSION_LESS ${GMP_FIND_VERSION}) + set(GMP_VERSION_OK FALSE) + message(STATUS "GMP version ${GMP_VERSION} found in ${GMP_INCLUDES}, " + "but at least version ${GMP_FIND_VERSION} is required") + else() + set(GMP_VERSION_OK TRUE) + endif() +endif() + +find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GMP DEFAULT_MSG + GMP_INCLUDES GMP_LIBRARIES GMP_VERSION_OK) +mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES) \ No newline at end of file diff --git a/cmake/packages/FindQuadmath.cmake b/cmake/packages/FindQuadmath.cmake new file mode 100644 index 000000000..47ba2b589 --- /dev/null +++ b/cmake/packages/FindQuadmath.cmake @@ -0,0 +1,49 @@ +# Module that checks whether the compiler supports the +# quadruple precision floating point math +# +# Sets the following variables: +# HAVE_QUAD +# QUADMATH_LIBRARIES +# +# perform tests +include(CheckCSourceCompiles) +include(CheckCXXSourceCompiles) +include(CMakePushCheckState) +include(CheckCXXCompilerFlag) + +if(NOT DEFINED USE_QUADMATH OR USE_QUADMATH) + if(NOT DEFINED HAVE_EXTENDED_NUMERIC_LITERALS) + check_cxx_compiler_flag("-Werror -fext-numeric-literals" HAVE_EXTENDED_NUMERIC_LITERALS) + endif() + + if (HAVE_EXTENDED_NUMERIC_LITERALS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals") + endif() + + cmake_push_check_state(RESET) + list(APPEND CMAKE_REQUIRED_LIBRARIES "quadmath") + CHECK_CXX_SOURCE_COMPILES(" +#include + +int main(void){ + __float128 foo = sqrtq(123.456); + foo = FLT128_MIN; +}" QUADMATH_FOUND) + cmake_pop_check_state() + + if (QUADMATH_FOUND) + set(QUADMATH_LIBRARIES "quadmath") + set(HAVE_QUAD "${QUADMATH_FOUND}") + endif() +endif() + +if (USE_QUADMATH AND NOT QUADMATH_FOUND) + message(FATAL_ERROR "Quadruple precision math support was explicitly requested but is unavailable!") +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Quadmath + DEFAULT_MSG + QUADMATH_LIBRARIES + HAVE_QUAD + ) diff --git a/cmake/packages/FindTomMath.cmake b/cmake/packages/FindTomMath.cmake new file mode 100644 index 000000000..317276baf --- /dev/null +++ b/cmake/packages/FindTomMath.cmake @@ -0,0 +1,26 @@ +# - Try to find TomMath +# Once done, this will define +# +# TomMath_FOUND - system has TomMath +# TomMath_INCLUDE_DIRS - the TomMath include directories +# TomMath_LIBRARY - link these to use TomMath + +FIND_PATH(TomMath_INCLUDE_DIR tommath.h) + +SET(TomMath_NAMES ${TomMath_NAMES} tommath libtommath ) +FIND_LIBRARY(TomMath_LIBRARY NAMES ${TomMath_NAMES} ) + +# handle the QUIETLY and REQUIRED arguments and set TIFF_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + + + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(TomMath DEFAULT_MSG TomMath_LIBRARY TomMath_INCLUDE_DIR) + +IF(TOMMATH_FOUND) + set( TomMath_FOUND true ) + SET( TomMath_LIBRARIES ${TomMath_LIBRARY} ) +ENDIF(TOMMATH_FOUND) + +MARK_AS_ADVANCED(TomMath_INCLUDE_DIR TomMath_LIBRARY TomMath_FOUND) From e4b8509dab7aa7a50c3668d17d6503790db4dbb0 Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Sat, 15 Jun 2019 03:22:02 +0300 Subject: [PATCH 009/294] Minor module lookup implementation updates. --- cmake/packages/FindGMP.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/packages/FindGMP.cmake b/cmake/packages/FindGMP.cmake index 6d1eb5776..6315da43a 100644 --- a/cmake/packages/FindGMP.cmake +++ b/cmake/packages/FindGMP.cmake @@ -32,7 +32,6 @@ if(NOT GMP_FIND_VERSION) "${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}") endif() -message("GMP_INCLUDES=${GMP_INCLUDES}") if(GMP_INCLUDES) # Since the GMP version macros may be in a file included by gmp.h of the form # gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them. From b7374339991e6d7419ce8b1c6d4c4dcb727bdfb1 Mon Sep 17 00:00:00 2001 From: Zerg1996 Date: Sun, 16 Jun 2019 19:11:33 +0300 Subject: [PATCH 010/294] Implement find gmp,mpc,mpfir,mfpr #7 --- CMakeLists.txt | 2 +- cmake/packages/FindGMP.cmake | 6 +- cmake/packages/FindMPC.cmake | 66 +++ cmake/packages/FindMPFI.cmake | 87 ++++ cmake/packages/FindMPFR.cmake | 72 ++++ .../FindPackageHandleStandardArgs.cmake | 260 ++++++++++++ cmake/packages/FindQuadmath.cmake | 103 +++-- cmake/packages/FindTomMath.cmake | 1 + test/CMakeLists.txt | 380 +++++++++++++----- 9 files changed, 845 insertions(+), 132 deletions(-) create mode 100644 cmake/packages/FindMPC.cmake create mode 100644 cmake/packages/FindMPFI.cmake create mode 100644 cmake/packages/FindMPFR.cmake create mode 100644 cmake/packages/FindPackageHandleStandardArgs.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a329165f..49a5c37eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,4 +71,4 @@ cm_deploy(TARGETS ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INCLUDE ${CURRENT_SOURCES_DIR}/include NAMESPACE ${CMAKE_WORKSPACE_NAME}::) -#add_subdirectory(test) +add_subdirectory(test) diff --git a/cmake/packages/FindGMP.cmake b/cmake/packages/FindGMP.cmake index 6315da43a..4d6fd7a6c 100644 --- a/cmake/packages/FindGMP.cmake +++ b/cmake/packages/FindGMP.cmake @@ -69,7 +69,11 @@ endif() find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) -include(FindPackageHandleStandardArgs) +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args(GMP DEFAULT_MSG GMP_INCLUDES GMP_LIBRARIES GMP_VERSION_OK) +if (GMP_FOUND) + set(HAVE_GMP "${GMP_FOUND}") +endif() + mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES) \ No newline at end of file diff --git a/cmake/packages/FindMPC.cmake b/cmake/packages/FindMPC.cmake new file mode 100644 index 000000000..362fa9596 --- /dev/null +++ b/cmake/packages/FindMPC.cmake @@ -0,0 +1,66 @@ +# Try to find the MPC library +# See http://www.multiprecision.org/index.php?prog=mpc&page=home +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(MPC 1.0.3) +# to require version 1.0.3 to newer of MPC. +# +# Once done this will define +# +# MPC_FOUND - system has MPC lib with correct version +# MPC_INCLUDES - the MPC include directory +# MPC_LIBRARIES - the MPC library +# MPC_VERSION - MPC version + +find_path(MPC_INCLUDES NAMES mpc.h PATHS $ENV{GMPDIR} $ENV{MPFRDIR} $ENV{MPCDIR} + ${INCLUDE_INSTALL_DIR}) + +# Set MPC_FIND_VERSION to 1.0.0 if no minimum version is specified +if(NOT MPC_FIND_VERSION) + if(NOT MPC_FIND_VERSION_MAJOR) + set(MPC_FIND_VERSION_MAJOR 1) + endif() + if(NOT MPC_FIND_VERSION_MINOR) + set(MPC_FIND_VERSION_MINOR 0) + endif() + if(NOT MPC_FIND_VERSION_PATCH) + set(MPC_FIND_VERSION_PATCH 0) + endif() + set(MPC_FIND_VERSION + "${MPC_FIND_VERSION_MAJOR}.${MPC_FIND_VERSION_MINOR}.${MPC_FIND_VERSION_PATCH}") +endif() + +if(MPC_INCLUDES) + # Query MPC_VERSION + file(READ "${MPC_INCLUDES}/mpc.h" _mpc_version_header) + + string(REGEX MATCH "define[ \t]+MPC_VERSION_MAJOR[ \t]+([0-9]+)" + _mpc_major_version_match "${_mpc_version_header}") + set(MPC_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPC_VERSION_MINOR[ \t]+([0-9]+)" + _mpc_minor_version_match "${_mpc_version_header}") + set(MPC_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPC_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _mpc_patchlevel_version_match "${_mpc_version_header}") + set(MPC_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + + set(MPC_VERSION + ${MPC_MAJOR_VERSION}.${MPC_MINOR_VERSION}.${MPC_PATCHLEVEL_VERSION}) + + # Check whether found version exceeds minimum required + if(${MPC_VERSION} VERSION_LESS ${MPC_FIND_VERSION}) + set(MPC_VERSION_OK FALSE) + message(STATUS "MPC version ${MPC_VERSION} found in ${MPC_INCLUDES}, " + "but at least version ${MPC_FIND_VERSION} is required") + else() + set(MPC_VERSION_OK TRUE) + endif() +endif(MPC_INCLUDES) + +find_library(MPC_LIBRARIES mpc + PATHS $ENV{GMPDIR} $ENV{MPFRDIR} $ENV{MPCDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MPC DEFAULT_MSG + MPC_INCLUDES MPC_LIBRARIES MPC_VERSION_OK) +mark_as_advanced(MPC_INCLUDES MPC_LIBRARIES) diff --git a/cmake/packages/FindMPFI.cmake b/cmake/packages/FindMPFI.cmake new file mode 100644 index 000000000..b97161971 --- /dev/null +++ b/cmake/packages/FindMPFI.cmake @@ -0,0 +1,87 @@ +find_package( GMP QUIET ) +find_package( MPFR QUIET ) + +if( GMP_FOUND AND MPFR_FOUND ) + + if( MPFI_INCLUDES AND MPFI_LIBRARIES ) + set( MPFI_FOUND TRUE ) + endif( MPFI_INCLUDES AND MPFI_LIBRARIES ) + + find_path(MPFI_INCLUDES NAMES mpfi.h + HINTS ENV MPFI_INC_DIR + ENV MPFI_DIR + PATHS ${GMP_INCLUDE_DIR_SEARCH} + PATH_SUFFIXES include + DOC "The directory containing the MPFI header files" + ) + if(MPFI_INCLUDES) + file(READ "${MPFI_INCLUDES}/mpfi.h" _mpfr_version_header) + + string(REGEX MATCH "define[ \t]+MPFI_VERSION_MAJOR[ \t]+([0-9]+)" + _mpfr_major_version_match "${_mpfr_version_header}") + set(MPFI_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFI_VERSION_MINOR[ \t]+([0-9]+)" + _mpfr_minor_version_match "${_mpfr_version_header}") + set(MPFI_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFI_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _mpfr_patchlevel_version_match "${_mpfr_version_header}") + set(MPFI_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + + set(MPFI_VERSION + ${MPFI_MAJOR_VERSION}.${MPFI_MINOR_VERSION}.${MPFI_PATCHLEVEL_VERSION}) + endif() + + + find_library(MPFI_LIBRARIES NAMES mpfi + HINTS ENV MPFI_LIB_DIR + ENV MPFI_DIR + PATHS ${GMP_LIBRARIES_DIR_SEARCH} + PATH_SUFFIXES lib + DOC "Directory containing the MPFI library" + ) + + if( MPFI_LIBRARIES ) + get_filename_component(MPFI_LIBRARIES_DIR ${MPFI_LIBRARIES} PATH CACHE ) + endif( MPFI_LIBRARIES ) + + if( NOT MPFI_INCLUDES OR NOT MPFI_LIBRARIES_DIR ) + include( MPFIConfig OPTIONAL ) + endif( NOT MPFI_INCLUDES OR NOT MPFI_LIBRARIES_DIR ) + + include(FindPackageHandleStandardArgs) + + find_package_handle_standard_args( MPFI + "DEFAULT_MSG" + MPFI_LIBRARIES + MPFI_INCLUDES ) + +else( GMP_FOUND AND MPFR_FOUND ) + + message( STATUS "MPFI needs GMP and MPFR" ) + +endif( GMP_FOUND AND MPFR_FOUND ) + +if( MPFI_FOUND ) + if ("${MPFR_VERSION}" VERSION_LESS "4.0.0") + set(_MPFR_OLD TRUE) + endif() + + if ("${MPFI_VERSION}" VERSION_LESS "1.5.2") + set(_MPFI_OLD TRUE) + endif() + + if( ( _MPFR_OLD AND NOT _MPFI_OLD ) OR ( NOT _MPFR_OLD AND _MPFI_OLD ) ) + + message( + STATUS + "MPFI<1.5.2 requires MPFR<4.0.0; MPFI>=1.5.2 requires MPFR>=4.0.0" ) + + set( MPFI_FOUND FALSE ) + + else( ( _MPFR_OLD AND NOT _MPFI_OLD ) OR ( NOT _MPFR_OLD AND _MPFI_OLD ) ) + + set( MPFI_USE_FILE "CGAL_UseMPFI" ) + + endif( ( _MPFR_OLD AND NOT _MPFI_OLD ) OR ( NOT _MPFR_OLD AND _MPFI_OLD ) ) + +endif( MPFI_FOUND ) diff --git a/cmake/packages/FindMPFR.cmake b/cmake/packages/FindMPFR.cmake new file mode 100644 index 000000000..83e5bec51 --- /dev/null +++ b/cmake/packages/FindMPFR.cmake @@ -0,0 +1,72 @@ +# Try to find the MPFR library +# See http://www.mpfr.org/ +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(MPFR 2.3.0) +# to require version 2.3.0 to newer of MPFR. +# +# Once done this will define +# +# MPFR_FOUND - system has MPFR lib with correct version +# MPFR_INCLUDES - the MPFR include directory +# MPFR_LIBRARIES - the MPFR library +# MPFR_VERSION - MPFR version + +# Copyright (c) 2006, 2007 Montel Laurent, +# Copyright (c) 2008, 2009 Gael Guennebaud, +# Copyright (c) 2010 Jitse Niesen, +# Copyright (c) 2015 Jack Poulson, +# Redistribution and use is allowed according to the terms of the BSD license. + +find_path(MPFR_INCLUDES NAMES mpfr.h PATHS $ENV{GMPDIR} $ENV{MPFRDIR} + ${INCLUDE_INSTALL_DIR}) + +# Set MPFR_FIND_VERSION to 1.0.0 if no minimum version is specified +if(NOT MPFR_FIND_VERSION) + if(NOT MPFR_FIND_VERSION_MAJOR) + set(MPFR_FIND_VERSION_MAJOR 1) + endif() + if(NOT MPFR_FIND_VERSION_MINOR) + set(MPFR_FIND_VERSION_MINOR 0) + endif() + if(NOT MPFR_FIND_VERSION_PATCH) + set(MPFR_FIND_VERSION_PATCH 0) + endif() + set(MPFR_FIND_VERSION + "${MPFR_FIND_VERSION_MAJOR}.${MPFR_FIND_VERSION_MINOR}.${MPFR_FIND_VERSION_PATCH}") +endif() + +if(MPFR_INCLUDES) + # Query MPFR_VERSION + file(READ "${MPFR_INCLUDES}/mpfr.h" _mpfr_version_header) + + string(REGEX MATCH "define[ \t]+MPFR_VERSION_MAJOR[ \t]+([0-9]+)" + _mpfr_major_version_match "${_mpfr_version_header}") + set(MPFR_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFR_VERSION_MINOR[ \t]+([0-9]+)" + _mpfr_minor_version_match "${_mpfr_version_header}") + set(MPFR_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFR_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _mpfr_patchlevel_version_match "${_mpfr_version_header}") + set(MPFR_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + + set(MPFR_VERSION + ${MPFR_MAJOR_VERSION}.${MPFR_MINOR_VERSION}.${MPFR_PATCHLEVEL_VERSION}) + + # Check whether found version exceeds minimum required + if(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) + set(MPFR_VERSION_OK FALSE) + message(STATUS "MPFR version ${MPFR_VERSION} found in ${MPFR_INCLUDES}, " + "but at least version ${MPFR_FIND_VERSION} is required") + else() + set(MPFR_VERSION_OK TRUE) + endif() +endif() + +find_library(MPFR_LIBRARIES mpfr + PATHS $ENV{GMPDIR} $ENV{MPFRDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MPFR DEFAULT_MSG + MPFR_INCLUDES MPFR_LIBRARIES MPFR_VERSION_OK) +mark_as_advanced(MPFR_INCLUDES MPFR_LIBRARIES) \ No newline at end of file diff --git a/cmake/packages/FindPackageHandleStandardArgs.cmake b/cmake/packages/FindPackageHandleStandardArgs.cmake new file mode 100644 index 000000000..00b3c02a8 --- /dev/null +++ b/cmake/packages/FindPackageHandleStandardArgs.cmake @@ -0,0 +1,260 @@ +# FIND_PACKAGE_HANDLE_STANDARD_ARGS( ... ) +# +# This function is intended to be used in FindXXX.cmake modules files. +# It handles the REQUIRED, QUIET and version-related arguments to FIND_PACKAGE(). +# It also sets the _FOUND variable. +# The package is considered found if all variables ... listed contain +# valid results, e.g. valid filepaths. +# +# There are two modes of this function. The first argument in both modes is +# the name of the Find-module where it is called (in original casing). +# +# The first simple mode looks like this: +# FIND_PACKAGE_HANDLE_STANDARD_ARGS( (DEFAULT_MSG|"Custom failure message") ... ) +# If the variables to are all valid, then _FOUND +# will be set to TRUE. +# If DEFAULT_MSG is given as second argument, then the function will generate +# itself useful success and error messages. You can also supply a custom error message +# for the failure case. This is not recommended. +# +# The second mode is more powerful and also supports version checking: +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME [REQUIRED_VARS ...] +# [VERSION_VAR +# [CONFIG_MODE] +# [FAIL_MESSAGE "Custom failure message"] ) +# +# As above, if through are all valid, _FOUND +# will be set to TRUE. +# After REQUIRED_VARS the variables which are required for this package are listed. +# Following VERSION_VAR the name of the variable can be specified which holds +# the version of the package which has been found. If this is done, this version +# will be checked against the (potentially) specified required version used +# in the find_package() call. The EXACT keyword is also handled. The default +# messages include information about the required version and the version +# which has been actually found, both if the version is ok or not. +# Use the option CONFIG_MODE if your FindXXX.cmake module is a wrapper for +# a find_package(... NO_MODULE) call, in this case all the information +# provided by the config-mode of find_package() will be evaluated +# automatically. +# Via FAIL_MESSAGE a custom failure message can be specified, if this is not +# used, the default message will be displayed. +# +# Example for mode 1: +# +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR) +# +# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and +# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE. +# If it is not found and REQUIRED was used, it fails with FATAL_ERROR, +# independent whether QUIET was used or not. +# If it is found, success will be reported, including the content of . +# On repeated Cmake runs, the same message won't be printed again. +# +# Example for mode 2: +# +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON REQUIRED_VARS BISON_EXECUTABLE +# VERSION_VAR BISON_VERSION) +# In this case, BISON is considered to be found if the variable(s) listed +# after REQUIRED_VAR are all valid, i.e. BISON_EXECUTABLE in this case. +# Also the version of BISON will be checked by using the version contained +# in BISON_VERSION. +# Since no FAIL_MESSAGE is given, the default messages will be printed. +# +# Another example for mode 2: +# +# FIND_PACKAGE(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4) +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(Automoc4 CONFIG_MODE) +# In this case, FindAutmoc4.cmake wraps a call to FIND_PACKAGE(Automoc4 NO_MODULE) +# and adds an additional search directory for automoc4. +# The following FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper +# success/error message. + +#============================================================================= +# Copyright 2007-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +INCLUDE(FindPackageMessage) +INCLUDE(CMakeParseArguments) + +# internal helper macro +MACRO(_FPHSA_FAILURE_MESSAGE _msg) + IF (${_NAME}_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "${_msg}") + ELSE (${_NAME}_FIND_REQUIRED) + IF (NOT ${_NAME}_FIND_QUIETLY) + MESSAGE(STATUS "${_msg}") + ENDIF (NOT ${_NAME}_FIND_QUIETLY) + ENDIF (${_NAME}_FIND_REQUIRED) +ENDMACRO(_FPHSA_FAILURE_MESSAGE _msg) + + +# internal helper macro to generate the failure message when used in CONFIG_MODE: +MACRO(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) + # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: + IF(${_NAME}_CONFIG) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + ELSE(${_NAME}_CONFIG) + # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. + # List them all in the error message: + IF(${_NAME}_CONSIDERED_CONFIGS) + SET(configsText "") + LIST(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) + MATH(EXPR configsCount "${configsCount} - 1") + FOREACH(currentConfigIndex RANGE ${configsCount}) + LIST(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) + LIST(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) + SET(configsText "${configsText} ${filename} (version ${version})\n") + ENDFOREACH(currentConfigIndex) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}") + + ELSE(${_NAME}_CONSIDERED_CONFIGS) + # Simple case: No Config-file was found at all: + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") + ENDIF(${_NAME}_CONSIDERED_CONFIGS) + ENDIF(${_NAME}_CONFIG) +ENDMACRO(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) + + +FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) + + # set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in + # new extended or in the "old" mode: + SET(options CONFIG_MODE) + SET(oneValueArgs FAIL_MESSAGE VERSION_VAR) + SET(multiValueArgs REQUIRED_VARS) + SET(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) + LIST(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) + + IF(${INDEX} EQUAL -1) + SET(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) + SET(FPHSA_REQUIRED_VARS ${ARGN}) + SET(FPHSA_VERSION_VAR) + ELSE(${INDEX} EQUAL -1) + + CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) + + IF(FPHSA_UNPARSED_ARGUMENTS) + MESSAGE(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") + ENDIF(FPHSA_UNPARSED_ARGUMENTS) + + IF(NOT FPHSA_FAIL_MESSAGE) + SET(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") + ENDIF(NOT FPHSA_FAIL_MESSAGE) + ENDIF(${INDEX} EQUAL -1) + + # now that we collected all arguments, process them + + IF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG") + SET(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") + ENDIF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG") + + # In config-mode, we rely on the variable _CONFIG, which is set by find_package() + # when it successfully found the config-file, including version checking: + IF(FPHSA_CONFIG_MODE) + LIST(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) + LIST(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) + SET(FPHSA_VERSION_VAR ${_NAME}_VERSION) + ENDIF(FPHSA_CONFIG_MODE) + + IF(NOT FPHSA_REQUIRED_VARS) + MESSAGE(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") + ENDIF(NOT FPHSA_REQUIRED_VARS) + + LIST(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) + + STRING(TOUPPER ${_NAME} _NAME_UPPER) + STRING(TOLOWER ${_NAME} _NAME_LOWER) + + # collect all variables which were not found, so they can be printed, so the + # user knows better what went wrong (#6375) + SET(MISSING_VARS "") + SET(DETAILS "") + SET(${_NAME_UPPER}_FOUND TRUE) + # check if all passed variables are valid + FOREACH(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) + IF(NOT ${_CURRENT_VAR}) + SET(${_NAME_UPPER}_FOUND FALSE) + SET(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}") + ELSE(NOT ${_CURRENT_VAR}) + SET(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]") + ENDIF(NOT ${_CURRENT_VAR}) + ENDFOREACH(_CURRENT_VAR) + + + # version handling: + SET(VERSION_MSG "") + SET(VERSION_OK TRUE) + SET(VERSION ${${FPHSA_VERSION_VAR}} ) + IF (${_NAME}_FIND_VERSION) + + IF(VERSION) + + IF(${_NAME}_FIND_VERSION_EXACT) # exact version required + IF (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + SET(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + SET(VERSION_OK FALSE) + ELSE (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + SET(VERSION_MSG "(found suitable exact version \"${VERSION}\")") + ENDIF (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + + ELSE(${_NAME}_FIND_VERSION_EXACT) # minimum version specified: + IF ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + SET(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"") + SET(VERSION_OK FALSE) + ELSE ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + SET(VERSION_MSG "(found suitable version \"${VERSION}\", required is \"${${_NAME}_FIND_VERSION}\")") + ENDIF ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + ENDIF(${_NAME}_FIND_VERSION_EXACT) + + ELSE(VERSION) + + # if the package was not found, but a version was given, add that to the output: + IF(${_NAME}_FIND_VERSION_EXACT) + SET(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") + ELSE(${_NAME}_FIND_VERSION_EXACT) + SET(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") + ENDIF(${_NAME}_FIND_VERSION_EXACT) + + ENDIF(VERSION) + ELSE (${_NAME}_FIND_VERSION) + IF(VERSION) + SET(VERSION_MSG "(found version \"${VERSION}\")") + ENDIF(VERSION) + ENDIF (${_NAME}_FIND_VERSION) + + IF(VERSION_OK) + SET(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]") + ELSE(VERSION_OK) + SET(${_NAME_UPPER}_FOUND FALSE) + ENDIF(VERSION_OK) + + + # print the result: + IF (${_NAME_UPPER}_FOUND) + FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG}" "${DETAILS}") + ELSE (${_NAME_UPPER}_FOUND) + + IF(FPHSA_CONFIG_MODE) + _FPHSA_HANDLE_FAILURE_CONFIG_MODE() + ELSE(FPHSA_CONFIG_MODE) + IF(NOT VERSION_OK) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") + ELSE(NOT VERSION_OK) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}") + ENDIF(NOT VERSION_OK) + ENDIF(FPHSA_CONFIG_MODE) + + ENDIF (${_NAME_UPPER}_FOUND) + + SET(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE) + +ENDFUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _FIRST_ARG) \ No newline at end of file diff --git a/cmake/packages/FindQuadmath.cmake b/cmake/packages/FindQuadmath.cmake index 47ba2b589..620fd9728 100644 --- a/cmake/packages/FindQuadmath.cmake +++ b/cmake/packages/FindQuadmath.cmake @@ -1,49 +1,82 @@ -# Module that checks whether the compiler supports the -# quadruple precision floating point math +# Originally copied from the KDE project repository: +# http://websvn.kde.org/trunk/KDE/kdeutils/cmake/modules/FindGMP.cmake?view=markup&pathrev=675218 + +# Copyright (c) 2006, Laurent Montel, +# Copyright (c) 2008-2019 Francesco Biscani, + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: # -# Sets the following variables: -# HAVE_QUAD -# QUADMATH_LIBRARIES +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. # -# perform tests -include(CheckCSourceCompiles) -include(CheckCXXSourceCompiles) +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ------------------------------------------------------------------------------------------ + +include(FindPackageHandleStandardArgs) include(CMakePushCheckState) -include(CheckCXXCompilerFlag) +include(CheckCXXSourceCompiles) -if(NOT DEFINED USE_QUADMATH OR USE_QUADMATH) - if(NOT DEFINED HAVE_EXTENDED_NUMERIC_LITERALS) - check_cxx_compiler_flag("-Werror -fext-numeric-literals" HAVE_EXTENDED_NUMERIC_LITERALS) - endif() +if(Quadmath_INCLUDE_DIR AND Quadmath_LIBRARY) + # Already in cache, be silent + set(Quadmath_FIND_QUIETLY TRUE) +endif() - if (HAVE_EXTENDED_NUMERIC_LITERALS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals") - endif() +find_path(Quadmath_INCLUDE_DIR NAMES quadmath.h PATHS /usr/local/lib) +find_library(Quadmath_LIBRARY NAMES libquadmath.a PATHS /usr/local/lib/gcc/8/) +message(--- ${Quadmath_INCLUDE_DIR}) +message(--- ${Quadmath_LIBRARY}) + +if(NOT Quadmath_INCLUDE_DIR OR NOT Quadmath_LIBRARY) cmake_push_check_state(RESET) list(APPEND CMAKE_REQUIRED_LIBRARIES "quadmath") CHECK_CXX_SOURCE_COMPILES(" -#include - -int main(void){ - __float128 foo = sqrtq(123.456); - foo = FLT128_MIN; -}" QUADMATH_FOUND) + #include + int main(void){ + __float128 foo = ::sqrtq(123.456); + }" + Quadmath_USE_DIRECTLY) cmake_pop_check_state() - - if (QUADMATH_FOUND) - set(QUADMATH_LIBRARIES "quadmath") - set(HAVE_QUAD "${QUADMATH_FOUND}") + if (Quadmath_USE_DIRECTLY) + set(Quadmath_INCLUDE_DIR "unused" CACHE PATH "" FORCE) + set(Quadmath_LIBRARY "quadmath" CACHE FILEPATH "" FORCE) endif() endif() -if (USE_QUADMATH AND NOT QUADMATH_FOUND) - message(FATAL_ERROR "Quadruple precision math support was explicitly requested but is unavailable!") -endif() +find_package_handle_standard_args(Quadmath DEFAULT_MSG Quadmath_LIBRARY Quadmath_INCLUDE_DIR) -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Quadmath - DEFAULT_MSG - QUADMATH_LIBRARIES - HAVE_QUAD - ) +mark_as_advanced(Quadmath_INCLUDE_DIR Quadmath_LIBRARY) + +# NOTE: this has been adapted from CMake's FindPNG.cmake. +if(Quadmath_FOUND AND NOT TARGET Quadmath::quadmath) + message(STATUS "Creating the 'Quadmath::quadmath' imported target.") + if(Quadmath_USE_DIRECTLY) + message(STATUS "libquadmath will be included and linked directly.") + # If we are using it directly, we must define an interface library, + # as we do not have the full path to the shared library. + add_library(Quadmath::quadmath INTERFACE IMPORTED) + set_target_properties(Quadmath::quadmath PROPERTIES INTERFACE_LINK_LIBRARIES "${Quadmath_LIBRARY}") + else() + # Otherwise, we proceed as usual. + add_library(Quadmath::quadmath UNKNOWN IMPORTED) + set_target_properties(Quadmath::quadmath PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Quadmath_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${Quadmath_LIBRARY}") + endif() +endif() diff --git a/cmake/packages/FindTomMath.cmake b/cmake/packages/FindTomMath.cmake index 317276baf..9f99a6869 100644 --- a/cmake/packages/FindTomMath.cmake +++ b/cmake/packages/FindTomMath.cmake @@ -21,6 +21,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(TomMath DEFAULT_MSG TomMath_LIBRARY TomMath IF(TOMMATH_FOUND) set( TomMath_FOUND true ) SET( TomMath_LIBRARIES ${TomMath_LIBRARY} ) + SET( TomMath_INCLUDES ${TomMath_INCLUDE_DIR} ) ENDIF(TOMMATH_FOUND) MARK_AS_ADVANCED(TomMath_INCLUDE_DIR TomMath_LIBRARY TomMath_FOUND) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f1e9cea6d..1efeb6a05 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,15 +1,24 @@ include(CMTest) +find_package(GMP) +find_package(Quadmath) +find_package(TomMath) +find_package(MPFR) +find_package(MPFI) +find_package(MPC) + if(BOOST_CMAKE) - cm_find_package(${CMAKE_WORKSPACE_NAME}_algorithm) - cm_find_package(${CMAKE_WORKSPACE_NAME}_chrono) - cm_find_package(${CMAKE_WORKSPACE_NAME}_exception) - cm_find_package(${CMAKE_WORKSPACE_NAME}_timer) - cm_find_package(${CMAKE_WORKSPACE_NAME}_numeric_ublas) - cm_find_package(${CMAKE_WORKSPACE_NAME}_filesystem) - cm_find_package(${CMAKE_WORKSPACE_NAME}_test) - cm_find_package(${CMAKE_WORKSPACE_NAME}_serialization) - cm_find_package(${CMAKE_WORKSPACE_NAME}_numeric_interval) + find_package(${CMAKE_WORKSPACE_NAME}_algorithm) + find_package(${CMAKE_WORKSPACE_NAME}_chrono) + find_package(${CMAKE_WORKSPACE_NAME}_exception) + find_package(${CMAKE_WORKSPACE_NAME}_timer) + find_package(${CMAKE_WORKSPACE_NAME}_numeric_ublas) + find_package(${CMAKE_WORKSPACE_NAME}_filesystem) + find_package(${CMAKE_WORKSPACE_NAME}_test) + find_package(${CMAKE_WORKSPACE_NAME}_serialization) + find_package(${CMAKE_WORKSPACE_NAME}_numeric_interval) + find_package(${CMAKE_WORKSPACE_NAME}_detail) + find_package(${CMAKE_WORKSPACE_NAME}_throw_exception) cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision ${CMAKE_WORKSPACE_NAME}::algorithm @@ -21,14 +30,18 @@ if(BOOST_CMAKE) ${CMAKE_WORKSPACE_NAME}::test ${CMAKE_WORKSPACE_NAME}::serialization ${CMAKE_WORKSPACE_NAME}::numeric_interval + ${CMAKE_WORKSPACE_NAME}::detail + ${CMAKE_WORKSPACE_NAME}::throw_exception ) else() - cm_find_package(Boost COMPONENTS chrono timer exception filesystem - unit_test_framework serialization) + find_package(Boost COMPONENTS chrono exception timer filesystem filesystem + unit_test_framework serialization) cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision ${Boost_LIBRARIES} ) + + include_directories(${Boost_INCLUDE_DIRS}) endif() # copyright John Maddock 2011 @@ -57,140 +70,317 @@ cm_test_link_libraries(multiprecision_test_settings) # target_link_libraries(no_eh_support boost_throw_exception) # cm_target_link_test_libs(no_eh_support) -try_compile(HAS_GMP ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_gmp.cpp CMAKE_FLAGS - "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") -try_compile(HAS_MPFR ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfr.cpp CMAKE_FLAGS - "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") -try_compile(HAS_TOMMATH ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_tommath.cpp CMAKE_FLAGS - "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") -try_compile(HAS_FLOAT128 ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_float128.cpp) -try_compile(HAS_MPFI ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfi.cpp CMAKE_FLAGS - "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") -try_compile(HAS_INTEL_QUAD ${CURRENT_TEST_SOURCES_DIR}/../config ${CURRENT_TEST_SOURCES_DIR}/../config/has_intel_quad.cpp CMAKE_FLAGS +try_compile(GMP_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_gmp.cpp + LINK_LIBRARIES ${GMP_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${GMP_INCLUDES}") + +try_compile(MPFR_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfr.cpp + LINK_LIBRARIES ${MPFR_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPFR_INCLUDES}") + +try_compile(TOMMATH_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_tommath.cpp + LINK_LIBRARIES ${TomMath_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${TomMath_INCLUDES}") + +try_compile(FLOAT128_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_float128.cpp) + +try_compile(MPFI_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfi.cpp + LINK_LIBRARIES ${MPFI_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPFI_INCLUDES}") + +try_compile(INTEL_QUAD_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_intel_quad.cpp CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") +try_compile(MPC_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpc.cpp + LINK_LIBRARIES ${MPC_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPC_INCLUDES}") + +message(GMP_COMPILED=${GMP_COMPILED}) +message(MPFR_COMPILED=${MPFR_COMPILED}) +message(TOMMATH_COMPILED=${TOMMATH_COMPILED}) +message(FLOAT128_COMPILED=${FLOAT128_COMPILED}) +message(MPFI_COMPILED=${MPFI_COMPILED}) +message(INTEL_QUAD_COMPILED=${INTEL_QUAD_COMPILED}) +message(MPC_COMPILED=${MPC_COMPILED}) + +#cm_test(NAME GMP_MY SOURCES ${CURRENT_TEST_SOURCES_DIR}/../config/has_float128.cpp) +#target_link_libraries(GMP_MY ${Quadmath_LIBRARY}) +#target_include_directories(GMP_MY PRIVATE ${Quadmath_INCLUDE_DIR}) + +add_library(no_eh_test_support SHARED ${CURRENT_TEST_SOURCES_DIR}/no_eh_test_support.cpp) + +#cm_test_link_libraries(no_eh_test_support) +#target_include_directories(no_eh_test_support INTERFACE ${Boost_INCLUDE_DIRS}) + cm_test(NAME multiprecision_test_test_arithmetic_backend_concept SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_backend_concept.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_backend_concept no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_1.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_1 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_2.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_2 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_3.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_3 no_eh_test_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_3m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_3m.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_3m no_eh_test_support) if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_1 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_arithmetic_cpp_bin_float_1.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_2 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_arithmetic_cpp_bin_float_2.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_3 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_arithmetic_cpp_bin_float_3.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_1.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_1 no_eh_test_support) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_2.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_2 no_eh_test_support) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_2m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_2m.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_2m no_eh_test_support) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_3.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_3 no_eh_test_support) + endif() -if(HAS_GMP) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_mpf_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpf_50.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpf_50 ${GMP_LIBRARIES} no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpf.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpf ${GMP_LIBRARIES} no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpz ${GMP_LIBRARIES} no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_mpz_rat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz_rat.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpz_rat ${GMP_LIBRARIES} no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_mpz_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz_br.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpz_br ${GMP_LIBRARIES} no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_mpq SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpq.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpq ${GMP_LIBRARIES} no_eh_test_support) endif() -if(HAS_MPFR) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr_50.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpfr_50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_mpfr_50_static SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr_50_static.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpfr_50_static ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_test_support) endif() -if(HAS_TOMMATH) +if(TOMMATH_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_tommath ${TomMath_LIBRARIES} no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_tommath_rat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath_rat.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_tommath_rat ${TomMath_LIBRARIES} no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_tommath_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath_br.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_tommath_br ${TomMath_LIBRARIES} no_eh_test_support) endif() if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") # TODO: fix test. Reason error: [-fpermissive] + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_1.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_1 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_2.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_2 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_3.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_3 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_4.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_4 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_5.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_5 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_6.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_6 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_7 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_7.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_7 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_8 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_8.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_8 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_9 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_9.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_9 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_10 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_10.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_10 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_11 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_11.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_11 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_12 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_12.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_12 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_13 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_13.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_13 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_14 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_14.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_14 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_15 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_15.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_15 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_16 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_16.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_16 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_17 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_17.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_17 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_18 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_18.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_18 no_eh_test_support) + cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_19 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_19.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_19 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_br.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_br no_eh_test_support) endif() cm_test(NAME multiprecision_test_test_arithmetic_ab_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_1.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_ab_1 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_ab_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_2.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_ab_2 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_ab_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_3.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_ab_3 no_eh_test_support) cm_test(NAME multiprecision_test_test_cpp_dec_float_round SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_round.cpp) +target_link_libraries(multiprecision_test_test_cpp_dec_float_round no_eh_test_support) if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") # TODO: fix test. Reason error: [-fpermissive] cm_test(NAME multiprecision_test_test_arithmetic_logged_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_1.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_logged_1 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_logged_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_2.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_logged_2 no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr1.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_dbg_adptr1 no_eh_test_support) + cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr1m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr1m.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_dbg_adptr1m no_eh_test_support) cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr2.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_dbg_adptr2 no_eh_test_support) endif() -if(HAS_MPFI) +if(MPFI_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_mpfi_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfi_50.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpfi_50 ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_test_support) + target_include_directories(multiprecision_test_test_arithmetic_mpfi_50 PRIVATE ${MPFI_INCLUDES}) endif() +if (HAS_INTEL_QUAD) + #TODO: fix it + cm_test(NAME multiprecision_test_test_arithmetic_float_128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_float_128.cpp) +endif() +if (HAS_FLOAT128) + #TODO: add quad lib + cm_test(NAME multiprecision_test_test_arithmetic_float_128_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_float_128.cpp) +endif() + +if (MPC_COMPILED) + cm_test(NAME multiprecision_test_test_arithmetic_mpc SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpc.cpp) + target_link_libraries(multiprecision_test_test_arithmetic_mpc ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + cm_test(NAME multiprecision_test_test_mpfr_mpc_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfr_mpc_precisions.cpp) + target_link_libraries(multiprecision_test_test_mpfr_mpc_precisions ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) +endif() +if (MPFI_COMPILED) + cm_test(NAME multiprecision_test_test_mpfi_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfi_precisions.cpp) + target_link_libraries(multiprecision_test_test_mpfi_precisions ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_mpfi_precisions PRIVATE ${MPFI_INCLUDES}) +endif() + +if (GMP_COMPILED) + cm_test(NAME multiprecision_test_test_mpf_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpf_precisions.cpp) + target_link_libraries(multiprecision_test_test_mpf_precisions ${GMP_LIBRARIES}) +endif() +if ((MPC_COMPILED) AND (HAS_FLOAT128)) + #TODO: fix it + cm_test(NAME multiprecision_test_test_complex SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_complex.cpp) +endif() +cm_test(NAME multiprecision_test_test_arithmetic_complex_adaptor SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex_adaptor.cpp) +cm_test(NAME multiprecision_test_test_arithmetic_complex_adaptor_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex_adaptor_2.cpp) +if (HAS_FLOAT128) + #TODO: fix it + cm_test(NAME multiprecision_test_test_arithmetic_complex128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex128.cpp) +endif() + +set(LOCAL_SOURCES test_exp.cpp test_log.cpp test_pow.cpp test_sinh.cpp test_sqrt.cpp test_cosh.cpp test_tanh.cpp test_sin.cpp test_cos.cpp test_tan.cpp test_asin.cpp test_acos.cpp test_atan.cpp test_round.cpp test_fpclassify.cpp test_sf_import_c99.cpp) +foreach(FILE ${LOCAL_SOURCES}) + get_filename_component(NAME ${FILE} NAME_WE) + if(GMP_COMPILED) + cm_test(NAME multiprecision_test_${NAME}_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) + target_link_libraries(multiprecision_test_${NAME}_mpf50 ${GMP_LIBRARIES} no_eh_support) + endif() + if(MPFR_COMPILED) + cm_test(NAME multiprecision_test_${NAME}_mpfr50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_mpfr50 PUBLIC -DTEST_MPFR_50) + target_link_libraries(multiprecision_test_${NAME}_mpfr50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + endif() + if(MPFI_COMPILED) + cm_test(NAME multiprecision_test_${NAME}_mpfi50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_mpfi50 PUBLIC -DTEST_MPFI_50) + target_link_libraries(multiprecision_test_${NAME}_mpfi50 ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_${NAME}_mpfi50 PRIVATE ${MPFI_INCLUDES}) + endif() + + cm_test(NAME multiprecision_test_${NAME}_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) + target_link_libraries(multiprecision_test_${NAME}_cpp_dec_float no_eh_support) + + cm_test(NAME multiprecision_test_${NAME}_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) + target_link_libraries(multiprecision_test_${NAME}_cpp_bin_float no_eh_support) + + if(HAS_FLOAT128) + #TODO: fix it + cm_test(NAME multiprecision_test_${NAME}_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_float128 PUBLIC -DTEST_FLOAT128) + target_link_libraries(multiprecision_test_${NAME}_float128 no_eh_support) + endif() + + if(HAS_INTEL_QUAD) + #TODO: fix it + cm_test(NAME multiprecision_test_${NAME}_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) + target_compile_definitions(multiprecision_test_${NAME}_intel_quad PUBLIC -DTEST_FLOAT128) + target_link_libraries(multiprecision_test_${NAME}_intel_quad no_eh_support) + endif() +endforeach() + + if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") # TODO: fix test. Reason error: [-fpermissive] cm_test(NAME multiprecision_test_test_numeric_limits_backend_concept SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_backend_concept PUBLIC -DTEST_BACKEND) + target_link_libraries(multiprecision_test_test_numeric_limits_backend_concept no_eh_support) endif() -if(HAS_GMP) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_numeric_limits_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpf50 PUBLIC -DTEST_MPF_50) + target_link_libraries(multiprecision_test_test_numeric_limits_mpf50 ${GMP_LIBRARIES} no_eh_support) cm_test(NAME multiprecision_test_test_numeric_limits_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpf PUBLIC -DTEST_MPF) + target_link_libraries(multiprecision_test_test_numeric_limits_mpf ${GMP_LIBRARIES} no_eh_support) cm_test(NAME multiprecision_test_test_numeric_limits_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpz PUBLIC -DTEST_MPZ) + target_link_libraries(multiprecision_test_test_numeric_limits_mpz ${GMP_LIBRARIES} no_eh_support) cm_test(NAME multiprecision_test_test_numeric_limits_mpq SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpq PUBLIC -DTEST_MPQ) + target_link_libraries(multiprecision_test_test_numeric_limits_mpq ${GMP_LIBRARIES} no_eh_support) endif() -if(HAS_MPFR) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_numeric_limits_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpfr PUBLIC -DTEST_MPFR) + target_link_libraries(multiprecision_test_test_numeric_limits_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) cm_test(NAME multiprecision_test_test_numeric_limits_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpfr_50 PUBLIC -DTEST_MPFR_50) + target_link_libraries(multiprecision_test_test_numeric_limits_mpfr_50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) endif() -if(HAS_GMP) - cm_test(NAME multiprecision_test_test_numeric_limits_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) - target_compile_definitions(multiprecision_test_test_numeric_limits_cpp_dec_float PUBLIC -TDEST_CPP_DEC_FLOAT) +cm_test(NAME multiprecision_test_test_numeric_limits_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) +target_compile_definitions(multiprecision_test_test_numeric_limits_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) +target_link_libraries(multiprecision_test_test_numeric_limits_cpp_dec_float no_eh_support) - cm_test(NAME multiprecision_test_test_numeric_limits_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) - target_compile_definitions(multiprecision_test_test_numeric_limits_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) -endif() +cm_test(NAME multiprecision_test_test_numeric_limits_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) +target_compile_definitions(multiprecision_test_test_numeric_limits_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) +target_link_libraries(multiprecision_test_test_numeric_limits_cpp_bin_float no_eh_support) -if(HAS_TOMMATH) +if(TOMMATH_COMPILED) cm_test(NAME multiprecision_test_test_numeric_limits_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_tommath PUBLIC -DTEST_TOMMATH) + target_link_libraries(multiprecision_test_test_numeric_limits_tommath ${TomMath_LIBRARIES} no_eh_support) endif() if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") cm_test(NAME multiprecision_test_test_numeric_limits_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_cpp_int PUBLIC -DTEST_CPP_INT) + target_link_libraries(multiprecision_test_test_numeric_limits_cpp_int no_eh_support) endif() - -if(HAS_MPFI) +#[[ +if(MPFI_COMPILED) cm_test(NAME multiprecision_test_test_numeric_limits_mpfi_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpfi_50 PUBLIC -DTEST_MPFI_50) endif() @@ -212,15 +402,15 @@ if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") test_tan.cpp test_asin.cpp test_atan.cpp test_fpclassify.cpp) foreach(FILE ${LOCAL_SOURCES}) get_filename_component(NAME ${FILE} NAME_WE) - if(HAS_GMP) + if(GMP_COMPILED) cm_test(NAME multiprecision_test_${NAME}_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) target_compile_definitions(multiprecision_test_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) endif() - if(HAS_MPFR) + if(MPFR_COMPILED) cm_test(NAME multiprecision_test_${NAME}_mpfr50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) target_compile_definitions(multiprecision_test_${NAME}_mpfr50 PUBLIC -DTEST_MPFR_50) endif() - if(HAS_MPFI) + if(MPFI_COMPILED) cm_test(NAME multiprecision_test_${NAME}_mpfi50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) target_compile_definitions(multiprecision_test_${NAME}_mpfi50 PUBLIC -DTEST_MPFI_50) endif() @@ -243,20 +433,20 @@ if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") endforeach() endif() -if(HAS_GMP) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_gmp_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_gmp_conversions.cpp) endif() -if(HAS_MPFR) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_mpfr_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfr_conversions.cpp) endif() -if(HAS_GMP) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_constants_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) target_compile_definitions(multiprecision_test_test_constants_mpf50 PUBLIC -DTEST_MPF_50) endif() -if(HAS_MPFR) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_constants_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) target_compile_definitions(multiprecision_test_test_constants_mpfr_50 PUBLIC -DTEST_MPFR_50) endif() @@ -264,17 +454,17 @@ endif() cm_test(NAME multiprecision_test_test_constants_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) target_compile_definitions(multiprecision_test_test_constants_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) -if(HAS_MPFR) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_move_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) target_compile_definitions(multiprecision_test_test_move_mpfr PUBLIC -DTEST_MPFR) endif() -if(HAS_GMP) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_move_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) target_compile_definitions(multiprecision_test_test_move_gmp PUBLIC -DTEST_GMP) endif() -if(HAS_TOMMATH) +if(TOMMATH_COMPILED) cm_test(NAME multiprecision_test_test_move_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) target_compile_definitions(multiprecision_test_test_move_tommath PUBLIC -DTEST_TOMMATH) endif() @@ -308,76 +498,76 @@ if(HAS_FLOAT128) cm_test(NAME multiprecision_test_test_nothrow_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_float128.cpp COMPILE_ONLY) endif() -if(HAS_GMP) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_nothrow_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_gmp.cpp COMPILE_ONLY) endif() -if(HAS_MPFR) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_nothrow_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_mpfr.cpp COMPILE_ONLY) endif() if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_cpp_bin_float_io_1 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_cpp_bin_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_cpp_bin_float_io_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_io.cpp) target_compile_definitions(multiprecision_test_test_cpp_bin_float_io_1 PUBLIC -DTEST1 -DTEST_CPP_BIN_FLOAT) - cm_test(NAME multiprecision_test_test_cpp_bin_float_io_2 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_cpp_bin_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_cpp_bin_float_io_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_io.cpp) target_compile_definitions(multiprecision_test_test_cpp_bin_float_io_2 PUBLIC -DTEST2 -DTEST_CPP_BIN_FLOAT) - if(HAS_MPFR) - cm_test(NAME multiprecision_test_test_cpp_bin_float SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_cpp_bin_float.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + if(MPFR_COMPILED) + cm_test(NAME multiprecision_test_test_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float.cpp) target_compile_definitions(multiprecision_test_test_cpp_bin_float PUBLIC -DTEST_MPFR) endif() - cm_test(NAME multiprecision_test_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) target_compile_definitions(multiprecision_test_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) - if(HAS_GMP) - cm_test(NAME multiprecision_test_test_float_io_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + if(GMP_COMPILED) + cm_test(NAME multiprecision_test_test_float_io_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) target_compile_definitions(multiprecision_test_test_float_io_mpf PUBLIC -DTEST_MPF_50) endif() - if(HAS_MPFR) - cm_test(NAME multiprecision_test_test_float_io_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + if(MPFR_COMPILED) + cm_test(NAME multiprecision_test_test_float_io_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) target_compile_definitions(multiprecision_test_test_float_io_mpfr PUBLIC -DTEST_MPFR_50) endif() - if(HAS_MPFI) - cm_test(NAME multiprecision_test_test_float_io_mpfi SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + if(MPFI_COMPILED) + cm_test(NAME multiprecision_test_test_float_io_mpfi SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) target_compile_definitions(multiprecision_test_test_float_io_mpfi PUBLIC -DTEST_MPFI_50) endif() if(HAS_FLOAT128) - cm_test(NAME multiprecision_test_test_float_io_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_float_io_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) target_compile_definitions(multiprecision_test_test_float_io_float128 PUBLIC -DTEST_FLOAT128) endif() if((HAS_INTEL_QUAD) AND (HAS_FLOAT128)) - cm_test(NAME multiprecision_test_test_float_io_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_float_io_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) target_compile_definitions(multiprecision_test_test_float_io_intel_quad PUBLIC -DTEST_FLOAT128) endif() - if(HAS_TOMMATH) - cm_test(NAME multiprecision_test_test_int_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + if(TOMMATH_COMPILED) + cm_test(NAME multiprecision_test_test_int_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) target_compile_definitions(multiprecision_test_test_int_io_tommath PUBLIC -DTEST_TOMMATH) endif() - if(HAS_GMP) - cm_test(NAME multiprecision_test_test_int_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + if(GMP_COMPILED) + cm_test(NAME multiprecision_test_test_int_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) target_compile_definitions(multiprecision_test_test_int_io_mpz PUBLIC -DTEST_MPZ) endif() - cm_test(NAME multiprecision_test_test_int_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_int_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) target_compile_definitions(multiprecision_test_test_int_io_cpp_int PUBLIC -DTEST_CPP_INT) - if(HAS_GMP) - cm_test(NAME multiprecision_test_test_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + if(GMP_COMPILED) + cm_test(NAME multiprecision_test_test_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) target_compile_definitions(multiprecision_test_test_cpp_int_1 PUBLIC -DTEST1) - cm_test(NAME multiprecision_test_test_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) target_compile_definitions(multiprecision_test_test_cpp_int_2 PUBLIC -DTEST2) - cm_test(NAME multiprecision_test_test_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) target_compile_definitions(multiprecision_test_test_cpp_int_3 PUBLIC -DTEST2) endif() endif() @@ -387,18 +577,18 @@ if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") cm_test(NAME multiprecision_test_test_checked_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_checked_cpp_int.cpp) endif() -if(HAS_GMP) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_miller_rabin SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_miller_rabin.cpp) endif() if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") # TODO: fix test. Reason error: [-fpermissive] - if(HAS_TOMMATH) + if(TOMMATH_COMPILED) cm_test(NAME multiprecision_test_test_rational_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) target_compile_definitions(multiprecision_test_test_rational_io_tommath PUBLIC -DTEST_TOMMATH) endif() - if(HAS_GMP) + if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_rational_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) target_compile_definitions(multiprecision_test_test_rational_io_mpz PUBLIC -DTEST_MPQ) endif() @@ -407,7 +597,7 @@ if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") target_compile_definitions(multiprecision_test_test_rational_io_cpp_int PUBLIC -DTEST_CPP_INT) endif() -if((HAS_GMP) AND (HAS_TOMMATH) AND (HAS_MPFR)) +if((GMP_COMPILED) AND (TOMMATH_COMPILED) AND (MPFR_COMPILED)) cm_test(NAME multiprecision_test_test_generic_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_generic_conv.cpp) target_compile_definitions(multiprecision_test_test_generic_conv PUBLIC -DTEST_GMP -DTEST_TOMMATH -DTEST_MPFR) @@ -428,7 +618,7 @@ if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") target_compile_definitions(multiprecision_test_test_rat_float_interconv_4 PUBLIC TEST4) endif() -if(HAS_MPFR) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_rat_float_interconv_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) target_compile_definitions(multiprecision_test_test_rat_float_interconv_5 PUBLIC -DTEST5) @@ -448,18 +638,18 @@ if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") cm_test(NAME multiprecision_test_test_native_integer SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_native_integer.cpp) cm_test(NAME multiprecision_test_test_mixed_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_int.cpp) - if((HAS_GMP) AND (HAS_MPFR)) + if((GMP_COMPILED) AND (MPFR_COMPILED)) cm_test(NAME multiprecision_test_test_mixed_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_float.cpp) endif() endif() -if(HAS_MPFR) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_include_test_mpfr_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/mpfr_include_test.cpp COMPILE_ONLY) endif() -if(HAS_GMP) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_include_test_gmp_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/gmp_include_test.cpp COMPILE_ONLY) endif() -if(HAS_TOMMATH) +if(TOMMATH_COMPILED) cm_test(NAME multiprecision_test_include_test_tommath_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/tommath_include_test.cpp COMPILE_ONLY) endif() cm_test(NAME multiprecision_test_include_test_cpp_int_include_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/include_test/cpp_int_include_test.cpp COMPILE_ONLY) @@ -518,13 +708,13 @@ target_include_directories(multiprecision_test_ublas_interop_test6_et PUBLIC -DT #run ublas_interop/test7.cpp ublas_interop/test71.cpp ublas_interop/test72.cpp ublas_interop/test73.cpp ; if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_cpp_int_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_cpp_int_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) target_compile_definitions(multiprecision_test_test_cpp_int_serial_1 PUBLIC -DTEST1) - cm_test(NAME multiprecision_test_test_cpp_int_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_cpp_int_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) target_compile_definitions(multiprecision_test_test_cpp_int_serial_2 PUBLIC -DTEST2) - cm_test(NAME multiprecision_test_test_cpp_int_serial_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_cpp_int_serial_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) target_compile_definitions(multiprecision_test_test_cpp_int_serial_3 PUBLIC -DTEST3) - cm_test(NAME multiprecision_test_test_cpp_int_serial_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp SOURCES_PREFIX ${CURRENT_TEST_SOURCES_DIR}) + cm_test(NAME multiprecision_test_test_cpp_int_serial_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) target_compile_definitions(multiprecision_test_test_cpp_int_serial_4 PUBLIC -DTEST4) cm_test(NAME multiprecision_test_test_cpp_int_deserial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_deserial.cpp) cm_test(NAME multiprecision_test_test_cpp_rat_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_rat_serial.cpp) @@ -552,10 +742,10 @@ if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") cm_test(NAME multiprecision_test_test_mixed_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_dec_float.cpp) endif() -if(HAS_GMP) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_mixed_mpf_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_mpf_float.cpp) endif() -if(HAS_MPFR) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_mixed_mpfr_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_mpfr_float.cpp) endif() @@ -565,13 +755,13 @@ set(TEST_FILES "") foreach(FILEB ${TEST_FILES}) get_filename_component(NAME ${FILEB} NAME_WE) - if(HAS_MPFR) + if(MPFR_COMPILED) cm_test(NAME multiprecision_test_math_${NAME}_mpfr SOURCES ${FILEB}) target_compile_definitions(multiprecision_test_math_${NAME}_mpfr PRIVATE -DTEST_MPFR_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) target_include_directories(multiprecision_test_math_${NAME}_mpfr PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) endif() - if(HAS_GMP) + if(GMP_COMPILED) cm_test(NAME multiprecision_test_math_${NAME}_mpf SOURCES ${FILEB}) target_compile_definitions(multiprecision_test_math_${NAME}_mpf PRIVATE -DTEST_MPF_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) target_include_directories(multiprecision_test_math_${NAME}_mpf PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) @@ -605,7 +795,7 @@ list(REMOVE_ITEM TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/high_prec/test_gamm foreach(FILEB ${TEST_FILES}) get_filename_component(NAME ${FILEB} NAME_WE) cm_test(NAME multiprecision_test_math_high_prec_${NAME} SOURCES ${FILEB}) - if(HAS_MPFR) + if(MPFR_COMPILED) target_compile_definitions(multiprecision_test_math_high_prec_${NAME} PRIVATE -DTEST_MPFR) endif() target_compile_definitions(multiprecision_test_math_high_prec_${NAME} PRIVATE -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE -DBOOST_ALL_NO_LIB) @@ -616,10 +806,10 @@ file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/compile_fail/*.cpp) foreach(FILEB ${TEST_FILES}) get_filename_component(NAME ${FILEB} NAME_WE) cm_test(NAME multiprecision_test_compile_fail_${NAME} SOURCES ${FILEB} COMPILE_ONLY WILL_FAIL) - if(HAS_GMP) + if(GMP_COMPILED) target_compile_definitions(multiprecision_test_compile_fail_${NAME} PUBLIC -DTEST_GMP) endif() - if(HAS_MPFR) + if(MPFR_COMPILED) target_compile_definitions(multiprecision_test_compile_fail_${NAME} PUBLIC -DTEST_MPFR) endif() endforeach() @@ -661,5 +851,5 @@ foreach(FILEB ${TEST_FILES}) cm_test(NAME multiprecision_test_concepts_${NAME}_logged_adaptor SOURCES ${FILEB} COMPILE_ONLY) target_compile_definitions(multiprecision_test_concepts_${NAME}_logged_adaptor PUBLIC -DTEST_LOGGED_ADAPTER) endforeach() - -include_directories(${CMAKE_WORKSPACE_SOURCES_DIR}) \ No newline at end of file +#]] +include_directories(${CMAKE_WORKSPACE_SOURCES_DIR}) From f398829c418e1c94573974d082ee4743113dcfb5 Mon Sep 17 00:00:00 2001 From: Zerg1996 Date: Mon, 1 Jul 2019 18:58:09 +0300 Subject: [PATCH 011/294] Checked Apple LLVM version 10.0.1 #11 --- test/CMakeLists.txt | 1115 ++++++++++++++++++++++++++++--------------- 1 file changed, 725 insertions(+), 390 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1efeb6a05..e08d47dfe 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,6 +6,7 @@ find_package(TomMath) find_package(MPFR) find_package(MPFI) find_package(MPC) +find_package(Eigen3) if(BOOST_CMAKE) find_package(${CMAKE_WORKSPACE_NAME}_algorithm) @@ -19,6 +20,8 @@ if(BOOST_CMAKE) find_package(${CMAKE_WORKSPACE_NAME}_numeric_interval) find_package(${CMAKE_WORKSPACE_NAME}_detail) find_package(${CMAKE_WORKSPACE_NAME}_throw_exception) + find_package(${CMAKE_WORKSPACE_NAME}_math) + find_package(${CMAKE_WORKSPACE_NAME}_regexp) cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision ${CMAKE_WORKSPACE_NAME}::algorithm @@ -32,10 +35,12 @@ if(BOOST_CMAKE) ${CMAKE_WORKSPACE_NAME}::numeric_interval ${CMAKE_WORKSPACE_NAME}::detail ${CMAKE_WORKSPACE_NAME}::throw_exception + ${CMAKE_WORKSPACE_NAME}::math + ${CMAKE_WORKSPACE_NAME}::regexp ) else() - find_package(Boost COMPONENTS chrono exception timer filesystem filesystem - unit_test_framework serialization) + find_package(Boost 1.70.0 REQUIRED chrono exception timer filesystem filesystem + unit_test_framework serialization regex ) cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision ${Boost_LIBRARIES} @@ -65,7 +70,7 @@ cm_test_link_libraries(multiprecision_test_settings) #msvc,off:-RTCc #msvc,off:_ALLOW_RTCc_IN_STL -# add_library(no_eh_support STATIC no_eh_test_support.cpp) +# add_library(no_eh_support STATIC no_eh_support.cpp) # cm_mark_as_test(no_eh_support) # target_link_libraries(no_eh_support boost_throw_exception) # cm_target_link_test_libs(no_eh_support) @@ -95,6 +100,10 @@ try_compile(MPC_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../conf LINK_LIBRARIES ${MPC_LIBRARIES} CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPC_INCLUDES}") +try_compile(EIGEN_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_eigen.cpp + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${EIGEN3_INCLUDE_DIR}") + +message(${EIGEN3_INCLUDE_DIR}) message(GMP_COMPILED=${GMP_COMPILED}) message(MPFR_COMPILED=${MPFR_COMPILED}) message(TOMMATH_COMPILED=${TOMMATH_COMPILED}) @@ -102,163 +111,164 @@ message(FLOAT128_COMPILED=${FLOAT128_COMPILED}) message(MPFI_COMPILED=${MPFI_COMPILED}) message(INTEL_QUAD_COMPILED=${INTEL_QUAD_COMPILED}) message(MPC_COMPILED=${MPC_COMPILED}) +message(EIGEN_COMPILED=${EIGEN_COMPILED}) #cm_test(NAME GMP_MY SOURCES ${CURRENT_TEST_SOURCES_DIR}/../config/has_float128.cpp) #target_link_libraries(GMP_MY ${Quadmath_LIBRARY}) #target_include_directories(GMP_MY PRIVATE ${Quadmath_INCLUDE_DIR}) -add_library(no_eh_test_support SHARED ${CURRENT_TEST_SOURCES_DIR}/no_eh_test_support.cpp) - -#cm_test_link_libraries(no_eh_test_support) -#target_include_directories(no_eh_test_support INTERFACE ${Boost_INCLUDE_DIRS}) +add_library(no_eh_support SHARED ${CURRENT_TEST_SOURCES_DIR}/no_eh_test_support.cpp) cm_test(NAME multiprecision_test_test_arithmetic_backend_concept SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_backend_concept.cpp) -target_link_libraries(multiprecision_test_test_arithmetic_backend_concept no_eh_test_support) +target_link_libraries(multiprecision_test_test_arithmetic_backend_concept no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_1.cpp) -target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_1 no_eh_test_support) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_1 no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_2.cpp) -target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_2 no_eh_test_support) +target_link_libraries( multiprecision_test_test_arithmetic_cpp_dec_float_2 no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_3.cpp) -target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_3 no_eh_test_support) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_3 no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_3m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_3m.cpp) -target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_3m no_eh_test_support) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_3m no_eh_support) -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_1.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_1 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_2.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_2 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_2m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_2m.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_2m no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_3.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_3 no_eh_test_support) - -endif() +cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_1.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_1 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_2.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_2 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_2m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_2m.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_2m no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_bin_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_bin_float_3.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_bin_float_3 no_eh_support) if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_mpf_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpf_50.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpf_50 ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpf_50 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_mpf_50 PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_arithmetic_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpf.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpf ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpf ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_mpf PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_arithmetic_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpz ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpz ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_mpz PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_arithmetic_mpz_rat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz_rat.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpz_rat ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpz_rat ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_mpz_rat PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_arithmetic_mpz_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpz_br.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpz_br ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpz_br ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_mpz_br PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_arithmetic_mpq SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpq.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpq ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpq ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_mpq PRIVATE ${GMP_INCLUDES}) endif() if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_mpfr PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_arithmetic_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr_50.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpfr_50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpfr_50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_mpfr_50 PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_arithmetic_mpfr_50_static SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfr_50_static.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpfr_50_static ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpfr_50_static ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_mpfr_50_static PRIVATE ${GMP_INCLUDES}) endif() if(TOMMATH_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_tommath ${TomMath_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_tommath ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_tommath PRIVATE ${TomMath_INCLUDES}) cm_test(NAME multiprecision_test_test_arithmetic_tommath_rat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath_rat.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_tommath_rat ${TomMath_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_tommath_rat ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_tommath_rat PRIVATE ${TomMath_INCLUDES}) cm_test(NAME multiprecision_test_test_arithmetic_tommath_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_tommath_br.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_tommath_br ${TomMath_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_tommath_br ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_arithmetic_tommath_br PRIVATE ${TomMath_INCLUDES}) endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_1.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_1 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_2.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_2 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_3.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_3 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_4.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_4 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_5.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_5 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_6.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_6 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_7 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_7.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_7 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_8 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_8.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_8 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_9 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_9.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_9 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_10 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_10.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_10 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_11 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_11.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_11 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_12 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_12.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_12 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_13 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_13.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_13 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_14 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_14.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_14 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_15 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_15.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_15 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_16 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_16.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_16 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_17 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_17.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_17 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_18 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_18.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_18 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_19 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_19.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_19 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_br.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_br no_eh_test_support) -endif() +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_1.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_1 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_2.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_2 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_3.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_3 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_4.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_4 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_5.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_5 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_6.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_6 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_7 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_7.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_7 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_8 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_8.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_8 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_9 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_9.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_9 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_10 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_10.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_10 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_11 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_11.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_11 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_12 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_12.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_12 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_13 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_13.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_13 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_14 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_14.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_14 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_15 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_15.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_15 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_16 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_16.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_16 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_17 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_17.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_17 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_18 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_18.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_18 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_19 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_19.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_19 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_cpp_int_br SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_int_br.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_int_br no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_ab_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_1.cpp) -target_link_libraries(multiprecision_test_test_arithmetic_ab_1 no_eh_test_support) +target_link_libraries(multiprecision_test_test_arithmetic_ab_1 no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_ab_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_2.cpp) -target_link_libraries(multiprecision_test_test_arithmetic_ab_2 no_eh_test_support) +target_link_libraries(multiprecision_test_test_arithmetic_ab_2 no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_ab_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_ab_3.cpp) -target_link_libraries(multiprecision_test_test_arithmetic_ab_3 no_eh_test_support) +target_link_libraries(multiprecision_test_test_arithmetic_ab_3 no_eh_support) cm_test(NAME multiprecision_test_test_cpp_dec_float_round SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_round.cpp) -target_link_libraries(multiprecision_test_test_cpp_dec_float_round no_eh_test_support) +target_link_libraries(multiprecision_test_test_cpp_dec_float_round no_eh_support) -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_arithmetic_logged_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_1.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_logged_1 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_logged_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_2.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_logged_2 no_eh_test_support) +cm_test(NAME multiprecision_test_test_arithmetic_logged_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_1.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_logged_1 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_logged_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_logged_2.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_logged_2 no_eh_support) - cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr1.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_dbg_adptr1 no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr1m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr1m.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_dbg_adptr1m no_eh_test_support) - cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr2.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_dbg_adptr2 no_eh_test_support) -endif() +cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr1.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_dbg_adptr1 no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr1m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr1m.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_dbg_adptr1m no_eh_support) +cm_test(NAME multiprecision_test_test_arithmetic_dbg_adptr2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_dbg_adptr2.cpp) +target_link_libraries(multiprecision_test_test_arithmetic_dbg_adptr2 no_eh_support) if(MPFI_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_mpfi_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpfi_50.cpp) - target_link_libraries(multiprecision_test_test_arithmetic_mpfi_50 ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_test_support) + target_link_libraries(multiprecision_test_test_arithmetic_mpfi_50 ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) target_include_directories(multiprecision_test_test_arithmetic_mpfi_50 PRIVATE ${MPFI_INCLUDES}) endif() -if (HAS_INTEL_QUAD) - #TODO: fix it +if (INTEL_QUAD_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_float_128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_float_128.cpp) endif() -if (HAS_FLOAT128) - #TODO: add quad lib + +if (FLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_float_128_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_float_128.cpp) endif() if (MPC_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_mpc SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpc.cpp) target_link_libraries(multiprecision_test_test_arithmetic_mpc ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_arithmetic_mpc PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_mpfr_mpc_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfr_mpc_precisions.cpp) target_link_libraries(multiprecision_test_test_mpfr_mpc_precisions ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_mpfr_mpc_precisions PRIVATE ${GMP_INCLUDES}) endif() if (MPFI_COMPILED) cm_test(NAME multiprecision_test_test_mpfi_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfi_precisions.cpp) @@ -269,15 +279,16 @@ endif() if (GMP_COMPILED) cm_test(NAME multiprecision_test_test_mpf_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpf_precisions.cpp) target_link_libraries(multiprecision_test_test_mpf_precisions ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_mpf_precisions PRIVATE ${GMP_INCLUDES}) endif() -if ((MPC_COMPILED) AND (HAS_FLOAT128)) - #TODO: fix it + +if ((MPC_COMPILED) AND (FLOAT128_COMPILED)) cm_test(NAME multiprecision_test_test_complex SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_complex.cpp) endif() cm_test(NAME multiprecision_test_test_arithmetic_complex_adaptor SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex_adaptor.cpp) cm_test(NAME multiprecision_test_test_arithmetic_complex_adaptor_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex_adaptor_2.cpp) -if (HAS_FLOAT128) - #TODO: fix it + +if (FLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_complex128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex128.cpp) endif() @@ -288,11 +299,13 @@ foreach(FILE ${LOCAL_SOURCES}) cm_test(NAME multiprecision_test_${NAME}_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) target_compile_definitions(multiprecision_test_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) target_link_libraries(multiprecision_test_${NAME}_mpf50 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_${NAME}_mpf50 PRIVATE ${GMP_INCLUDES}) endif() if(MPFR_COMPILED) cm_test(NAME multiprecision_test_${NAME}_mpfr50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) target_compile_definitions(multiprecision_test_${NAME}_mpfr50 PUBLIC -DTEST_MPFR_50) target_link_libraries(multiprecision_test_${NAME}_mpfr50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_${NAME}_mpfr50 PRIVATE ${GMP_INCLUDES}) endif() if(MPFI_COMPILED) cm_test(NAME multiprecision_test_${NAME}_mpfi50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) @@ -309,55 +322,55 @@ foreach(FILE ${LOCAL_SOURCES}) target_compile_definitions(multiprecision_test_${NAME}_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) target_link_libraries(multiprecision_test_${NAME}_cpp_bin_float no_eh_support) - if(HAS_FLOAT128) - #TODO: fix it + if(FLOAT128_COMPILED) cm_test(NAME multiprecision_test_${NAME}_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) target_compile_definitions(multiprecision_test_${NAME}_float128 PUBLIC -DTEST_FLOAT128) target_link_libraries(multiprecision_test_${NAME}_float128 no_eh_support) endif() - if(HAS_INTEL_QUAD) - #TODO: fix it + if(INTEL_QUAD_COMPILED) cm_test(NAME multiprecision_test_${NAME}_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) target_compile_definitions(multiprecision_test_${NAME}_intel_quad PUBLIC -DTEST_FLOAT128) target_link_libraries(multiprecision_test_${NAME}_intel_quad no_eh_support) endif() endforeach() - -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_numeric_limits_backend_concept SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) - target_compile_definitions(multiprecision_test_test_numeric_limits_backend_concept PUBLIC -DTEST_BACKEND) - target_link_libraries(multiprecision_test_test_numeric_limits_backend_concept no_eh_support) -endif() +cm_test(NAME multiprecision_test_test_numeric_limits_backend_concept SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) +target_compile_definitions(multiprecision_test_test_numeric_limits_backend_concept PUBLIC -DTEST_BACKEND) +target_link_libraries(multiprecision_test_test_numeric_limits_backend_concept no_eh_support) if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_numeric_limits_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpf50 PUBLIC -DTEST_MPF_50) target_link_libraries(multiprecision_test_test_numeric_limits_mpf50 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_numeric_limits_mpf50 PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_numeric_limits_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpf PUBLIC -DTEST_MPF) target_link_libraries(multiprecision_test_test_numeric_limits_mpf ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_numeric_limits_mpf PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_numeric_limits_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpz PUBLIC -DTEST_MPZ) target_link_libraries(multiprecision_test_test_numeric_limits_mpz ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_numeric_limits_mpz PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_numeric_limits_mpq SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpq PUBLIC -DTEST_MPQ) target_link_libraries(multiprecision_test_test_numeric_limits_mpq ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_numeric_limits_mpq PRIVATE ${GMP_INCLUDES}) endif() if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_numeric_limits_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpfr PUBLIC -DTEST_MPFR) target_link_libraries(multiprecision_test_test_numeric_limits_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_numeric_limits_mpfr PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_numeric_limits_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpfr_50 PUBLIC -DTEST_MPFR_50) target_link_libraries(multiprecision_test_test_numeric_limits_mpfr_50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_numeric_limits_mpfr_50 PRIVATE ${GMP_INCLUDES}) endif() cm_test(NAME multiprecision_test_test_numeric_limits_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) @@ -372,6 +385,7 @@ if(TOMMATH_COMPILED) cm_test(NAME multiprecision_test_test_numeric_limits_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_tommath PUBLIC -DTEST_TOMMATH) target_link_libraries(multiprecision_test_test_numeric_limits_tommath ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_numeric_limits_tommath PRIVATE ${TomMath_INCLUDES}) endif() if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") @@ -379,110 +393,290 @@ if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") target_compile_definitions(multiprecision_test_test_numeric_limits_cpp_int PUBLIC -DTEST_CPP_INT) target_link_libraries(multiprecision_test_test_numeric_limits_cpp_int no_eh_support) endif() -#[[ + if(MPFI_COMPILED) cm_test(NAME multiprecision_test_test_numeric_limits_mpfi_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_mpfi_50 PUBLIC -DTEST_MPFI_50) + target_link_libraries(multiprecision_test_test_numeric_limits_mpfi_50 ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_numeric_limits_mpfi_50 PRIVATE ${MPFI_INCLUDES}) endif() -if(HAS_FLOAT128) +if(FLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_numeric_limits_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_float128 PUBLIC -DTEST_FLOAT128) endif() -if((HAS_INTEL_QUAD) AND (HAS_FLOAT128)) +if((INTEL_QUAD_COMPILED) AND (FLOAT128_COMPILED)) cm_test(NAME multiprecision_test_test_numeric_limits_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_numeric_limits.cpp) target_compile_definitions(multiprecision_test_test_numeric_limits_intel_quad PUBLIC -DTEST_FLOAT128) endif() +cm_test(NAME multiprecision_test_test_sf_import_c99_cpp_dec_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(multiprecision_test_test_sf_import_c99_cpp_dec_float_2 PUBLIC -DTEST_CPP_DEC_FLOAT_2) +cm_test(NAME multiprecision_test_test_sf_import_c99_cpp_dec_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(multiprecision_test_test_sf_import_c99_cpp_dec_float_3 PUBLIC -DTEST_CPP_DEC_FLOAT_3) +cm_test(NAME multiprecision_test_test_sf_import_c99_cpp_dec_float_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(multiprecision_test_test_sf_import_c99_cpp_dec_float_4 PUBLIC -DTEST_CPP_DEC_FLOAT_4) +cm_test(NAME multiprecision_test_test_sf_import_c99_cpp_dec_float_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(multiprecision_test_test_sf_import_c99_cpp_dec_float_5 PUBLIC -DTEST_CPP_DEC_FLOAT_5) +cm_test(NAME multiprecision_test_test_sf_import_c99_cpp_dec_float_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(multiprecision_test_test_sf_import_c99_cpp_dec_float_6 PUBLIC -DTEST_CPP_DEC_FLOAT_6) + +cm_test(NAME multiprecision_test_test_sf_import_c99_cpp_bin_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(multiprecision_test_test_sf_import_c99_cpp_bin_float_2 PUBLIC -DTEST_CPP_BIN_FLOAT_2) +cm_test(NAME multiprecision_test_test_sf_import_c99_cpp_bin_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_sf_import_c99.cpp) +target_compile_definitions(multiprecision_test_test_sf_import_c99_cpp_bin_float_3 PUBLIC -DTEST_CPP_BIN_FLOAT_2) -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - set(LOCAL_SOURCES "") - # TODO: fix test. Reason error: [-fpermissive] - set(LOCAL_SOURCES test_log.cpp test_pow.cpp test_sinh.cpp test_sqrt.cpp test_cosh.cpp test_tanh.cpp test_sin.cpp - test_tan.cpp test_asin.cpp test_atan.cpp test_fpclassify.cpp) - foreach(FILE ${LOCAL_SOURCES}) - get_filename_component(NAME ${FILE} NAME_WE) - if(GMP_COMPILED) - cm_test(NAME multiprecision_test_${NAME}_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) - target_compile_definitions(multiprecision_test_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) - endif() - if(MPFR_COMPILED) - cm_test(NAME multiprecision_test_${NAME}_mpfr50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) - target_compile_definitions(multiprecision_test_${NAME}_mpfr50 PUBLIC -DTEST_MPFR_50) - endif() - if(MPFI_COMPILED) - cm_test(NAME multiprecision_test_${NAME}_mpfi50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) - target_compile_definitions(multiprecision_test_${NAME}_mpfi50 PUBLIC -DTEST_MPFI_50) - endif() - - cm_test(NAME multiprecision_test_${FILE}_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) - target_compile_definitions(multiprecision_test_${FILE}_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) +if(MPFR_COMPILED) + cm_test(NAME multiprecision_test_test_move_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(multiprecision_test_test_move_mpfr PUBLIC -DTEST_MPFR) + target_link_libraries(multiprecision_test_test_move_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) +endif() - cm_test(NAME multiprecision_test_${NAME}_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) - target_compile_definitions(multiprecision_test_${NAME}_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) +if(MPC_COMPILED) + cm_test(NAME multiprecision_test_test_move_mpc SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(multiprecision_test_test_move_mpc PUBLIC -DTEST_MPC) + target_link_libraries(multiprecision_test_test_move_mpc ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) +endif() - if(HAS_FLOAT128) - cm_test(NAME multiprecision_test_${NAME}_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) - target_compile_definitions(multiprecision_test_${NAME}_float128 PUBLIC -DTEST_FLOAT128) - endif() +if(GMP_COMPILED) + cm_test(NAME multiprecision_test_test_move_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(multiprecision_test_test_move_gmp PUBLIC -DTEST_GMP) + target_link_libraries(multiprecision_test_test_move_gmp ${GMP_LIBRARIES} no_eh_support) +endif() - if(HAS_INTEL_QUAD) - cm_test(NAME multiprecision_test_${NAME}_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/${FILE}) - target_compile_definitions(multiprecision_test_${NAME}_intel_quad PUBLIC -DTEST_FLOAT128) - endif() - endforeach() +if(TOMMATH_COMPILED) + cm_test(NAME multiprecision_test_test_move_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) + target_compile_definitions(multiprecision_test_test_move_tommath PUBLIC -DTEST_TOMMATH) + target_link_libraries(multiprecision_test_test_move_tommath ${TomMath_LIBRARIES} no_eh_support) endif() +cm_test(NAME multiprecision_test_test_move_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) +target_compile_definitions(multiprecision_test_test_move_tommath PUBLIC -DTEST_CPP_INT) +target_link_libraries(multiprecision_test_test_move_tommath no_eh_support) + if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_gmp_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_gmp_conversions.cpp) + target_link_libraries(multiprecision_test_test_gmp_conversions ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_gmp_conversions PRIVATE ${GMP_INCLUDES}) endif() if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_mpfr_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfr_conversions.cpp) + target_link_libraries(multiprecision_test_test_mpfr_conversions ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_mpfr_conversions PRIVATE ${GMP_INCLUDES}) +endif() + +if(MPC_COMPILED) + cm_test(NAME multiprecision_test_test_mpc_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfr_conversions.cpp) + target_link_libraries(multiprecision_test_test_mpc_conversions ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_mpc_conversions PRIVATE ${GMP_INCLUDES}) endif() if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_constants_mpf50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) target_compile_definitions(multiprecision_test_test_constants_mpf50 PUBLIC -DTEST_MPF_50) + target_link_libraries(multiprecision_test_test_constants_mpf50 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_constants_mpf50 PRIVATE ${GMP_INCLUDES}) endif() if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_constants_mpfr_50 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) target_compile_definitions(multiprecision_test_test_constants_mpfr_50 PUBLIC -DTEST_MPFR_50) + target_link_libraries(multiprecision_test_test_constants_mpfr_50 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_constants_mpfr_50 PRIVATE ${GMP_INCLUDES}) endif() cm_test(NAME multiprecision_test_test_constants_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constants.cpp) target_compile_definitions(multiprecision_test_test_constants_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) +target_link_libraries(multiprecision_test_test_constants_cpp_dec_float no_eh_support) + +cm_test(NAME multiprecision_test_test_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_test.cpp) + +cm_test(NAME multiprecision_test_test_cpp_int_lit SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_lit.cpp) +target_link_libraries(multiprecision_test_test_cpp_int_lit no_eh_support) + +if ((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPFI_COMPILED) AND (TOMMATH_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME multiprecision_test_test_convert_from_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_int.cpp) + target_link_libraries(multiprecision_test_test_convert_from_cpp_int ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_cpp_int PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_mpz_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpz_int.cpp) + target_link_libraries(multiprecision_test_test_convert_from_mpz_int ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_mpz_int PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_tom_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_tom_int.cpp) + target_link_libraries(multiprecision_test_test_convert_from_tom_int ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_tom_int PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_cpp_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_rational.cpp) + target_link_libraries(multiprecision_test_test_convert_from_cpp_rational ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_cpp_rational PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_gmp_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_gmp_rational.cpp) + target_link_libraries(test_convert_from_gmp_rational ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_gmp_rational PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_tom_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_tom_rational.cpp) + target_link_libraries(test_convert_from_tom_rational ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_tom_rational PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_bin_float.cpp) + target_link_libraries(test_convert_from_cpp_bin_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_cpp_bin_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_dec_float.cpp) + target_link_libraries(test_convert_from_cpp_dec_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_cpp_dec_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_mpf_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpf_float.cpp) + target_link_libraries(test_convert_from_mpf_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_mpf_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_mpfr_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpfr_float.cpp) + target_link_libraries(test_convert_from_mpfr_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_mpfr_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_mpfi_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpfi_float.cpp) + target_link_libraries(test_convert_from_mpfi_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_mpfi_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + + cm_test(NAME multiprecision_test_test_convert_from_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_float128.cpp) + target_link_libraries(test_convert_from_float128 ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_convert_from_float128 PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) + +endif() + +cm_test(NAME multiprecision_test_test_cpp_bin_float_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_conv.cpp) + +cm_test(NAME multiprecision_test_test_cpp_bin_float_io_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_io.cpp) +target_compile_definitions(multiprecision_test_test_cpp_bin_float_io_1 PUBLIC -DTEST1 -DTEST_CPP_BIN_FLOAT) + +cm_test(NAME multiprecision_test_test_cpp_bin_float_io_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_io.cpp) +target_compile_definitions(multiprecision_test_test_cpp_bin_float_io_2 PUBLIC -DTEST2 -DTEST_CPP_BIN_FLOAT) if(MPFR_COMPILED) - cm_test(NAME multiprecision_test_test_move_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) - target_compile_definitions(multiprecision_test_test_move_mpfr PUBLIC -DTEST_MPFR) + cm_test(NAME multiprecision_test_test_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float.cpp) + target_compile_definitions(multiprecision_test_test_cpp_bin_float PUBLIC -DTEST_MPFR) + target_link_libraries(multiprecision_test_test_cpp_bin_float ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_cpp_bin_float PRIVATE ${GMP_INCLUDES}) endif() +cm_test(NAME multiprecision_test_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) +target_compile_definitions(multiprecision_test_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) +target_link_libraries(multiprecision_test_cpp_dec_float no_eh_support) + if(GMP_COMPILED) - cm_test(NAME multiprecision_test_test_move_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) - target_compile_definitions(multiprecision_test_test_move_gmp PUBLIC -DTEST_GMP) + cm_test(NAME multiprecision_test_test_float_io_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(multiprecision_test_test_float_io_mpf PUBLIC -DTEST_MPF_50) + target_link_libraries(multiprecision_test_test_float_io_mpf ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_float_io_mpf PRIVATE ${GMP_INCLUDES}) +endif() + +if(MPFR_COMPILED) + cm_test(NAME multiprecision_test_test_float_io_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(multiprecision_test_test_float_io_mpfr PUBLIC -DTEST_MPFR_50) + target_link_libraries(multiprecision_test_test_float_io_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_float_io_mpfr PRIVATE ${GMP_INCLUDES}) +endif() + +if(MPFI_COMPILED) + cm_test(NAME multiprecision_test_test_float_io_mpfi SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(multiprecision_test_test_float_io_mpfi PUBLIC -DTEST_MPFI_50) + target_link_libraries(multiprecision_test_test_float_io_mpfi ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_float_io_mpfi PRIVATE ${GMP_INCLUDES} ${MPFI_INCLUDES}) +endif() + +if(FLOAT128_COMPILED) + cm_test(NAME multiprecision_test_test_float_io_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(multiprecision_test_test_float_io_float128 PUBLIC -DTEST_FLOAT128) + target_link_libraries(multiprecision_test_test_float_io_float128 ${QUADMATH_LIBRARIES} no_eh_support) +endif() + +if((INTEL_QUAD_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME multiprecision_test_test_float_io_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) + target_compile_definitions(multiprecision_test_test_float_io_intel_quad PUBLIC -DTEST_FLOAT128) + target_link_libraries(multiprecision_test_test_float_io_intel_quad no_eh_support) endif() if(TOMMATH_COMPILED) - cm_test(NAME multiprecision_test_test_move_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) - target_compile_definitions(multiprecision_test_test_move_tommath PUBLIC -DTEST_TOMMATH) + cm_test(NAME multiprecision_test_test_int_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) + target_compile_definitions(multiprecision_test_test_int_io_tommath PUBLIC -DTEST_TOMMATH) + target_link_libraries(multiprecision_test_test_int_io_tommath ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_int_io_tommath PRIVATE ${TomMath_INCLUDES}) endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_move_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) - target_compile_definitions(multiprecision_test_test_move_cpp_int PUBLIC -DTEST_CPP_INT) +if(GMP_COMPILED) + cm_test(NAME multiprecision_test_test_int_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) + target_compile_definitions(multiprecision_test_test_int_io_mpz PUBLIC -DTEST_MPZ) + target_link_libraries(multiprecision_test_test_int_io_mpz ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_int_io_mpz PRIVATE ${GMP_INCLUDES}) endif() -cm_test(NAME multiprecision_test_test_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_test.cpp) +cm_test(NAME multiprecision_test_test_int_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) +target_compile_definitions(multiprecision_test_test_int_io_cpp_int PUBLIC -DTEST_CPP_INT) +target_link_libraries(multiprecision_test_test_int_io_cpp_int no_eh_support) -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_cpp_int_lit SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_lit.cpp) +if(GMP_COMPILED) + cm_test(NAME multiprecision_test_test_cpp_int_left_shift SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_left_shift.cpp) + target_link_libraries(multiprecision_test_test_cpp_int_left_shift ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_cpp_int_left_shift PRIVATE ${GMP_INCLUDES}) + + cm_test(NAME multiprecision_test_test_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(multiprecision_test_test_cpp_int_1 PUBLIC -DTEST1) + target_link_libraries(multiprecision_test_test_cpp_int_1 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_cpp_int_1 PRIVATE ${GMP_INCLUDES}) + + cm_test(NAME multiprecision_test_test_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(multiprecision_test_test_cpp_int_2 PUBLIC -DTEST2) + target_link_libraries(multiprecision_test_test_cpp_int_2 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_cpp_int_2 PRIVATE ${GMP_INCLUDES}) + + cm_test(NAME multiprecision_test_test_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(multiprecision_test_test_cpp_int_3 PUBLIC -DTEST3) + target_link_libraries(multiprecision_test_test_cpp_int_3 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_cpp_int_3 PRIVATE ${GMP_INCLUDES}) + + cm_test(NAME multiprecision_test_test_cpp_int_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(multiprecision_test_test_cpp_int_4 PUBLIC -DTEST4) + target_link_libraries(multiprecision_test_test_cpp_int_4 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_cpp_int_4 PRIVATE ${GMP_INCLUDES}) + + cm_test(NAME multiprecision_test_test_cpp_int_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) + target_compile_definitions(multiprecision_test_test_cpp_int_5 PUBLIC -DTEST5) + target_link_libraries(multiprecision_test_test_cpp_int_5 ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_cpp_int_5 PRIVATE ${GMP_INCLUDES}) endif() -if((HAS_FLOAT128) AND (HAS_INTEL_QUAD)) +cm_test(NAME multiprecision_test_test_checked_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_checked_cpp_int.cpp) +target_link_libraries(multiprecision_test_test_checked_cpp_int no_eh_support) +cm_test(NAME multiprecision_test_test_unchecked_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_unchecked_cpp_int.cpp) +target_link_libraries(multiprecision_test_test_unchecked_cpp_int no_eh_support) + +cm_test(NAME multiprecision_test_test_cpp_int_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) +target_compile_definitions(multiprecision_test_test_cpp_int_serial_1 PUBLIC -DTEST1) +cm_test(NAME multiprecision_test_test_cpp_int_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) +target_compile_definitions(multiprecision_test_test_cpp_int_serial_2 PUBLIC -DTEST2) +cm_test(NAME multiprecision_test_test_cpp_int_serial_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) +target_compile_definitions(multiprecision_test_test_cpp_int_serial_3 PUBLIC -DTEST3) +cm_test(NAME multiprecision_test_test_cpp_int_serial_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) +target_compile_definitions(multiprecision_test_test_cpp_int_serial_4 PUBLIC -DTEST4) + +cm_test(NAME multiprecision_test_test_cpp_int_deserial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_deserial.cpp) +cm_test(NAME multiprecision_test_test_cpp_rat_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_rat_serial.cpp) + +if((FLOAT128_COMPILED) AND (QUADMATH_COMPILED)) cm_test(NAME multiprecision_test_test_constexpr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_constexpr.cpp COMPILE_ONLY) target_compile_definitions(multiprecision_test_test_constexpr PUBLIC -DHAVE_FLOAT128) endif() @@ -493,8 +687,7 @@ cm_test(NAME multiprecision_test_test_nothrow_cpp_rational SOURCES ${CURRENT_TES cm_test(NAME multiprecision_test_test_nothrow_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_bin_float.cpp COMPILE_ONLY) cm_test(NAME multiprecision_test_test_nothrow_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_cpp_dec_float.cpp COMPILE_ONLY) - -if(HAS_FLOAT128) +if(FLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_nothrow_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_float128.cpp COMPILE_ONLY) endif() @@ -506,141 +699,88 @@ if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_nothrow_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_nothrow_mpfr.cpp COMPILE_ONLY) endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_cpp_bin_float_io_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_io.cpp) - target_compile_definitions(multiprecision_test_test_cpp_bin_float_io_1 PUBLIC -DTEST1 -DTEST_CPP_BIN_FLOAT) - - cm_test(NAME multiprecision_test_test_cpp_bin_float_io_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_io.cpp) - target_compile_definitions(multiprecision_test_test_cpp_bin_float_io_2 PUBLIC -DTEST2 -DTEST_CPP_BIN_FLOAT) - - if(MPFR_COMPILED) - cm_test(NAME multiprecision_test_test_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float.cpp) - target_compile_definitions(multiprecision_test_test_cpp_bin_float PUBLIC -DTEST_MPFR) - endif() - - cm_test(NAME multiprecision_test_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) - target_compile_definitions(multiprecision_test_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) - - if(GMP_COMPILED) - cm_test(NAME multiprecision_test_test_float_io_mpf SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) - target_compile_definitions(multiprecision_test_test_float_io_mpf PUBLIC -DTEST_MPF_50) - endif() - - if(MPFR_COMPILED) - cm_test(NAME multiprecision_test_test_float_io_mpfr SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) - target_compile_definitions(multiprecision_test_test_float_io_mpfr PUBLIC -DTEST_MPFR_50) - endif() - - if(MPFI_COMPILED) - cm_test(NAME multiprecision_test_test_float_io_mpfi SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) - target_compile_definitions(multiprecision_test_test_float_io_mpfi PUBLIC -DTEST_MPFI_50) - endif() - - if(HAS_FLOAT128) - cm_test(NAME multiprecision_test_test_float_io_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) - target_compile_definitions(multiprecision_test_test_float_io_float128 PUBLIC -DTEST_FLOAT128) - endif() - - if((HAS_INTEL_QUAD) AND (HAS_FLOAT128)) - cm_test(NAME multiprecision_test_test_float_io_intel_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) - target_compile_definitions(multiprecision_test_test_float_io_intel_quad PUBLIC -DTEST_FLOAT128) - endif() - - if(TOMMATH_COMPILED) - cm_test(NAME multiprecision_test_test_int_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) - target_compile_definitions(multiprecision_test_test_int_io_tommath PUBLIC -DTEST_TOMMATH) - endif() - - if(GMP_COMPILED) - cm_test(NAME multiprecision_test_test_int_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) - target_compile_definitions(multiprecision_test_test_int_io_mpz PUBLIC -DTEST_MPZ) - endif() - - cm_test(NAME multiprecision_test_test_int_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_int_io.cpp) - target_compile_definitions(multiprecision_test_test_int_io_cpp_int PUBLIC -DTEST_CPP_INT) - - if(GMP_COMPILED) - cm_test(NAME multiprecision_test_test_cpp_int_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) - target_compile_definitions(multiprecision_test_test_cpp_int_1 PUBLIC -DTEST1) - - cm_test(NAME multiprecision_test_test_cpp_int_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) - target_compile_definitions(multiprecision_test_test_cpp_int_2 PUBLIC -DTEST2) - - cm_test(NAME multiprecision_test_test_cpp_int_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int.cpp) - target_compile_definitions(multiprecision_test_test_cpp_int_3 PUBLIC -DTEST2) - endif() +if(GMP_COMPILED) + cm_test(NAME multiprecision_test_test_miller_rabin SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_miller_rabin.cpp) + target_link_libraries(multiprecision_test_test_miller_rabin ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_miller_rabin PRIVATE ${GMP_INCLUDES}) endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_checked_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_checked_cpp_int.cpp) +if(TOMMATH_COMPILED) + cm_test(NAME multiprecision_test_test_rational_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) + target_compile_definitions(multiprecision_test_test_rational_io_tommath PUBLIC -DTEST_TOMMATH) + target_link_libraries(multiprecision_test_test_rational_io_tommath ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_rational_io_tommath PRIVATE ${TomMath_INCLUDES}) endif() if(GMP_COMPILED) - cm_test(NAME multiprecision_test_test_miller_rabin SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_miller_rabin.cpp) + cm_test(NAME multiprecision_test_test_rational_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) + target_compile_definitions(multiprecision_test_test_rational_io_mpz PUBLIC -DTEST_MPQ) + target_link_libraries(multiprecision_test_test_rational_io_mpz ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_rational_io_mpz PRIVATE ${GMP_INCLUDES}) endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - if(TOMMATH_COMPILED) - cm_test(NAME multiprecision_test_test_rational_io_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) - target_compile_definitions(multiprecision_test_test_rational_io_tommath PUBLIC -DTEST_TOMMATH) - endif() - - if(GMP_COMPILED) - cm_test(NAME multiprecision_test_test_rational_io_mpz SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) - target_compile_definitions(multiprecision_test_test_rational_io_mpz PUBLIC -DTEST_MPQ) - endif() - - cm_test(NAME multiprecision_test_test_rational_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) - target_compile_definitions(multiprecision_test_test_rational_io_cpp_int PUBLIC -DTEST_CPP_INT) -endif() +cm_test(NAME multiprecision_test_test_rational_io_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rational_io.cpp) +target_compile_definitions(multiprecision_test_test_rational_io_cpp_int PUBLIC -DTEST_CPP_INT) +target_link_libraries(multiprecision_test_test_rational_io_cpp_int ${GMP_LIBRARIES} no_eh_support) if((GMP_COMPILED) AND (TOMMATH_COMPILED) AND (MPFR_COMPILED)) cm_test(NAME multiprecision_test_test_generic_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_generic_conv.cpp) target_compile_definitions(multiprecision_test_test_generic_conv PUBLIC -DTEST_GMP -DTEST_TOMMATH -DTEST_MPFR) - + target_link_libraries(multiprecision_test_test_generic_conv ${TomMath_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_generic_conv PRIVATE ${GMP_INCLUDES}) endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_rat_float_interconv_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) - target_compile_definitions(multiprecision_test_test_rat_float_interconv_1 PUBLIC TEST1) +cm_test(NAME multiprecision_test_test_rat_float_interconv_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) +target_compile_definitions(multiprecision_test_test_rat_float_interconv_1 PUBLIC -DTEST1) +target_link_libraries(multiprecision_test_test_rat_float_interconv_1 no_eh_support) - cm_test(NAME multiprecision_test_test_rat_float_interconv_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) - target_compile_definitions(multiprecision_test_test_rat_float_interconv_2 PUBLIC TEST2) +cm_test(NAME multiprecision_test_test_rat_float_interconv_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) +target_compile_definitions(multiprecision_test_test_rat_float_interconv_2 PUBLIC -DTEST2) +target_link_libraries(multiprecision_test_test_rat_float_interconv_2 no_eh_support) - cm_test(NAME multiprecision_test_test_rat_float_interconv_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) - target_compile_definitions(multiprecision_test_test_rat_float_interconv_3 PUBLIC TEST3) +cm_test(NAME multiprecision_test_test_rat_float_interconv_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) +target_compile_definitions(multiprecision_test_test_rat_float_interconv_3 PUBLIC -DTEST3) +target_link_libraries(multiprecision_test_test_rat_float_interconv_3 no_eh_support) - cm_test(NAME multiprecision_test_test_rat_float_interconv_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) - target_compile_definitions(multiprecision_test_test_rat_float_interconv_4 PUBLIC TEST4) -endif() +cm_test(NAME multiprecision_test_test_rat_float_interconv_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) +target_compile_definitions(multiprecision_test_test_rat_float_interconv_4 PUBLIC -DTEST4) +target_link_libraries(multiprecision_test_test_rat_float_interconv_4 no_eh_support) if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_rat_float_interconv_5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) target_compile_definitions(multiprecision_test_test_rat_float_interconv_5 PUBLIC -DTEST5) + target_link_libraries(multiprecision_test_test_rat_float_interconv_5 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_rat_float_interconv_5 PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_rat_float_interconv_6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) target_compile_definitions(multiprecision_test_test_rat_float_interconv_6 PUBLIC -DTEST6) + target_link_libraries(multiprecision_test_test_rat_float_interconv_6 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_rat_float_interconv_6 PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_rat_float_interconv_7 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) target_compile_definitions(multiprecision_test_test_rat_float_interconv_7 PUBLIC -DTEST7) + target_link_libraries(multiprecision_test_test_rat_float_interconv_7 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_rat_float_interconv_7 PRIVATE ${GMP_INCLUDES}) cm_test(NAME multiprecision_test_test_rat_float_interconv_8 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rat_float_interconv.cpp) target_compile_definitions(multiprecision_test_test_rat_float_interconv_8 PUBLIC -DTEST8) + target_link_libraries(multiprecision_test_test_rat_float_interconv_8 ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_rat_float_interconv_8 PRIVATE ${GMP_INCLUDES}) endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_cpp_int_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_conv.cpp) - cm_test(NAME multiprecision_test_test_native_integer SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_native_integer.cpp) - cm_test(NAME multiprecision_test_test_mixed_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_int.cpp) +cm_test(NAME multiprecision_test_test_cpp_int_conv SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_conv.cpp) +target_link_libraries(multiprecision_test_test_cpp_int_conv no_eh_support) +cm_test(NAME multiprecision_test_test_cpp_int_import_export SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_import_export.cpp) +target_link_libraries(multiprecision_test_test_cpp_int_import_export no_eh_support) +cm_test(NAME multiprecision_test_test_native_integer SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_native_integer.cpp) +target_link_libraries(multiprecision_test_test_native_integer no_eh_support) - if((GMP_COMPILED) AND (MPFR_COMPILED)) - cm_test(NAME multiprecision_test_test_mixed_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_float.cpp) - endif() +cm_test(NAME multiprecision_test_test_mixed_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_int.cpp) +target_link_libraries(multiprecision_test_test_mixed_cpp_int no_eh_support) + +if((GMP_COMPILED) AND (MPFR_COMPILED)) + cm_test(NAME multiprecision_test_test_mixed_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_float.cpp) + target_link_libraries(multiprecision_test_test_mixed_float ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) endif() if(MPFR_COMPILED) @@ -660,21 +800,25 @@ cm_test(NAME multiprecision_test_ublas_interop_test1 SOURCES ${CURRENT_TEST_SOUR ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test11.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test12.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test13.cpp) - +target_link_libraries(multiprecision_test_ublas_interop_test1 no_eh_support) cm_test(NAME multiprecision_test_ublas_interop_test2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test2.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test21.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test22.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test23.cpp) +target_link_libraries(multiprecision_test_ublas_interop_test2 no_eh_support) #run ublas_interop/test3.cpp ublas_interop/test31.cpp ublas_interop/test32.cpp ublas_interop/test33.cpp ; cm_test(NAME multiprecision_test_ublas_interop_test4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test4.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test42.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test43.cpp) +target_link_libraries(multiprecision_test_ublas_interop_test4 no_eh_support) cm_test(NAME multiprecision_test_ublas_interop_test5 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test5.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test52.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test53.cpp) +target_link_libraries(multiprecision_test_ublas_interop_test5 no_eh_support) cm_test(NAME multiprecision_test_ublas_interop_test6 SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test6.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test62.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test63.cpp) +target_link_libraries(multiprecision_test_ublas_interop_test6 no_eh_support) #run ublas_interop/test7.cpp ublas_interop/test71.cpp ublas_interop/test72.cpp ublas_interop/test73.cpp ; cm_test(NAME multiprecision_test_ublas_interop_test1_et SOURCES @@ -682,174 +826,365 @@ cm_test(NAME multiprecision_test_ublas_interop_test1_et SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test11.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test12.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test13.cpp) -target_include_directories(multiprecision_test_ublas_interop_test1_et PUBLIC -DTEST_ET=1) +target_link_libraries(multiprecision_test_ublas_interop_test1_et no_eh_support) +target_compile_definitions(multiprecision_test_ublas_interop_test1_et PUBLIC -DTEST_ET=1) cm_test(NAME multiprecision_test_ublas_interop_test2_et SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test2.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test21.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test22.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test23.cpp) -target_include_directories(multiprecision_test_ublas_interop_test2_et PUBLIC -DTEST_ET=1) +target_link_libraries(multiprecision_test_ublas_interop_test2_et no_eh_support) +target_compile_definitions(multiprecision_test_ublas_interop_test2_et PUBLIC -DTEST_ET=1) #run ublas_interop/test3.cpp ublas_interop/test31.cpp ublas_interop/test32.cpp ublas_interop/test33.cpp ; cm_test(NAME multiprecision_test_ublas_interop_test4_et SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test4.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test42.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test43.cpp) -target_include_directories(multiprecision_test_ublas_interop_test4_et PUBLIC -DTEST_ET=1) +target_link_libraries(multiprecision_test_ublas_interop_test4_et no_eh_support) +target_compile_definitions(multiprecision_test_ublas_interop_test4_et PUBLIC -DTEST_ET=1) cm_test(NAME multiprecision_test_ublas_interop_test5_et SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test5.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test52.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test53.cpp) -target_include_directories(multiprecision_test_ublas_interop_test5_et PUBLIC -DTEST_ET=1) +target_link_libraries(multiprecision_test_ublas_interop_test5_et no_eh_support) +target_compile_definitions(multiprecision_test_ublas_interop_test5_et PUBLIC -DTEST_ET=1) cm_test(NAME multiprecision_test_ublas_interop_test6_et SOURCES ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test6.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test62.cpp ${CURRENT_TEST_SOURCES_DIR}/ublas_interop/test63.cpp) -target_include_directories(multiprecision_test_ublas_interop_test6_et PUBLIC -DTEST_ET=1) - +target_link_libraries(multiprecision_test_ublas_interop_test6_et no_eh_support) +target_compile_definitions(multiprecision_test_ublas_interop_test6_et PUBLIC -DTEST_ET=1) #run ublas_interop/test7.cpp ublas_interop/test71.cpp ublas_interop/test72.cpp ublas_interop/test73.cpp ; -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_cpp_int_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) - target_compile_definitions(multiprecision_test_test_cpp_int_serial_1 PUBLIC -DTEST1) - cm_test(NAME multiprecision_test_test_cpp_int_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) - target_compile_definitions(multiprecision_test_test_cpp_int_serial_2 PUBLIC -DTEST2) - cm_test(NAME multiprecision_test_test_cpp_int_serial_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) - target_compile_definitions(multiprecision_test_test_cpp_int_serial_3 PUBLIC -DTEST3) - cm_test(NAME multiprecision_test_test_cpp_int_serial_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_serial.cpp) - target_compile_definitions(multiprecision_test_test_cpp_int_serial_4 PUBLIC -DTEST4) - cm_test(NAME multiprecision_test_test_cpp_int_deserial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_deserial.cpp) - cm_test(NAME multiprecision_test_test_cpp_rat_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_rat_serial.cpp) - cm_test(NAME multiprecision_test_test_adapt_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_adapt_serial.cpp) - cm_test(NAME multiprecision_test_test_cpp_dec_float_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_serial.cpp) - target_compile_definitions(multiprecision_test_test_cpp_dec_float_serial_1 PUBLIC -DTEST1) - cm_test(NAME multiprecision_test_test_cpp_dec_float_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_serial.cpp) - target_compile_definitions(multiprecision_test_test_cpp_dec_float_serial_2 PUBLIC -DTEST2) -endif() - -if(HAS_FLOAT128) - cm_test(NAME multiprecision_test_test_float128_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float128_serial.cpp) -endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # TODO: fix test. Reason error: [-fpermissive] - cm_test(NAME multiprecision_test_test_bin_dec_float_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_serial.cpp) - target_compile_definitions(multiprecision_test_test_bin_dec_float_serial_1 PUBLIC TEST1) +cm_test(NAME multiprecision_test_test_adapt_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_adapt_serial.cpp) +cm_test(NAME multiprecision_test_test_cpp_dec_float_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_serial.cpp) +target_compile_definitions(multiprecision_test_test_cpp_dec_float_serial_1 PUBLIC -DTEST1) +cm_test(NAME multiprecision_test_test_cpp_dec_float_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_dec_float_serial.cpp) +target_compile_definitions(multiprecision_test_test_cpp_dec_float_serial_2 PUBLIC -DTEST2) - cm_test(NAME multiprecision_test_test_bin_dec_float_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_serial.cpp) - target_compile_definitions(multiprecision_test_test_bin_dec_float_serial_2 PUBLIC TEST2) - - cm_test(NAME multiprecision_test_test_checked_mixed_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_checked_mixed_cpp_int.cpp) - cm_test(NAME multiprecision_test_test_mixed_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_bin_float.cpp) - cm_test(NAME multiprecision_test_test_mixed_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_dec_float.cpp) +if(QUADMATH_COMPILED) + cm_test(NAME multiprecision_test_test_float128_serial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float128_serial.cpp) endif() - +#TODO: Enable this +#[[ +cm_test(NAME multiprecision_test_test_bin_dec_float_serial_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_serial.cpp) +target_compile_definitions(multiprecision_test_test_bin_dec_float_serial_1 PUBLIC -DTEST1) +cm_test(NAME multiprecision_test_test_bin_dec_float_serial_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_bin_float_serial.cpp) +target_compile_definitions(multiprecision_test_test_bin_dec_float_serial_2 PUBLIC -DTEST2) +]] +cm_test(NAME multiprecision_test_test_checked_mixed_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_checked_mixed_cpp_int.cpp) +target_link_libraries(multiprecision_test_test_checked_mixed_cpp_int no_eh_support) +cm_test(NAME multiprecision_test_test_mixed_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_bin_float.cpp) +target_link_libraries(multiprecision_test_test_mixed_cpp_bin_float no_eh_support) +cm_test(NAME multiprecision_test_test_mixed_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_cpp_dec_float.cpp) +target_link_libraries(multiprecision_test_test_mixed_cpp_dec_float no_eh_support) if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_mixed_mpf_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_mpf_float.cpp) + target_link_libraries(multiprecision_test_test_mixed_mpf_float ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_mixed_mpf_float PRIVATE ${GMP_INCLUDES}) endif() if(MPFR_COMPILED) cm_test(NAME multiprecision_test_test_mixed_mpfr_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixed_mpfr_float.cpp) + target_link_libraries(multiprecision_test_test_mixed_mpfr_float ${MPFR_LIBRARIES} ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_test_mixed_mpfr_float PRIVATE ${GMP_INCLUDES}) endif() -file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/*.cpp) -# reason error: right operand of shift expression ‘(1u << 63u)’ is >= than the precision of the left operand [-fpermissive] -set(TEST_FILES "") +cm_test(NAME multiprecision_test_test_float_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_conversions.cpp) +target_link_libraries(multiprecision_test_test_float_conversions no_eh_support) -foreach(FILEB ${TEST_FILES}) - get_filename_component(NAME ${FILEB} NAME_WE) - if(MPFR_COMPILED) - cm_test(NAME multiprecision_test_math_${NAME}_mpfr SOURCES ${FILEB}) - target_compile_definitions(multiprecision_test_math_${NAME}_mpfr PRIVATE -DTEST_MPFR_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) - target_include_directories(multiprecision_test_math_${NAME}_mpfr PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) - endif() +cm_test(NAME multiprecision_test_bug11922 SOURCES ${CURRENT_TEST_SOURCES_DIR}/bug11922.cpp COMPILE_ONLY) - if(GMP_COMPILED) - cm_test(NAME multiprecision_test_math_${NAME}_mpf SOURCES ${FILEB}) - target_compile_definitions(multiprecision_test_math_${NAME}_mpf PRIVATE -DTEST_MPF_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) - target_include_directories(multiprecision_test_math_${NAME}_mpf PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) - endif() +cm_test(NAME multiprecision_test_bug12039 SOURCES ${CURRENT_TEST_SOURCES_DIR}/bug12039.cpp) +target_link_libraries(multiprecision_test_bug12039 no_eh_support) + +cm_test(NAME multiprecision_test_git_issue_30 SOURCES ${CURRENT_TEST_SOURCES_DIR}/git_issue_30.cpp COMPILE_ONLY) +cm_test(NAME multiprecision_test_git_issue_98 SOURCES ${CURRENT_TEST_SOURCES_DIR}/git_issue_98.cpp COMPILE_ONLY) - cm_test(NAME multiprecision_test_math_${NAME}_cpp_dec_float SOURCES ${FILEB}) - target_compile_definitions(multiprecision_test_math_${NAME}_cpp_dec_float PRIVATE -DTEST_CPP_DEC_FLOAT -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) - target_include_directories(multiprecision_test_math_${NAME}_cpp_dec_float PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) +if ((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPC_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME multiprecision_test_git_issue_98 ${CURRENT_TEST_SOURCES_DIR}/git_issue_98.cpp COMPILE_ONLY) + target_link_libraries(multiprecision_test_git_issue_98 ${QUADMATH_LIBRARIES} ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_compile_definitions(multiprecision_test_git_issue_98 PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPC -DFLOAT128_COMPILED) +endif() - cm_test(NAME multiprecision_test_math_${NAME}_cpp_bin_float SOURCES ${FILEB}) - target_compile_definitions(multiprecision_test_math_${NAME}_cpp_bin_float PRIVATE -DTEST_CPP_BIN_FLOAT -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) - target_include_directories(multiprecision_test_math_${NAME}_cpp_bin_float PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) +cm_test(NAME multiprecision_test_issue_13301 SOURCES ${CURRENT_TEST_SOURCES_DIR}/issue_13301.cpp) +cm_test(NAME multiprecision_test_issue_13148 SOURCES ${CURRENT_TEST_SOURCES_DIR}/issue_13148.cpp) - if(HAS_FLOAT128) - cm_test(NAME multiprecision_test_math_${NAME}_float128 SOURCES ${FILEB}) - target_compile_definitions(multiprecision_test_math_${NAME}_float128 PRIVATE -DTEST_FLOAT128 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) - target_include_directories(multiprecision_test_math_${NAME}_float128 PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) - endif() +if ((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPFI_COMPILED) AND (TomMath_COMPILED) AND (FLOAT128_COMPILED)) + cm_test(NAME multiprecision_test_test_hash ${CURRENT_TEST_SOURCES_DIR}/test_hash.cpp COMPILE_ONLY) + target_link_libraries(multiprecision_test_test_hash ${QUADMATH_LIBRARIES} ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} + ${GMP_LIBRARIES} ${TomMath_LIBRARIES}) + target_compile_definitions(multiprecision_test_test_hash PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) +endif() - if((HAS_FLOAT128) AND (HAS_INTEL_QUAD)) - cm_test(NAME multiprecision_test_math_${NAME}_intel_quad SOURCES ${FILEB}) - target_compile_definitions(multiprecision_test_math_${NAME}_intel_quad PRIVATE -DTEST_FLOAT128 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) - target_include_directories(multiprecision_test_math_${NAME}_intel_quad PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) - endif() -endforeach() +cm_test(NAME multiprecision_test_test_optional_compat SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_optional_compat.cpp) -file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/high_prec/*.cpp) -# reason error: right operand of shift expression ‘(1u << 63u)’ is >= than the precision of the left operand [-fpermissive] -list(REMOVE_ITEM TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/high_prec/test_gamma.cpp) +# TODO: Fix this +#[[ +if (EIGEN_COMPILED) + cm_test(NAME multiprecision_test_test_eigen_interop_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_int.cpp) + target_include_directories(multiprecision_test_test_eigen_interop_cpp_int PRIVATE ${EIGEN3_INCLUDE_DIR}) -foreach(FILEB ${TEST_FILES}) - get_filename_component(NAME ${FILEB} NAME_WE) - cm_test(NAME multiprecision_test_math_high_prec_${NAME} SOURCES ${FILEB}) - if(MPFR_COMPILED) - target_compile_definitions(multiprecision_test_math_high_prec_${NAME} PRIVATE -DTEST_MPFR) - endif() - target_compile_definitions(multiprecision_test_math_high_prec_${NAME} PRIVATE -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE -DBOOST_ALL_NO_LIB) - target_include_directories(multiprecision_test_math_high_prec_${NAME} PRIVATE ${CURRENT_TEST_SOURCES_DIR}/../../math/include_private) -endforeach() + cm_test(NAME multiprecision_test_test_eigen_interop_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_dec_float.cpp) + target_include_directories(multiprecision_test_test_eigen_interop_cpp_dec_float PRIVATE ${EIGEN3_INCLUDE_DIR}) + + cm_test(NAME multiprecision_test_test_eigen_interop_cpp_dec_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_dec_float_2.cpp) + target_include_directories(multiprecision_test_test_eigen_interop_cpp_dec_float_2 PRIVATE ${EIGEN3_INCLUDE_DIR}) + + cm_test(NAME multiprecision_test_test_eigen_interop_cpp_dec_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_dec_float_3.cpp) + target_include_directories(multiprecision_test_test_eigen_interop_cpp_dec_float_3 PRIVATE ${EIGEN3_INCLUDE_DIR}) + + cm_test(NAME multiprecision_test_test_eigen_interop_cpp_bin_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_bin_float_1.cpp) + target_include_directories(multiprecision_test_test_eigen_interop_cpp_bin_float_1 PRIVATE ${EIGEN3_INCLUDE_DIR}) + + cm_test(NAME multiprecision_test_test_eigen_interop_cpp_bin_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_bin_float_2.cpp) + target_include_directories(multiprecision_test_test_eigen_interop_cpp_bin_float_2 PRIVATE ${EIGEN3_INCLUDE_DIR}) + cm_test(NAME multiprecision_test_test_eigen_interop_cpp_bin_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_cpp_bin_float_3.cpp) + target_include_directories(multiprecision_test_test_eigen_interop_cpp_bin_float_3 PRIVATE ${EIGEN3_INCLUDE_DIR}) +endif() + +if ((EIGEN_COMPILED) AND (MPFR_COMPILED)) + cm_test(NAME multiprecision_test_test_eigen_interop_mpfr_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_mpfr_1.cpp) + target_link_libraries(multiprecision_test_test_eigen_interop_mpfr_1 ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_eigen_interop_mpfr_1 PRIVATE ${EIGEN3_INCLUDE_DIR} ${GMP_INCLUDES}) + + cm_test(NAME multiprecision_test_test_eigen_interop_mpfr_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_mpfr_2.cpp) + target_link_libraries(multiprecision_test_test_eigen_interop_mpfr_2 ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_eigen_interop_mpfr_2 PRIVATE ${EIGEN3_INCLUDE_DIR} ${GMP_INCLUDES}) + + cm_test(NAME multiprecision_test_test_eigen_interop_mpfr_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_mpfr_3.cpp) + target_link_libraries(multiprecision_test_test_eigen_interop_mpfr_3 ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_eigen_interop_mpfr_3 PRIVATE ${EIGEN3_INCLUDE_DIR} ${GMP_INCLUDES}) +endif() + +if ((EIGEN_COMPILED) AND (GMP_COMPILED)) + cm_test(NAME multiprecision_test_test_eigen_interop_gmp SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_gmp.cpp) + target_link_libraries(multiprecision_test_test_eigen_interop_gmp ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_eigen_interop_gmp PRIVATE ${EIGEN3_INCLUDE_DIR} ${GMP_INCLUDES}) +endif() + +if ((EIGEN_COMPILED) AND (MPC_COMPILED)) + cm_test(NAME multiprecision_test_test_eigen_interop_mpc SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_eigen_interop_mpc.cpp) + target_link_libraries(multiprecision_test_test_eigen_interop_mpc ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_test_eigen_interop_mpc PUBLIC ${EIGEN3_INCLUDE_DIR} ${GMP_INCLUDES}) +endif() +#]] + +#TODO: enable it +#[[ +if (BUILD_WITH_SOURCES_DIR) + file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/*.cpp) + foreach(FILEB ${TEST_FILES}) + get_filename_component(NAME ${FILEB} NAME_WE) + if(MPFR_COMPILED) + cm_test(NAME multiprecision_test_math_${NAME}_mpfr SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_mpfr PRIVATE -DTEST_MPFR_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_mpfr PRIVATE ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private ${BUILD_WITH_SOURCES_DIR} ${GMP_INCLUDES}) + target_link_libraries(multiprecision_test_math_${NAME}_mpfr ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + endif() + + if(GMP_COMPILED) + cm_test(NAME multiprecision_test_math_${NAME}_mpf SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_mpf PRIVATE -DTEST_MPF_50 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_mpf PRIVATE ${GMP_INCLUDES} ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + target_link_libraries(multiprecision_test_math_${NAME}_mpf ${GMP_LIBRARIES}) + endif() + + cm_test(NAME multiprecision_test_math_${NAME}_cpp_dec_float SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_cpp_dec_float PRIVATE -DTEST_CPP_DEC_FLOAT -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_cpp_dec_float PRIVATE ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + + cm_test(NAME multiprecision_test_math_${NAME}_cpp_bin_float SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_cpp_bin_float PRIVATE -DTEST_CPP_BIN_FLOAT -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_cpp_bin_float PRIVATE ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + + if(FLOAT128_COMPILED) + cm_test(NAME multiprecision_test_math_${NAME}_float128 SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_float128 PRIVATE -DTEST_FLOAT128 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_float128 PRIVATE ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + target_link_libraries(multiprecision_test_math_${NAME}_float128 ${QUADMATH_LIBRARIES}) + endif() + + if((FLOAT128_COMPILED) AND (HAS_INTEL_QUAD)) + #TODO: fix test + cm_test(NAME multiprecision_test_math_${NAME}_intel_quad SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_${NAME}_intel_quad PRIVATE -DTEST_FLOAT128 -DBOOST_ALL_NO_LIB -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) + target_include_directories(multiprecision_test_math_${NAME}_intel_quad PRIVATE ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + endif() + endforeach() +endif() +]] + +#TODO: implicit entry/start for main executable +#[[ +if (BUILD_WITH_SOURCES_DIR) + file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/math/high_prec/*.cpp) + foreach(FILEB ${TEST_FILES}) + if(MPFR_COMPILED) + get_filename_component(NAME ${FILEB} NAME_WE) + cm_test(NAME multiprecision_test_math_high_prec_${NAME} SOURCES ${FILEB}) + target_compile_definitions(multiprecision_test_math_high_prec_${NAME} PRIVATE -DTEST_MPFR -DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE -DBOOST_ALL_NO_LIB) + target_include_directories(multiprecision_test_math_high_prec_${NAME} PRIVATE ${GMP_INCLUDES} ${BUILD_WITH_SOURCES_DIR} ${BUILD_WITH_SOURCES_DIR}/libs/math/include_private) + target_link_libraries(multiprecision_test_math_high_prec_${NAME} ${GMP_LIBRARIES} ${MPFR_LIBRARIES}) + endif() + endforeach() +endif() +]] file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/compile_fail/*.cpp) foreach(FILEB ${TEST_FILES}) - get_filename_component(NAME ${FILEB} NAME_WE) - cm_test(NAME multiprecision_test_compile_fail_${NAME} SOURCES ${FILEB} COMPILE_ONLY WILL_FAIL) - if(GMP_COMPILED) - target_compile_definitions(multiprecision_test_compile_fail_${NAME} PUBLIC -DTEST_GMP) - endif() - if(MPFR_COMPILED) - target_compile_definitions(multiprecision_test_compile_fail_${NAME} PUBLIC -DTEST_MPFR) + if ((GMP_COMPILED) AND (MPFR_COMPILED)) + get_filename_component(NAME ${FILEB} NAME_WE) + cm_test(NAME multiprecision_test_compile_fail_${NAME} SOURCES ${FILEB} COMPILE_ONLY WILL_FAIL) + target_compile_definitions(multiprecision_test_compile_fail_${NAME} PRIVATE -DTEST_GMP -DTEST_MPFR) endif() endforeach() -file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/concepts/*.cpp) -foreach(FILEB ${TEST_FILES}) - get_filename_component(NAME ${FILEB} NAME_WE) +if (BUILD_WITH_SOURCES_DIR) + file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/concepts/*.cpp) + foreach(FILEB ${TEST_FILES}) + get_filename_component(NAME ${FILEB} NAME_WE) + + if (MPFR_COMPILED) + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_50 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_50 PUBLIC -DTEST_MPFR_50) + target_link_libraries(multiprecision_test_concepts_${NAME}_mpfr_50 ${MPFR_LIBRARIES}) + target_include_directories(multiprecision_test_concepts_${NAME}_mpfr_50 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_6 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_6 PUBLIC -DTEST_MPFR_6) + target_link_libraries(multiprecision_test_concepts_${NAME}_mpfr_6 ${MPFR_LIBRARIES}) + target_include_directories(multiprecision_test_concepts_${NAME}_mpfr_6 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_15 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_15 PUBLIC -DTEST_MPFR_15) + target_link_libraries(multiprecision_test_concepts_${NAME}_mpfr_15 ${MPFR_LIBRARIES}) + target_include_directories(multiprecision_test_concepts_${NAME}_mpfr_15 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_17 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_17 PUBLIC -DTEST_MPFR_17) + target_link_libraries(multiprecision_test_concepts_${NAME}_mpfr_17 ${MPFR_LIBRARIES}) + target_include_directories(multiprecision_test_concepts_${NAME}_mpfr_17 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + + cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_30 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_30 PUBLIC -DTEST_MPFR_30) + target_link_libraries(multiprecision_test_concepts_${NAME}_mpfr_30 ${MPFR_LIBRARIES}) + target_include_directories(multiprecision_test_concepts_${NAME}_mpfr_30 PRIVATE ${BUILD_WITH_SOURCES_DIR}) - cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_50 SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_50 PUBLIC -DTEST_MPFR_50) + endif() - cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_6 SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_6 PUBLIC -DTEST_MPFR_6) + if (GMP_COMPILED) + cm_test(NAME multiprecision_test_concepts_${NAME}_mpf50 SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) + target_link_libraries(multiprecision_test_concepts_${NAME}_mpf50 ${GMP_LIBRARIES}) + target_include_directories(multiprecision_test_concepts_${NAME}_mpf50 PRIVATE ${BUILD_WITH_SOURCES_DIR}) + endif() - cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_15 SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_15 PUBLIC -DTEST_MPFR_15) + cm_test(NAME multiprecision_test_concepts_${NAME}_cpp_dec_float SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) + target_include_directories(multiprecision_test_concepts_${NAME}_cpp_dec_float PRIVATE ${BUILD_WITH_SOURCES_DIR}) - cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_17 SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_17 PUBLIC -DTEST_MPFR_17) + cm_test(NAME multiprecision_test_concepts_${NAME}_cpp_bin_float SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) + target_include_directories(multiprecision_test_concepts_${NAME}_cpp_bin_float PRIVATE ${BUILD_WITH_SOURCES_DIR}) - cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_30 SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_30 PUBLIC -DTEST_MPFR_30) + cm_test(NAME multiprecision_test_concepts_${NAME}_cpp_dec_float_no_et SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_cpp_dec_float_no_et PUBLIC -DTEST_CPP_DEC_FLOAT_NO_ET) + target_include_directories(multiprecision_test_concepts_${NAME}_cpp_dec_float_no_et PRIVATE ${BUILD_WITH_SOURCES_DIR}) - cm_test(NAME multiprecision_test_concepts_${NAME}_mpf50 SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) + cm_test(NAME multiprecision_test_concepts_${NAME}_backend_concept SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_backend_concept PUBLIC -DTEST_BACKEND) + target_include_directories(multiprecision_test_concepts_${NAME}_backend_concept PRIVATE ${BUILD_WITH_SOURCES_DIR}) - cm_test(NAME multiprecision_test_concepts_${NAME}_cpp_dec_float SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_cpp_dec_float PUBLIC -DTEST_CPP_DEC_FLOAT) + cm_test(NAME multiprecision_test_concepts_${NAME}_logged_adaptor SOURCES ${FILEB} COMPILE_ONLY) + target_compile_definitions(multiprecision_test_concepts_${NAME}_logged_adaptor PUBLIC -DTEST_LOGGED_ADAPTER) + target_include_directories(multiprecision_test_concepts_${NAME}_logged_adaptor PRIVATE ${BUILD_WITH_SOURCES_DIR}) + endforeach() +endif() - cm_test(NAME multiprecision_test_concepts_${NAME}_cpp_bin_float SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_cpp_bin_float PUBLIC -DTEST_CPP_BIN_FLOAT) +#test-suite examples - cm_test(NAME multiprecision_test_concepts_${NAME}_cpp_dec_float_no_et SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_cpp_dec_float_no_et PUBLIC -DTEST_CPP_DEC_FLOAT_NO_ET) +cm_test(NAME multiprecision_test_cpp_int_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_int_snips.cpp) +target_link_libraries(multiprecision_test_cpp_int_snips no_eh_support) +cm_test(NAME multiprecision_test_cpp_int_import_export SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_int_import_export.cpp) +target_link_libraries(multiprecision_test_cpp_int_import_export no_eh_support) +cm_test(NAME multiprecision_test_cpp_bin_float_import_export SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_bin_float_import_export.cpp) +target_link_libraries(multiprecision_test_cpp_bin_float_import_export no_eh_support) - cm_test(NAME multiprecision_test_concepts_${NAME}_backend_concept SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_backend_concept PUBLIC -DTEST_BACKEND) +cm_test(NAME multiprecision_test_cpp_dec_float_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_dec_float_snips.cpp) +target_link_libraries(multiprecision_test_cpp_dec_float_snips no_eh_support) + +cm_test(NAME multiprecision_test_cpp_bin_float_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/cpp_bin_float_snips.cpp) +target_link_libraries(multiprecision_test_cpp_bin_float_snips no_eh_support) + +cm_test(NAME multiprecision_test_debug_adaptor_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/debug_adaptor_snips.cpp) +target_link_libraries(multiprecision_test_debug_adaptor_snips no_eh_support) + +if (FLOAT128_COMPILED) + #TODO: fix this + #[ run float128_snips.cpp quadmath no_eh_eg_support : : : [ check-target-builds ../config//has_float128 : : no ] ] + cm_test(NAME multiprecision_test_debug_adaptor_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/debug_adaptor_snips.cpp) + target_link_libraries(multiprecision_test_debug_adaptor_snips no_eh_support) +endif() + +cm_test(NAME multiprecision_test_floating_point_examples SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/floating_point_examples.cpp) +target_link_libraries(multiprecision_test_floating_point_examples no_eh_support) + +#TODO: Enable this +#cm_test(NAME multiprecision_test_gauss_laguerre_quadrature SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/gauss_laguerre_quadrature.cpp) +#target_link_libraries(multiprecision_test_gauss_laguerre_quadrature no_eh_support) + +#TODO: Fix this +#cm_test(NAME multiprecision_test_hypergeometric_luke_algorithms SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/hypergeometric_luke_algorithms.cpp) +#target_link_libraries(multiprecision_test_hypergeometric_luke_algorithms no_eh_support) + +cm_test(NAME multiprecision_test_integer_examples SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/integer_examples.cpp) +target_link_libraries(multiprecision_test_integer_examples no_eh_support) + +if (MPFI_COMPILED) + cm_test(NAME multiprecision_test_logged_adaptor SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/logged_adaptor.cpp) + target_link_libraries(multiprecision_test_logged_adaptor ${GMP_LIBRARIES} ${MPFR_LIBRARIES} ${MPFI_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_logged_adaptor PRIVATE ${GMP_INCLUDES} ${MPFI_INCLUDES}) +endif() + +cm_test(NAME multiprecision_test_mixed_integer_arithmetic SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/mixed_integer_arithmetic.cpp) +target_link_libraries(multiprecision_test_mixed_integer_arithmetic no_eh_support) + +if (FLOAT128_COMPILED) + #TODO: fix this + #[ run numeric_limits_snips.cpp no_eh_eg_support /boost//test_exec_monitor : : : [ requires cxx11_numeric_limits ] [ check-target-builds ../config//has_float128 : quadmath ] ] +endif() + +if (GMP_COMPILED) + #TODO: enable this + #cm_test(NAME multiprecision_test_random_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/random_snips.cpp) + #target_link_libraries(multiprecision_test_random_snips ${GMP_LIBRARIES} no_eh_support) + #target_include_directories(multiprecision_test_random_snips PRIVATE ${GMP_INCLUDES}) +endif() + +cm_test(NAME multiprecision_test_safe_prime SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/safe_prime.cpp) +target_link_libraries(multiprecision_test_safe_prime no_eh_support) + +if (GMP_COMPILED) + cm_test(NAME multiprecision_test_gmp_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/gmp_snips.cpp) + target_link_libraries(multiprecision_test_gmp_snips ${GMP_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_gmp_snips PRIVATE ${GMP_INCLUDES}) +endif() + +if (MPFI_COMPILED) + cm_test(NAME multiprecision_test_mpfi_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/mpfi_snips.cpp) + target_link_libraries(multiprecision_test_mpfi_snips ${GMP_LIBRARIES} ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_mpfi_snips PRIVATE ${GMP_INCLUDES} ${MPFI_INCLUDES}) +endif() + +if (MPFR_COMPILED) + cm_test(NAME multiprecision_test_mpfr_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/mpfr_snips.cpp) + target_link_libraries(multiprecision_test_mpfr_snips ${GMP_LIBRARIES} ${MPFR_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_mpfr_snips PRIVATE ${GMP_INCLUDES}) +endif() + +if (TOMMATH_COMPILED) + cm_test(NAME multiprecision_test_tommath_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/tommath_snips.cpp) + target_link_libraries(multiprecision_test_tommath_snips ${TomMath_LIBRARIES} no_eh_support) + target_include_directories(multiprecision_test_tommath_snips PRIVATE ${TomMath_INCLUDES}) +endif() - cm_test(NAME multiprecision_test_concepts_${NAME}_logged_adaptor SOURCES ${FILEB} COMPILE_ONLY) - target_compile_definitions(multiprecision_test_concepts_${NAME}_logged_adaptor PUBLIC -DTEST_LOGGED_ADAPTER) -endforeach() -#]] include_directories(${CMAKE_WORKSPACE_SOURCES_DIR}) From a5f1c3c7d8cecf6466ed371ca393c7634927fee4 Mon Sep 17 00:00:00 2001 From: Zerg1996 Date: Mon, 1 Jul 2019 19:06:37 +0300 Subject: [PATCH 012/294] Add tests Cmake #11 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a329165f..49a5c37eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,4 +71,4 @@ cm_deploy(TARGETS ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} INCLUDE ${CURRENT_SOURCES_DIR}/include NAMESPACE ${CMAKE_WORKSPACE_NAME}::) -#add_subdirectory(test) +add_subdirectory(test) From a494f4b36cee19a4a15c3f5af887305bfe279402 Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Sat, 13 Jul 2019 02:26:59 +0300 Subject: [PATCH 013/294] Workspace definition updated #2 --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6d101e2a..34829c000 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,8 @@ else() include(CMConfig) include(CMSetupVersion) + cm_workspace(boost SOURCES_DIR "${CMAKE_CURRENT_LIST_DIR}") + cm_project(multiprecision WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME}) find_package(Boost COMPONENTS REQUIRED random) From 3075dabad9a8e288919ba358aa2778ef4ea14ee5 Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Sun, 14 Jul 2019 02:02:30 +0300 Subject: [PATCH 014/294] Minor changes introduced #2 --- cmake/packages/FindGMP.cmake | 2 +- cmake/packages/FindGMPXX.cmake | 32 +++ cmake/packages/FindMPC.cmake | 16 +- cmake/packages/FindMPFI.cmake | 101 +++---- cmake/packages/FindMPFR.cmake | 16 +- cmake/packages/FindMPIRXX.cmake | 31 ++ .../FindPackageHandleStandardArgs.cmake | 266 +++++++++--------- cmake/packages/FindQuadmath.cmake | 50 ++-- cmake/packages/FindTomMath.cmake | 23 +- .../boost/multiprecision/modular_adaptor.hpp | 251 +++++++++++++++++ .../multiprecision/montgomery/inverse.hpp | 15 +- .../multiprecision/montgomery/mask_bits.hpp | 10 + .../montgomery/modular_reduce.hpp | 118 ++++---- .../multiprecision/montgomery/reduce.hpp | 118 ++++---- .../montgomery/reduce_below.hpp | 10 + .../multiprecision/montgomery_adaptor.hpp | 222 --------------- meta/libraries.json | 28 +- test/CMakeLists.txt | 130 ++++----- test/{zerg.cpp => test_modular.cpp} | 16 +- 19 files changed, 806 insertions(+), 649 deletions(-) create mode 100644 cmake/packages/FindGMPXX.cmake create mode 100644 cmake/packages/FindMPIRXX.cmake create mode 100644 include/boost/multiprecision/modular_adaptor.hpp delete mode 100644 include/boost/multiprecision/montgomery_adaptor.hpp rename test/{zerg.cpp => test_modular.cpp} (59%) diff --git a/cmake/packages/FindGMP.cmake b/cmake/packages/FindGMP.cmake index 4d6fd7a6c..7e735a503 100644 --- a/cmake/packages/FindGMP.cmake +++ b/cmake/packages/FindGMP.cmake @@ -72,7 +72,7 @@ find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args(GMP DEFAULT_MSG GMP_INCLUDES GMP_LIBRARIES GMP_VERSION_OK) -if (GMP_FOUND) +if(GMP_FOUND) set(HAVE_GMP "${GMP_FOUND}") endif() diff --git a/cmake/packages/FindGMPXX.cmake b/cmake/packages/FindGMPXX.cmake new file mode 100644 index 000000000..8b256af04 --- /dev/null +++ b/cmake/packages/FindGMPXX.cmake @@ -0,0 +1,32 @@ +# https://svn.zib.de/lenne3d/lib/qpl_cgal/3.5.1/cmake/modules/FindGMPXX.cmake +# +# Try to find the GMPXX libraries +# GMPXX_FOUND - system has GMPXX lib +# GMPXX_INCLUDE_DIR - the GMPXX include directory +# GMPXX_LIBRARIES - Libraries needed to use GMPXX + +# TODO: support Windows + +# GMPXX needs GMP + +find_package(GMP QUIET) + +if(GMP_FOUND) + + if(GMPXX_INCLUDE_DIR AND GMPXX_LIBRARIES) + # Already in cache, be silent + set(GMPXX_FIND_QUIETLY TRUE) + endif() + + find_path(GMPXX_INCLUDE_DIR NAMES gmpxx.h + PATHS ${GMP_INCLUDE_DIR_SEARCH} + DOC "The directory containing the GMPXX include files") + + find_library(GMPXX_LIBRARIES NAMES gmpxx + PATHS ${GMP_LIBRARIES_DIR_SEARCH} + DOC "Path to the GMPXX library") + + + find_package_handle_standard_args(GMPXX "DEFAULT_MSG" GMPXX_LIBRARIES GMPXX_INCLUDE_DIR) + +endif() diff --git a/cmake/packages/FindMPC.cmake b/cmake/packages/FindMPC.cmake index 362fa9596..42eff31c2 100644 --- a/cmake/packages/FindMPC.cmake +++ b/cmake/packages/FindMPC.cmake @@ -13,7 +13,7 @@ # MPC_VERSION - MPC version find_path(MPC_INCLUDES NAMES mpc.h PATHS $ENV{GMPDIR} $ENV{MPFRDIR} $ENV{MPCDIR} - ${INCLUDE_INSTALL_DIR}) + ${INCLUDE_INSTALL_DIR}) # Set MPC_FIND_VERSION to 1.0.0 if no minimum version is specified if(NOT MPC_FIND_VERSION) @@ -27,7 +27,7 @@ if(NOT MPC_FIND_VERSION) set(MPC_FIND_VERSION_PATCH 0) endif() set(MPC_FIND_VERSION - "${MPC_FIND_VERSION_MAJOR}.${MPC_FIND_VERSION_MINOR}.${MPC_FIND_VERSION_PATCH}") + "${MPC_FIND_VERSION_MAJOR}.${MPC_FIND_VERSION_MINOR}.${MPC_FIND_VERSION_PATCH}") endif() if(MPC_INCLUDES) @@ -35,17 +35,17 @@ if(MPC_INCLUDES) file(READ "${MPC_INCLUDES}/mpc.h" _mpc_version_header) string(REGEX MATCH "define[ \t]+MPC_VERSION_MAJOR[ \t]+([0-9]+)" - _mpc_major_version_match "${_mpc_version_header}") + _mpc_major_version_match "${_mpc_version_header}") set(MPC_MAJOR_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+MPC_VERSION_MINOR[ \t]+([0-9]+)" - _mpc_minor_version_match "${_mpc_version_header}") + _mpc_minor_version_match "${_mpc_version_header}") set(MPC_MINOR_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+MPC_VERSION_PATCHLEVEL[ \t]+([0-9]+)" - _mpc_patchlevel_version_match "${_mpc_version_header}") + _mpc_patchlevel_version_match "${_mpc_version_header}") set(MPC_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") set(MPC_VERSION - ${MPC_MAJOR_VERSION}.${MPC_MINOR_VERSION}.${MPC_PATCHLEVEL_VERSION}) + ${MPC_MAJOR_VERSION}.${MPC_MINOR_VERSION}.${MPC_PATCHLEVEL_VERSION}) # Check whether found version exceeds minimum required if(${MPC_VERSION} VERSION_LESS ${MPC_FIND_VERSION}) @@ -58,9 +58,9 @@ if(MPC_INCLUDES) endif(MPC_INCLUDES) find_library(MPC_LIBRARIES mpc - PATHS $ENV{GMPDIR} $ENV{MPFRDIR} $ENV{MPCDIR} ${LIB_INSTALL_DIR}) + PATHS $ENV{GMPDIR} $ENV{MPFRDIR} $ENV{MPCDIR} ${LIB_INSTALL_DIR}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MPC DEFAULT_MSG - MPC_INCLUDES MPC_LIBRARIES MPC_VERSION_OK) + MPC_INCLUDES MPC_LIBRARIES MPC_VERSION_OK) mark_as_advanced(MPC_INCLUDES MPC_LIBRARIES) diff --git a/cmake/packages/FindMPFI.cmake b/cmake/packages/FindMPFI.cmake index b97161971..553193f75 100644 --- a/cmake/packages/FindMPFI.cmake +++ b/cmake/packages/FindMPFI.cmake @@ -1,87 +1,94 @@ -find_package( GMP QUIET ) -find_package( MPFR QUIET ) -if( GMP_FOUND AND MPFR_FOUND ) +if(GMP_FOUND) + find_package(GMP QUIET) +else() + find_package(GMP) +endif() - if( MPFI_INCLUDES AND MPFI_LIBRARIES ) - set( MPFI_FOUND TRUE ) - endif( MPFI_INCLUDES AND MPFI_LIBRARIES ) +if(MPFR_FOUND) + find_package(MPFR QUIET) +else() + find_package(MPFR) +endif() + +if(GMP_FOUND AND MPFR_FOUND) + if(MPFI_INCLUDES AND MPFI_LIBRARIES) + set(MPFI_FOUND TRUE) + endif(MPFI_INCLUDES AND MPFI_LIBRARIES) find_path(MPFI_INCLUDES NAMES mpfi.h - HINTS ENV MPFI_INC_DIR - ENV MPFI_DIR - PATHS ${GMP_INCLUDE_DIR_SEARCH} - PATH_SUFFIXES include - DOC "The directory containing the MPFI header files" - ) + HINTS ENV MPFI_INC_DIR + ENV MPFI_DIR + PATHS ${GMP_INCLUDE_DIR_SEARCH} + PATH_SUFFIXES include + DOC "The directory containing the MPFI header files" + ) if(MPFI_INCLUDES) file(READ "${MPFI_INCLUDES}/mpfi.h" _mpfr_version_header) string(REGEX MATCH "define[ \t]+MPFI_VERSION_MAJOR[ \t]+([0-9]+)" - _mpfr_major_version_match "${_mpfr_version_header}") + _mpfr_major_version_match "${_mpfr_version_header}") set(MPFI_MAJOR_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+MPFI_VERSION_MINOR[ \t]+([0-9]+)" - _mpfr_minor_version_match "${_mpfr_version_header}") + _mpfr_minor_version_match "${_mpfr_version_header}") set(MPFI_MINOR_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+MPFI_VERSION_PATCHLEVEL[ \t]+([0-9]+)" - _mpfr_patchlevel_version_match "${_mpfr_version_header}") + _mpfr_patchlevel_version_match "${_mpfr_version_header}") set(MPFI_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") set(MPFI_VERSION - ${MPFI_MAJOR_VERSION}.${MPFI_MINOR_VERSION}.${MPFI_PATCHLEVEL_VERSION}) + ${MPFI_MAJOR_VERSION}.${MPFI_MINOR_VERSION}.${MPFI_PATCHLEVEL_VERSION}) endif() find_library(MPFI_LIBRARIES NAMES mpfi - HINTS ENV MPFI_LIB_DIR - ENV MPFI_DIR - PATHS ${GMP_LIBRARIES_DIR_SEARCH} - PATH_SUFFIXES lib - DOC "Directory containing the MPFI library" - ) + HINTS ENV MPFI_LIB_DIR + ENV MPFI_DIR + PATHS ${GMP_LIBRARIES_DIR_SEARCH} + PATH_SUFFIXES lib + DOC "Directory containing the MPFI library" + ) - if( MPFI_LIBRARIES ) - get_filename_component(MPFI_LIBRARIES_DIR ${MPFI_LIBRARIES} PATH CACHE ) - endif( MPFI_LIBRARIES ) + if(MPFI_LIBRARIES) + get_filename_component(MPFI_LIBRARIES_DIR ${MPFI_LIBRARIES} PATH CACHE) + endif(MPFI_LIBRARIES) - if( NOT MPFI_INCLUDES OR NOT MPFI_LIBRARIES_DIR ) - include( MPFIConfig OPTIONAL ) - endif( NOT MPFI_INCLUDES OR NOT MPFI_LIBRARIES_DIR ) + if(NOT MPFI_INCLUDES OR NOT MPFI_LIBRARIES_DIR) + include(MPFIConfig OPTIONAL) + endif(NOT MPFI_INCLUDES OR NOT MPFI_LIBRARIES_DIR) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args( MPFI - "DEFAULT_MSG" - MPFI_LIBRARIES - MPFI_INCLUDES ) + find_package_handle_standard_args(MPFI + "DEFAULT_MSG" + MPFI_LIBRARIES + MPFI_INCLUDES) -else( GMP_FOUND AND MPFR_FOUND ) +else(GMP_FOUND AND MPFR_FOUND) - message( STATUS "MPFI needs GMP and MPFR" ) + message(STATUS "MPFI needs GMP and MPFR") -endif( GMP_FOUND AND MPFR_FOUND ) +endif(GMP_FOUND AND MPFR_FOUND) -if( MPFI_FOUND ) - if ("${MPFR_VERSION}" VERSION_LESS "4.0.0") +if(MPFI_FOUND) + if("${MPFR_VERSION}" VERSION_LESS "4.0.0") set(_MPFR_OLD TRUE) endif() - if ("${MPFI_VERSION}" VERSION_LESS "1.5.2") + if("${MPFI_VERSION}" VERSION_LESS "1.5.2") set(_MPFI_OLD TRUE) endif() - if( ( _MPFR_OLD AND NOT _MPFI_OLD ) OR ( NOT _MPFR_OLD AND _MPFI_OLD ) ) + if((_MPFR_OLD AND NOT _MPFI_OLD) OR (NOT _MPFR_OLD AND _MPFI_OLD)) - message( - STATUS - "MPFI<1.5.2 requires MPFR<4.0.0; MPFI>=1.5.2 requires MPFR>=4.0.0" ) + message(STATUS "MPFI<1.5.2 requires MPFR<4.0.0; MPFI>=1.5.2 requires MPFR>=4.0.0") - set( MPFI_FOUND FALSE ) + set(MPFI_FOUND FALSE) - else( ( _MPFR_OLD AND NOT _MPFI_OLD ) OR ( NOT _MPFR_OLD AND _MPFI_OLD ) ) + else((_MPFR_OLD AND NOT _MPFI_OLD) OR (NOT _MPFR_OLD AND _MPFI_OLD)) - set( MPFI_USE_FILE "CGAL_UseMPFI" ) + set(MPFI_USE_FILE "CGAL_UseMPFI") - endif( ( _MPFR_OLD AND NOT _MPFI_OLD ) OR ( NOT _MPFR_OLD AND _MPFI_OLD ) ) + endif((_MPFR_OLD AND NOT _MPFI_OLD) OR (NOT _MPFR_OLD AND _MPFI_OLD)) -endif( MPFI_FOUND ) +endif(MPFI_FOUND) \ No newline at end of file diff --git a/cmake/packages/FindMPFR.cmake b/cmake/packages/FindMPFR.cmake index 83e5bec51..8fdc03443 100644 --- a/cmake/packages/FindMPFR.cmake +++ b/cmake/packages/FindMPFR.cmake @@ -19,7 +19,7 @@ # Redistribution and use is allowed according to the terms of the BSD license. find_path(MPFR_INCLUDES NAMES mpfr.h PATHS $ENV{GMPDIR} $ENV{MPFRDIR} - ${INCLUDE_INSTALL_DIR}) + ${INCLUDE_INSTALL_DIR}) # Set MPFR_FIND_VERSION to 1.0.0 if no minimum version is specified if(NOT MPFR_FIND_VERSION) @@ -33,7 +33,7 @@ if(NOT MPFR_FIND_VERSION) set(MPFR_FIND_VERSION_PATCH 0) endif() set(MPFR_FIND_VERSION - "${MPFR_FIND_VERSION_MAJOR}.${MPFR_FIND_VERSION_MINOR}.${MPFR_FIND_VERSION_PATCH}") + "${MPFR_FIND_VERSION_MAJOR}.${MPFR_FIND_VERSION_MINOR}.${MPFR_FIND_VERSION_PATCH}") endif() if(MPFR_INCLUDES) @@ -41,17 +41,17 @@ if(MPFR_INCLUDES) file(READ "${MPFR_INCLUDES}/mpfr.h" _mpfr_version_header) string(REGEX MATCH "define[ \t]+MPFR_VERSION_MAJOR[ \t]+([0-9]+)" - _mpfr_major_version_match "${_mpfr_version_header}") + _mpfr_major_version_match "${_mpfr_version_header}") set(MPFR_MAJOR_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+MPFR_VERSION_MINOR[ \t]+([0-9]+)" - _mpfr_minor_version_match "${_mpfr_version_header}") + _mpfr_minor_version_match "${_mpfr_version_header}") set(MPFR_MINOR_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+MPFR_VERSION_PATCHLEVEL[ \t]+([0-9]+)" - _mpfr_patchlevel_version_match "${_mpfr_version_header}") + _mpfr_patchlevel_version_match "${_mpfr_version_header}") set(MPFR_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") set(MPFR_VERSION - ${MPFR_MAJOR_VERSION}.${MPFR_MINOR_VERSION}.${MPFR_PATCHLEVEL_VERSION}) + ${MPFR_MAJOR_VERSION}.${MPFR_MINOR_VERSION}.${MPFR_PATCHLEVEL_VERSION}) # Check whether found version exceeds minimum required if(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) @@ -64,9 +64,9 @@ if(MPFR_INCLUDES) endif() find_library(MPFR_LIBRARIES mpfr - PATHS $ENV{GMPDIR} $ENV{MPFRDIR} ${LIB_INSTALL_DIR}) + PATHS $ENV{GMPDIR} $ENV{MPFRDIR} ${LIB_INSTALL_DIR}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MPFR DEFAULT_MSG - MPFR_INCLUDES MPFR_LIBRARIES MPFR_VERSION_OK) + MPFR_INCLUDES MPFR_LIBRARIES MPFR_VERSION_OK) mark_as_advanced(MPFR_INCLUDES MPFR_LIBRARIES) \ No newline at end of file diff --git a/cmake/packages/FindMPIRXX.cmake b/cmake/packages/FindMPIRXX.cmake new file mode 100644 index 000000000..8f8aae2a5 --- /dev/null +++ b/cmake/packages/FindMPIRXX.cmake @@ -0,0 +1,31 @@ +# Try to find the MPIRXX libraries +# MPIRXX_FOUND - system has MPIRXX lib +# MPIRXX_INCLUDE_DIR - the MPIRXX include directory +# MPIRXX_LIBRARIES - Libraries needed to use MPIRXX + +# TODO: support Windows and MacOSX + +# MPIRXX needs MPIR + +find_package(MPIR QUIET) + +if(MPIR_FOUND) + if(MPIRXX_INCLUDE_DIR AND MPIRXX_LIBRARIES) + # Already in cache, be silent + set(MPIRXX_FIND_QUIETLY TRUE) + endif() + + find_path(MPIRXX_INCLUDE_DIR NAMES mpirxx.h + PATHS ${MPIR_INCLUDE_DIR_SEARCH} + DOC "The directory containing the MPIRXX include files" + ) + + find_library(MPIRXX_LIBRARIES NAMES mpirxx + PATHS ${MPIR_LIBRARIES_DIR_SEARCH} + DOC "Path to the MPIRXX library" + ) + + + find_package_handle_standard_args(MPIRXX "DEFAULT_MSG" MPIRXX_LIBRARIES MPIRXX_INCLUDE_DIR) + +endif() diff --git a/cmake/packages/FindPackageHandleStandardArgs.cmake b/cmake/packages/FindPackageHandleStandardArgs.cmake index 00b3c02a8..adacd4e6a 100644 --- a/cmake/packages/FindPackageHandleStandardArgs.cmake +++ b/cmake/packages/FindPackageHandleStandardArgs.cmake @@ -82,179 +82,179 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -INCLUDE(FindPackageMessage) -INCLUDE(CMakeParseArguments) +include(FindPackageMessage) +include(CMakeParseArguments) # internal helper macro -MACRO(_FPHSA_FAILURE_MESSAGE _msg) - IF (${_NAME}_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "${_msg}") - ELSE (${_NAME}_FIND_REQUIRED) - IF (NOT ${_NAME}_FIND_QUIETLY) - MESSAGE(STATUS "${_msg}") - ENDIF (NOT ${_NAME}_FIND_QUIETLY) - ENDIF (${_NAME}_FIND_REQUIRED) -ENDMACRO(_FPHSA_FAILURE_MESSAGE _msg) +macro(_fphsa_failure_message _msg) + if(${_NAME}_FIND_REQUIRED) + message(FATAL_ERROR "${_msg}") + else(${_NAME}_FIND_REQUIRED) + if(NOT ${_NAME}_FIND_QUIETLY) + message(STATUS "${_msg}") + endif(NOT ${_NAME}_FIND_QUIETLY) + endif(${_NAME}_FIND_REQUIRED) +endmacro(_fphsa_failure_message _msg) # internal helper macro to generate the failure message when used in CONFIG_MODE: -MACRO(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) +macro(_fphsa_handle_failure_config_mode) # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: - IF(${_NAME}_CONFIG) - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") - ELSE(${_NAME}_CONFIG) + if(${_NAME}_CONFIG) + _fphsa_failure_message("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + else(${_NAME}_CONFIG) # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. # List them all in the error message: - IF(${_NAME}_CONSIDERED_CONFIGS) - SET(configsText "") - LIST(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) - MATH(EXPR configsCount "${configsCount} - 1") - FOREACH(currentConfigIndex RANGE ${configsCount}) - LIST(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) - LIST(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) - SET(configsText "${configsText} ${filename} (version ${version})\n") - ENDFOREACH(currentConfigIndex) - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}") - - ELSE(${_NAME}_CONSIDERED_CONFIGS) + if(${_NAME}_CONSIDERED_CONFIGS) + set(configsText "") + list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) + math(EXPR configsCount "${configsCount} - 1") + foreach(currentConfigIndex RANGE ${configsCount}) + list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) + list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) + set(configsText "${configsText} ${filename} (version ${version})\n") + endforeach(currentConfigIndex) + _fphsa_failure_message("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}") + + else(${_NAME}_CONSIDERED_CONFIGS) # Simple case: No Config-file was found at all: - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") - ENDIF(${_NAME}_CONSIDERED_CONFIGS) - ENDIF(${_NAME}_CONFIG) -ENDMACRO(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) + _fphsa_failure_message("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") + endif(${_NAME}_CONSIDERED_CONFIGS) + endif(${_NAME}_CONFIG) +endmacro(_fphsa_handle_failure_config_mode) -FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) +function(find_package_handle_standard_args _NAME _FIRST_ARG) # set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in # new extended or in the "old" mode: - SET(options CONFIG_MODE) - SET(oneValueArgs FAIL_MESSAGE VERSION_VAR) - SET(multiValueArgs REQUIRED_VARS) - SET(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) - LIST(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) + set(options CONFIG_MODE) + set(oneValueArgs FAIL_MESSAGE VERSION_VAR) + set(multiValueArgs REQUIRED_VARS) + set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs}) + list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) - IF(${INDEX} EQUAL -1) - SET(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) - SET(FPHSA_REQUIRED_VARS ${ARGN}) - SET(FPHSA_VERSION_VAR) - ELSE(${INDEX} EQUAL -1) + if(${INDEX} EQUAL -1) + set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) + set(FPHSA_REQUIRED_VARS ${ARGN}) + set(FPHSA_VERSION_VAR) + else(${INDEX} EQUAL -1) - CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) + cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) - IF(FPHSA_UNPARSED_ARGUMENTS) - MESSAGE(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") - ENDIF(FPHSA_UNPARSED_ARGUMENTS) + if(FPHSA_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") + endif(FPHSA_UNPARSED_ARGUMENTS) - IF(NOT FPHSA_FAIL_MESSAGE) - SET(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") - ENDIF(NOT FPHSA_FAIL_MESSAGE) - ENDIF(${INDEX} EQUAL -1) + if(NOT FPHSA_FAIL_MESSAGE) + set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") + endif(NOT FPHSA_FAIL_MESSAGE) + endif(${INDEX} EQUAL -1) # now that we collected all arguments, process them - IF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG") - SET(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") - ENDIF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG") + if("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG") + set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") + endif("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG") # In config-mode, we rely on the variable _CONFIG, which is set by find_package() # when it successfully found the config-file, including version checking: - IF(FPHSA_CONFIG_MODE) - LIST(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) - LIST(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) - SET(FPHSA_VERSION_VAR ${_NAME}_VERSION) - ENDIF(FPHSA_CONFIG_MODE) + if(FPHSA_CONFIG_MODE) + list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) + list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) + set(FPHSA_VERSION_VAR ${_NAME}_VERSION) + endif(FPHSA_CONFIG_MODE) - IF(NOT FPHSA_REQUIRED_VARS) - MESSAGE(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") - ENDIF(NOT FPHSA_REQUIRED_VARS) + if(NOT FPHSA_REQUIRED_VARS) + message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") + endif(NOT FPHSA_REQUIRED_VARS) - LIST(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) + list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) - STRING(TOUPPER ${_NAME} _NAME_UPPER) - STRING(TOLOWER ${_NAME} _NAME_LOWER) + string(TOUPPER ${_NAME} _NAME_UPPER) + string(TOLOWER ${_NAME} _NAME_LOWER) # collect all variables which were not found, so they can be printed, so the # user knows better what went wrong (#6375) - SET(MISSING_VARS "") - SET(DETAILS "") - SET(${_NAME_UPPER}_FOUND TRUE) + set(MISSING_VARS "") + set(DETAILS "") + set(${_NAME_UPPER}_FOUND TRUE) # check if all passed variables are valid - FOREACH(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) - IF(NOT ${_CURRENT_VAR}) - SET(${_NAME_UPPER}_FOUND FALSE) - SET(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}") - ELSE(NOT ${_CURRENT_VAR}) - SET(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]") - ENDIF(NOT ${_CURRENT_VAR}) - ENDFOREACH(_CURRENT_VAR) + foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) + if(NOT ${_CURRENT_VAR}) + set(${_NAME_UPPER}_FOUND FALSE) + set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}") + else(NOT ${_CURRENT_VAR}) + set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]") + endif(NOT ${_CURRENT_VAR}) + endforeach(_CURRENT_VAR) # version handling: - SET(VERSION_MSG "") - SET(VERSION_OK TRUE) - SET(VERSION ${${FPHSA_VERSION_VAR}} ) - IF (${_NAME}_FIND_VERSION) - - IF(VERSION) - - IF(${_NAME}_FIND_VERSION_EXACT) # exact version required - IF (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") - SET(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") - SET(VERSION_OK FALSE) - ELSE (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") - SET(VERSION_MSG "(found suitable exact version \"${VERSION}\")") - ENDIF (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") - - ELSE(${_NAME}_FIND_VERSION_EXACT) # minimum version specified: - IF ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") - SET(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"") - SET(VERSION_OK FALSE) - ELSE ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") - SET(VERSION_MSG "(found suitable version \"${VERSION}\", required is \"${${_NAME}_FIND_VERSION}\")") - ENDIF ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") - ENDIF(${_NAME}_FIND_VERSION_EXACT) - - ELSE(VERSION) + set(VERSION_MSG "") + set(VERSION_OK TRUE) + set(VERSION ${${FPHSA_VERSION_VAR}}) + if(${_NAME}_FIND_VERSION) + + if(VERSION) + + if(${_NAME}_FIND_VERSION_EXACT) # exact version required + if(NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else(NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + set(VERSION_MSG "(found suitable exact version \"${VERSION}\")") + endif(NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + + else(${_NAME}_FIND_VERSION_EXACT) # minimum version specified: + if("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + set(VERSION_MSG "(found suitable version \"${VERSION}\", required is \"${${_NAME}_FIND_VERSION}\")") + endif("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + endif(${_NAME}_FIND_VERSION_EXACT) + + else(VERSION) # if the package was not found, but a version was given, add that to the output: - IF(${_NAME}_FIND_VERSION_EXACT) - SET(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") - ELSE(${_NAME}_FIND_VERSION_EXACT) - SET(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") - ENDIF(${_NAME}_FIND_VERSION_EXACT) - - ENDIF(VERSION) - ELSE (${_NAME}_FIND_VERSION) - IF(VERSION) - SET(VERSION_MSG "(found version \"${VERSION}\")") - ENDIF(VERSION) - ENDIF (${_NAME}_FIND_VERSION) - - IF(VERSION_OK) - SET(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]") - ELSE(VERSION_OK) - SET(${_NAME_UPPER}_FOUND FALSE) - ENDIF(VERSION_OK) + if(${_NAME}_FIND_VERSION_EXACT) + set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") + else(${_NAME}_FIND_VERSION_EXACT) + set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") + endif(${_NAME}_FIND_VERSION_EXACT) + + endif(VERSION) + else(${_NAME}_FIND_VERSION) + if(VERSION) + set(VERSION_MSG "(found version \"${VERSION}\")") + endif(VERSION) + endif(${_NAME}_FIND_VERSION) + + if(VERSION_OK) + set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]") + else(VERSION_OK) + set(${_NAME_UPPER}_FOUND FALSE) + endif(VERSION_OK) # print the result: - IF (${_NAME_UPPER}_FOUND) - FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG}" "${DETAILS}") - ELSE (${_NAME_UPPER}_FOUND) + if(${_NAME_UPPER}_FOUND) + find_package_message(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG}" "${DETAILS}") + else(${_NAME_UPPER}_FOUND) - IF(FPHSA_CONFIG_MODE) - _FPHSA_HANDLE_FAILURE_CONFIG_MODE() - ELSE(FPHSA_CONFIG_MODE) - IF(NOT VERSION_OK) - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") - ELSE(NOT VERSION_OK) - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}") - ENDIF(NOT VERSION_OK) - ENDIF(FPHSA_CONFIG_MODE) + if(FPHSA_CONFIG_MODE) + _fphsa_handle_failure_config_mode() + else(FPHSA_CONFIG_MODE) + if(NOT VERSION_OK) + _fphsa_failure_message("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") + else(NOT VERSION_OK) + _fphsa_failure_message("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}") + endif(NOT VERSION_OK) + endif(FPHSA_CONFIG_MODE) - ENDIF (${_NAME_UPPER}_FOUND) + endif(${_NAME_UPPER}_FOUND) - SET(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE) + set(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE) -ENDFUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _FIRST_ARG) \ No newline at end of file +endfunction(find_package_handle_standard_args _FIRST_ARG) \ No newline at end of file diff --git a/cmake/packages/FindQuadmath.cmake b/cmake/packages/FindQuadmath.cmake index 620fd9728..ca34ad911 100644 --- a/cmake/packages/FindQuadmath.cmake +++ b/cmake/packages/FindQuadmath.cmake @@ -33,8 +33,8 @@ include(CMakePushCheckState) include(CheckCXXSourceCompiles) if(Quadmath_INCLUDE_DIR AND Quadmath_LIBRARY) - # Already in cache, be silent - set(Quadmath_FIND_QUIETLY TRUE) + # Already in cache, be silent + set(Quadmath_FIND_QUIETLY TRUE) endif() find_path(Quadmath_INCLUDE_DIR NAMES quadmath.h PATHS /usr/local/lib) @@ -44,19 +44,19 @@ message(--- ${Quadmath_INCLUDE_DIR}) message(--- ${Quadmath_LIBRARY}) if(NOT Quadmath_INCLUDE_DIR OR NOT Quadmath_LIBRARY) - cmake_push_check_state(RESET) - list(APPEND CMAKE_REQUIRED_LIBRARIES "quadmath") - CHECK_CXX_SOURCE_COMPILES(" + cmake_push_check_state(RESET) + list(APPEND CMAKE_REQUIRED_LIBRARIES "quadmath") + check_cxx_source_compiles(" #include int main(void){ __float128 foo = ::sqrtq(123.456); }" - Quadmath_USE_DIRECTLY) - cmake_pop_check_state() - if (Quadmath_USE_DIRECTLY) - set(Quadmath_INCLUDE_DIR "unused" CACHE PATH "" FORCE) - set(Quadmath_LIBRARY "quadmath" CACHE FILEPATH "" FORCE) - endif() + Quadmath_USE_DIRECTLY) + cmake_pop_check_state() + if(Quadmath_USE_DIRECTLY) + set(Quadmath_INCLUDE_DIR "unused" CACHE PATH "" FORCE) + set(Quadmath_LIBRARY "quadmath" CACHE FILEPATH "" FORCE) + endif() endif() find_package_handle_standard_args(Quadmath DEFAULT_MSG Quadmath_LIBRARY Quadmath_INCLUDE_DIR) @@ -65,18 +65,18 @@ mark_as_advanced(Quadmath_INCLUDE_DIR Quadmath_LIBRARY) # NOTE: this has been adapted from CMake's FindPNG.cmake. if(Quadmath_FOUND AND NOT TARGET Quadmath::quadmath) - message(STATUS "Creating the 'Quadmath::quadmath' imported target.") - if(Quadmath_USE_DIRECTLY) - message(STATUS "libquadmath will be included and linked directly.") - # If we are using it directly, we must define an interface library, - # as we do not have the full path to the shared library. - add_library(Quadmath::quadmath INTERFACE IMPORTED) - set_target_properties(Quadmath::quadmath PROPERTIES INTERFACE_LINK_LIBRARIES "${Quadmath_LIBRARY}") - else() - # Otherwise, we proceed as usual. - add_library(Quadmath::quadmath UNKNOWN IMPORTED) - set_target_properties(Quadmath::quadmath PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Quadmath_INCLUDE_DIR}" - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${Quadmath_LIBRARY}") - endif() + message(STATUS "Creating the 'Quadmath::quadmath' imported target.") + if(Quadmath_USE_DIRECTLY) + message(STATUS "libquadmath will be included and linked directly.") + # If we are using it directly, we must define an interface library, + # as we do not have the full path to the shared library. + add_library(Quadmath::quadmath INTERFACE IMPORTED) + set_target_properties(Quadmath::quadmath PROPERTIES INTERFACE_LINK_LIBRARIES "${Quadmath_LIBRARY}") + else() + # Otherwise, we proceed as usual. + add_library(Quadmath::quadmath UNKNOWN IMPORTED) + set_target_properties(Quadmath::quadmath PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Quadmath_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${Quadmath_LIBRARY}") + endif() endif() diff --git a/cmake/packages/FindTomMath.cmake b/cmake/packages/FindTomMath.cmake index 9f99a6869..1812f49f3 100644 --- a/cmake/packages/FindTomMath.cmake +++ b/cmake/packages/FindTomMath.cmake @@ -5,23 +5,22 @@ # TomMath_INCLUDE_DIRS - the TomMath include directories # TomMath_LIBRARY - link these to use TomMath -FIND_PATH(TomMath_INCLUDE_DIR tommath.h) +find_path(TomMath_INCLUDE_DIR tommath.h) -SET(TomMath_NAMES ${TomMath_NAMES} tommath libtommath ) -FIND_LIBRARY(TomMath_LIBRARY NAMES ${TomMath_NAMES} ) +set(TomMath_NAMES ${TomMath_NAMES} tommath libtommath) +find_library(TomMath_LIBRARY NAMES ${TomMath_NAMES}) # handle the QUIETLY and REQUIRED arguments and set TIFF_FOUND to TRUE if # all listed variables are TRUE -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +find_package_handle_standard_args(TomMath DEFAULT_MSG TomMath_LIBRARY TomMath_INCLUDE_DIR) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(TomMath DEFAULT_MSG TomMath_LIBRARY TomMath_INCLUDE_DIR) +if(TOMMATH_FOUND) + set(TomMath_FOUND true) + set(TomMath_LIBRARIES ${TomMath_LIBRARY}) + set(TomMath_INCLUDES ${TomMath_INCLUDE_DIR}) +endif(TOMMATH_FOUND) -IF(TOMMATH_FOUND) - set( TomMath_FOUND true ) - SET( TomMath_LIBRARIES ${TomMath_LIBRARY} ) - SET( TomMath_INCLUDES ${TomMath_INCLUDE_DIR} ) -ENDIF(TOMMATH_FOUND) - -MARK_AS_ADVANCED(TomMath_INCLUDE_DIR TomMath_LIBRARY TomMath_FOUND) +mark_as_advanced(TomMath_INCLUDE_DIR TomMath_LIBRARY TomMath_FOUND) diff --git a/include/boost/multiprecision/modular_adaptor.hpp b/include/boost/multiprecision/modular_adaptor.hpp new file mode 100644 index 000000000..ed7aa5230 --- /dev/null +++ b/include/boost/multiprecision/modular_adaptor.hpp @@ -0,0 +1,251 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018 John Maddock +// Copyright (c) 2018-2019 Nil Foundation AG +// Copyright (c) 2018-2019 Mikhail Komarov +// Copyright (c) 2018-2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef BOOST_MULTIPRECISION_MODULAR_ADAPTOR_HPP +#define BOOST_MULTIPRECISION_MODULAR_ADAPTOR_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { + namespace multiprecision { + namespace backends { + + template + struct modular_adaptor { + protected: + BackendBase m_base; + montgomery_params m_mod; + public: + BackendBase &base_data() { + return m_base; + } + + const BackendBase &base_data() const { + return m_base; + } + + montgomery_params &mod_data() { + return m_mod; + } + + const montgomery_params &mod_data() const { + return m_mod; + } + + //typedef typename Backend::signed_types signed_types; + //typedef typename Backend::unsigned_types unsigned_types; + //typedef typename Backend::float_types float_types; + //typedef typename Backend::exponent_type exponent_type; + + modular_adaptor() { + } + + modular_adaptor(const modular_adaptor &o) : m_base(o.base_data()), m_mod(o.mod_data()) { + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + modular_adaptor(modular_adaptor &&o) : m_base(std::move(o.base_data())), + m_mod(std::move(o.mod_data())) { + } + +#endif + + modular_adaptor(const BackendBase &val) : m_base(val) { + } + + modular_adaptor(const BackendBase &val, const montgomery_params &mod) : m_base(val), + m_mod(mod) { + } + + modular_adaptor(const montgomery_params &mod) : m_base(0), m_mod(mod) { + } + + modular_adaptor &operator=(const modular_adaptor &o) { + m_base = o.base_data(); + m_mod = o.mod_data(); + return *this; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + modular_adaptor &operator=(modular_adaptor &&o) + + BOOST_NOEXCEPT + { + m_base = std::move(o.base_data()); + m_mod = std::move(o.mod_data()); + return *this; + } +#endif + + int compare(const modular_adaptor &o) const { + // They are either equal or not: + return (m_base.compare(o.base_data()) == 0) && (m_mod.compare(o.mod_data()) == 0) ? 0 : 1; + } + + template + int compare(const T &val) const { + using default_ops::eval_lt; + return (m_base.compare(val) == 0) && eval_lt(m_mod, val) ? 0 : 1; + } + + void swap(modular_adaptor &o) { + base_data().swap(o.base_data()); + mod_data().swap(o.mod_data()); + } + + std::string str(std::streamsize dig, std::ios_base::fmtflags f) const { + modular_adaptor> + tmp = this; + redc(tmp); + return str(tmp.base_data()); + } + + }; + + template inline typename enable_if, bool> + + ::type eval_eq(const modular_adaptor &a, const T &b) + + BOOST_NOEXCEPT { + return a. + compare(b) + == 0; + } + + template + inline void eval_add(modular_adaptor &result, + const modular_adaptor &o) { + eval_add(result.base_data(), o.base_data()); + redc(result); + } + + template + inline void eval_subtract(modular_adaptor &result, + const modular_adaptor &o) { + BackendBase tmp = result.base_data(); + eval_subtract(tmp, o.base_data()); + if (eval_lt(tmp, 0)) { + BOOST_THROW_EXCEPTION(std::range_error("Montgomery less than zero")); + } + result.base_data() = tmp; + } + + template + inline void eval_multiply(modular_adaptor &result, + const modular_adaptor &o) { + eval_multiply(result.base_data(), o.base_data()); + redc(result); + } + + template + inline void eval_divide(modular_adaptor &result, + const modular_adaptor &o) { + eval_divide(result.base_data(), o.base_data()); + } + + template + inline bool eval_is_zero(const modular_adaptor &val) + + BOOST_NOEXCEPT { + using default_ops::eval_is_zero; + return + eval_is_zero(val + . + + base_data() + + ); + } + + template + inline int eval_get_sign(const modular_adaptor &) { + return 1; + } + + template + inline typename disable_if_c::value>::type eval_convert_to(Result *result, + const modular_adaptor &val) { + using default_ops::eval_is_zero; + using default_ops::eval_convert_to; + if (!eval_is_zero(val.imag_data())) { + BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar.")); + } + eval_convert_to(result, val.real_data()); + } + + template + inline void assign_components(modular_adaptor &result, const T &a, + const montgomery_params &b) { + result.base_data() = a; + result.mod_data() = b; + } + + template + inline void eval_sqrt(modular_adaptor &result, + const modular_adaptor &val) { + eval_sqrt(result.base_data(), val.base_data()); + } + + template + inline void eval_abs(modular_adaptor &result, + const modular_adaptor &val) { + result = val; + } + + template + inline void eval_pow(modular_adaptor &result, + const modular_adaptor &b, + const modular_adaptor &e) { + using default_ops::eval_acos; + using default_ops::eval_exp; + modular_adaptor t; + eval_log(t, b); + eval_multiply(t, e); + eval_exp(result, t); + redc(result); + } + + template + inline void eval_exp(modular_adaptor &result, + const modular_adaptor &arg) { + using default_ops::eval_exp; + + eval_exp(result.base_data(), arg.base_data()); + result.mod_data() = arg.mod_data(); + redc(result); + } + + template + inline void eval_log(modular_adaptor &result, + const modular_adaptor &arg) { + using default_ops::eval_log; + + eval_log(result.base_data(), arg.base_data()); + result.mod_data() = arg.mod_data(); + redc(result); + } + +} // namespace multiprecision + +} // namespaces + +#endif diff --git a/include/boost/multiprecision/montgomery/inverse.hpp b/include/boost/multiprecision/montgomery/inverse.hpp index 561a20d9a..18ad51e47 100644 --- a/include/boost/multiprecision/montgomery/inverse.hpp +++ b/include/boost/multiprecision/montgomery/inverse.hpp @@ -1,18 +1,27 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2019 Nil Foundation AG +// Copyright (c) 2018-2019 Mikhail Komarov +// Copyright (c) 2018-2019 Alexey Moskvin // -// Created by Zerg1996 on 2019-05-07. -// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// #ifndef CRYPTO3_INVERSE_H #define CRYPTO3_INVERSE_H + #define CRYPTO3_MP_WORD_BITS 64 + namespace boost { namespace multiprecision { limb_type monty_inverse(limb_type a) { const limb_type MP_WORD_MAX = ~static_cast(0); - if (a % 2 == 0) + if (a % 2 == 0) { throw std::invalid_argument("monty_inverse only valid for odd integers"); + } /* * From "A New Algorithm for Inversion mod p^k" by Çetin Kaya Koç diff --git a/include/boost/multiprecision/montgomery/mask_bits.hpp b/include/boost/multiprecision/montgomery/mask_bits.hpp index 5fcaeedbe..58db98785 100644 --- a/include/boost/multiprecision/montgomery/mask_bits.hpp +++ b/include/boost/multiprecision/montgomery/mask_bits.hpp @@ -1,3 +1,13 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2019 Nil Foundation AG +// Copyright (c) 2018-2019 Mikhail Komarov +// Copyright (c) 2018-2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + #ifndef CRYPTO3_MASK_BITS_HPP #define CRYPTO3_MASK_BITS_HPP diff --git a/include/boost/multiprecision/montgomery/modular_reduce.hpp b/include/boost/multiprecision/montgomery/modular_reduce.hpp index c3bf5ca71..c3fbfcf5b 100644 --- a/include/boost/multiprecision/montgomery/modular_reduce.hpp +++ b/include/boost/multiprecision/montgomery/modular_reduce.hpp @@ -1,3 +1,13 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2019 Nil Foundation AG +// Copyright (c) 2018-2019 Mikhail Komarov +// Copyright (c) 2018-2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + #ifndef CRYPTO3_MP_MONTGOMERY_INT_MOD_REDC_HPP #define CRYPTO3_MP_MONTGOMERY_INT_MOD_REDC_HPP @@ -16,70 +26,72 @@ namespace boost { #endif template - inline void mod_redc(Backend &result, const Backend &mod) BOOST_MP_NOEXCEPT_IF ( + inline void mod_redc(Backend &result, const Backend &mod) + + BOOST_MP_NOEXCEPT_IF ( is_non_throwing_cpp_int::value) { - using default_ops::eval_lt; - using default_ops::eval_gt; - using default_ops::eval_add; - using default_ops::eval_multiply; - using default_ops::eval_bit_set; - - const size_t x_sw = result.size(); - - Backend mod2 = mod; - eval_add(mod2, mod); - - if (result.size() < mod.size() || eval_lt(result, mod)) { - if (eval_lt(result, 0)) { - eval_add(result, mod); - return; - } // make positive - return; - } else if (eval_lt(result, mod2)) { - //secure_vector ws; - Backend t1; - - eval_import_bits(t1, result.limbs() + mod.size() - 1, result.limbs() + x_sw); - { - Backend p2; - eval_bit_set(p2, 2 * Backend::limb_bits * mod.size()); - eval_divide(p2, mod); - eval_multiply(t1, p2); - } - eval_right_shift(t1, (Backend::limb_bits * (mod.size() + 1))); + using default_ops::eval_lt; + using default_ops::eval_gt; + using default_ops::eval_add; + using default_ops::eval_multiply; + using default_ops::eval_bit_set; + + const size_t x_sw = result.size(); + + Backend mod2 = mod; + eval_add(mod2, mod); + + if (result.size() < mod.size() || eval_lt(result, mod)) { + if (eval_lt(result, 0)) { + eval_add(result, mod); + return; + } // make positive + return; + } else if (eval_lt(result, mod2)) { + //secure_vector ws; + Backend t1; - eval_multiply(t1, mod); + eval_import_bits(t1, result.limbs() + mod.size() - 1, result.limbs() + x_sw); + { + Backend p2; + eval_bit_set(p2, 2 * Backend::limb_bits * mod.size()); + eval_divide(p2, mod); + eval_multiply(t1, p2); + } + eval_right_shift(t1, (Backend::limb_bits * (mod.size() + 1))); - eval_mask_bits(t1, Backend::limb_bits * (mod.size() + 1)); + eval_multiply(t1, mod); - eval_subtract(t1, result, t1); + eval_mask_bits(t1, Backend::limb_bits * (mod.size() + 1)); + + eval_subtract(t1, result, t1); // t1.rev_sub(result.data(), std::min(x_sw, mod.size() + 1), ws); - if (eval_lt(t1, 0)) { - Backend p2; - eval_bit_set(p2, Backend::limb_bits * (mod.size() + 1)); - eval_add(t1, p2); - } + if (eval_lt(t1, 0)) { + Backend p2; + eval_bit_set(p2, Backend::limb_bits * (mod.size() + 1)); + eval_add(t1, p2); + } - eval_reduce_below(t1, mod); + eval_reduce_below(t1, mod); - if (eval_lt(result, 0)) { - eval_subtract(t1, mod, t1); - } + if (eval_lt(result, 0)) { + eval_subtract(t1, mod, t1); + } - result = t1; - return; - } else { - // too big, fall back to normal division - Backend t2; - divide_unsigned_helper(&result, result, mod, t2); - result = t2; - return; - } - - } + result = t1; + return; + } else { + // too big, fall back to normal division + Backend t2; + divide_unsigned_helper(&result, result, mod, t2); + result = t2; + return; + } + + } #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/multiprecision/montgomery/reduce.hpp b/include/boost/multiprecision/montgomery/reduce.hpp index e92022f21..98d8a59b1 100644 --- a/include/boost/multiprecision/montgomery/reduce.hpp +++ b/include/boost/multiprecision/montgomery/reduce.hpp @@ -1,3 +1,13 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2019 Nil Foundation AG +// Copyright (c) 2018-2019 Mikhail Komarov +// Copyright (c) 2018-2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + #include #include @@ -19,87 +29,91 @@ namespace boost { #pragma warning(push) #pragma warning(disable:4127) // conditional expression is constant #endif - template - inline void redc(MontgomeryBackend &result) BOOST_MP_NOEXCEPT_IF ( - is_non_throwing_montgomery_int::value) { - using default_ops::eval_multiply_add; - using default_ops::eval_lt; + template + inline void redc(MontgomeryBackend &result) - typedef cpp_int_backend cpp_three_int_backend; - typename MontgomeryBackend::allocator_type alloc; + BOOST_MP_NOEXCEPT_IF ( + is_non_throwing_montgomery_int::value) { - const size_t p_size = result.m_params.p_words(); - const limb_type p_dash = result.m_params.p_dash(); - const size_t z_size = 2 * (result.m_params.p_words() + 1); + using default_ops::eval_multiply_add; + using default_ops::eval_lt; + typedef cpp_int_backend cpp_three_int_backend; + typename MontgomeryBackend::allocator_type alloc; - container::vector z(result.size(), 0); + const size_t p_size = result.m_params.p_words(); + const limb_type p_dash = result.m_params.p_dash(); + const size_t z_size = 2 * (result.m_params.p_words() + 1); - eval_export_bits(result, z.rbegin(), MontgomeryBackend::limb_bits); - z.resize(z_size, 0); + container::vector z(result.size(), 0); - if (result.size() < z_size) { - result.resize(z_size, z_size); - } + eval_export_bits(result, z.rbegin(), MontgomeryBackend::limb_bits); - cpp_three_int_backend w(z[0]); + z.resize(z_size, 0); - result.limbs()[0] = w.limbs()[0] * p_dash; + if (result.size() < z_size) { + result.resize(z_size, z_size); + } - eval_multiply_add(w, result.limbs()[0], result.m_params.p().backend().limbs()[0]); - eval_right_shift(w, MontgomeryBackend::limb_bits); + cpp_three_int_backend w(z[0]); - for (size_t i = 1; i != p_size; ++i) { - for (size_t j = 0; j < i; ++j) { - eval_multiply_add(w, result.limbs()[j], result.m_params.p().backend().limbs()[i - j]); - } + result.limbs()[0] = w.limbs()[0] * p_dash; - eval_add(w, z[i]); + eval_multiply_add(w, result.limbs()[0], result.m_params.p().backend().limbs()[0]); + eval_right_shift(w, MontgomeryBackend::limb_bits); - result.limbs()[i] = w.limbs()[0] * p_dash; + for (size_t i = 1; i != p_size; ++i) { + for (size_t j = 0; j < i; ++j) { + eval_multiply_add(w, result.limbs()[j], result.m_params.p().backend().limbs()[i - j]); + } - eval_multiply_add(w, result.limbs()[i], result.m_params.p().backend().limbs()[0]); + eval_add(w, z[i]); - eval_right_shift(w, MontgomeryBackend::limb_bits); - } + result.limbs()[i] = w.limbs()[0] * p_dash; - for (size_t i = 0; i != p_size; ++i) { - for (size_t j = i + 1; j != p_size; ++j) { - eval_multiply_add(w, result.limbs()[j], result.m_params.p().backend().limbs()[p_size + i - j]); - } + eval_multiply_add(w, result.limbs()[i], result.m_params.p().backend().limbs()[0]); - eval_add(w, z[p_size + i]); + eval_right_shift(w, MontgomeryBackend::limb_bits); + } - result.limbs()[i] = w.limbs()[0]; + for (size_t i = 0; i != p_size; ++i) { + for (size_t j = i + 1; j != p_size; ++j) { + eval_multiply_add(w, result.limbs()[j], + result.m_params.p().backend().limbs()[p_size + i - j]); + } - eval_right_shift(w, MontgomeryBackend::limb_bits); - } + eval_add(w, z[p_size + i]); - eval_add(w, z[z_size - 1]); + result.limbs()[i] = w.limbs()[0]; - result.limbs()[p_size] = w.limbs()[0]; - result.limbs()[p_size + 1] = w.limbs()[1]; + eval_right_shift(w, MontgomeryBackend::limb_bits); + } + eval_add(w, z[z_size - 1]); + + result.limbs()[p_size] = w.limbs()[0]; + result.limbs()[p_size + 1] = w.limbs()[1]; - if (result.size() != p_size + 1) { - result.resize(p_size + 1, p_size + 1); - } - result.normalize(); - //if (!eval_lt(result, result.m_params.p().backend())) { - //eval_subtract(result, result.m_params.p().backend()); - //} + if (result.size() != p_size + 1) { + result.resize(p_size + 1, p_size + 1); + } + result.normalize(); + //if (!eval_lt(result, result.m_params.p().backend())) { + //eval_subtract(result, result.m_params.p().backend()); + //} - //nil::crypto3::ct::conditional_copy_mem(borrow, result.limbs(), ws.begin(), ws.begin() + (result.m_params.p_words() + 1), (result.m_params.p_words() + 1)); - //clear_mem(result.m_params.limbs() + result.m_params.p_words(), z_size - result.m_params.p_words() - 2); - // This check comes after we've used it but that's ok here - //nil::crypto3::ct::unpoison(&borrow, 1); + //nil::crypto3::ct::conditional_copy_mem(borrow, result.limbs(), ws.begin(), ws.begin() + (result.m_params.p_words() + 1), (result.m_params.p_words() + 1)); + //clear_mem(result.m_params.limbs() + result.m_params.p_words(), z_size - result.m_params.p_words() - 2); - } + // This check comes after we've used it but that's ok here + //nil::crypto3::ct::unpoison(&borrow, 1); + + } #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/multiprecision/montgomery/reduce_below.hpp b/include/boost/multiprecision/montgomery/reduce_below.hpp index 909c6f181..2217b03d3 100644 --- a/include/boost/multiprecision/montgomery/reduce_below.hpp +++ b/include/boost/multiprecision/montgomery/reduce_below.hpp @@ -1,3 +1,13 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2019 Nil Foundation AG +// Copyright (c) 2018-2019 Mikhail Komarov +// Copyright (c) 2018-2019 Alexey Moskvin +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + #ifndef CRYPTO3_REDUCE_BELOW_HPP #define CRYPTO3_REDUCE_BELOW_HPP diff --git a/include/boost/multiprecision/montgomery_adaptor.hpp b/include/boost/multiprecision/montgomery_adaptor.hpp deleted file mode 100644 index 7984d2f3c..000000000 --- a/include/boost/multiprecision/montgomery_adaptor.hpp +++ /dev/null @@ -1,222 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright 2018 John Maddock. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_MULTIPRECISION_COMPLEX_ADAPTOR_HPP -#define BOOST_MULTIPRECISION_COMPLEX_ADAPTOR_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost{ -namespace multiprecision{ -namespace backends{ - -template -struct montgomery_adaptor -{ -protected: - BackendBase m_base; - montgomery_params m_mod; -public: - BackendBase& base_data() - { - return m_base; - } - const BackendBase& base_data() const - { - return m_base; - } - montgomery_params& mod_data() - { - return m_mod; - } - const montgomery_params& mod_data() const - { - return m_mod; - } - - //typedef typename Backend::signed_types signed_types; - //typedef typename Backend::unsigned_types unsigned_types; - //typedef typename Backend::float_types float_types; - //typedef typename Backend::exponent_type exponent_type; - - montgomery_adaptor() {} - montgomery_adaptor(const montgomery_adaptor& o) : m_base(o.base_data()), m_mod(o.mod_data()) {} -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - montgomery_adaptor(montgomery_adaptor&& o) : m_base(std::move(o.base_data())), m_mod(std::move(o.mod_data())) {} -#endif - montgomery_adaptor(const BackendBase& val) - : m_base(val) {} - - montgomery_adaptor(const BackendBase& val, const montgomery_params& mod) : m_base(val), m_mod(mod) {} - - montgomery_adaptor(const montgomery_params& mod) : m_base(0), m_mod(mod) {} - - montgomery_adaptor& operator=(const montgomery_adaptor& o) - { - m_base = o.base_data(); - m_mod = o.mod_data(); - return *this; - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - montgomery_adaptor& operator=(montgomery_adaptor&& o) BOOST_NOEXCEPT - { - m_base = std::move(o.base_data()); - m_mod = std::move(o.mod_data()); - return *this; - } -#endif - - int compare(const montgomery_adaptor& o)const - { - // They are either equal or not: - return (m_base.compare(o.base_data()) == 0) && (m_mod.compare(o.mod_data()) == 0) ? 0 : 1; - } - template - int compare(const T& val)const - { - using default_ops::eval_lt; - return (m_base.compare(val) == 0) && eval_lt(m_mod, val) ? 0 : 1; - } - - void swap(montgomery_adaptor& o) - { - base_data().swap(o.base_data()); - mod_data().swap(o.mod_data()); - } - - std::string str(std::streamsize dig, std::ios_base::fmtflags f)const - { - montgomery_adaptor> tmp = this; - redc(tmp); - return str(tmp.base_data()); - } - -}; - -template -inline typename enable_if, bool>::type eval_eq(const montgomery_adaptor& a, const T& b) BOOST_NOEXCEPT -{ - return a.compare(b) == 0; -} - -template -inline void eval_add(montgomery_adaptor& result, const montgomery_adaptor& o) -{ - eval_add(result.base_data(), o.base_data()); - redc(result); -} -template -inline void eval_subtract(montgomery_adaptor& result, const montgomery_adaptor& o) -{ - BackendBase tmp = result.base_data(); - eval_subtract(tmp, o.base_data()); - if (eval_lt(tmp, 0)) { - BOOST_THROW_EXCEPTION(std::range_error("Montgomery less than zero")); - } - result.base_data() = tmp; -} - -template -inline void eval_multiply(montgomery_adaptor& result, const montgomery_adaptor& o) -{ - eval_multiply(result.base_data(), o.base_data()); - redc(result); -} - -template -inline void eval_divide(montgomery_adaptor& result, const montgomery_adaptor& o) -{ - eval_divide(result.base_data(), o.base_data()); -} - -template -inline bool eval_is_zero(const montgomery_adaptor& val) BOOST_NOEXCEPT -{ - using default_ops::eval_is_zero; - return eval_is_zero(val.base_data()); -} -template -inline int eval_get_sign(const montgomery_adaptor&) -{ - return 1; -} - -template -inline typename disable_if_c::value>::type eval_convert_to(Result* result, const montgomery_adaptor& val) -{ - using default_ops::eval_is_zero; - using default_ops::eval_convert_to; - if (!eval_is_zero(val.imag_data())) - { - BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar.")); - } - eval_convert_to(result, val.real_data()); -} - -template -inline void assign_components(montgomery_adaptor& result, const T& a, const montgomery_params& b) -{ - result.base_data() = a; - result.mod_data() = b; -} - -template -inline void eval_sqrt(montgomery_adaptor& result, const montgomery_adaptor& val) -{ - eval_sqrt(result.base_data(), val.base_data()); -} - -template -inline void eval_abs(montgomery_adaptor& result, const montgomery_adaptor& val) -{ - result = val; -} - -template -inline void eval_pow(montgomery_adaptor& result, const montgomery_adaptor& b, const montgomery_adaptor& e) -{ - using default_ops::eval_acos; - using default_ops::eval_exp; - montgomery_adaptor t; - eval_log(t, b); - eval_multiply(t, e); - eval_exp(result, t); - redc(result); -} - -template -inline void eval_exp(montgomery_adaptor& result, const montgomery_adaptor& arg) -{ - using default_ops::eval_exp; - - eval_exp(result.base_data(), arg.base_data()); - result.mod_data() = arg.mod_data(); - redc(result); -} - -template -inline void eval_log(montgomery_adaptor& result, const montgomery_adaptor& arg) -{ - using default_ops::eval_log; - - eval_log(result.base_data(), arg.base_data()); - result.mod_data() = arg.mod_data(); - redc(result); -} - -} // namespace multiprecision - -} // namespaces - -#endif diff --git a/meta/libraries.json b/meta/libraries.json index ce2f2eb18..2438e1ea2 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -1,16 +1,16 @@ { - "key": "multiprecision", - "name": "Multiprecision", - "authors": [ - "John Maddock", - "Christopher Kormanyos" - ], - "description": "Extended precision arithmetic types for floating point, integer andrational arithmetic.", - "category": [ - "Math" - ], - "maintainers": [ - "John Maddock ", - "christopher Kormanyos " - ] + "key": "multiprecision", + "name": "Multiprecision", + "authors": [ + "John Maddock", + "Christopher Kormanyos" + ], + "description": "Extended precision arithmetic types for floating point, integer and rational arithmetic.", + "category": [ + "Math" + ], + "maintainers": [ + "John Maddock ", + "christopher Kormanyos " + ] } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e08d47dfe..db586c0b9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -39,8 +39,8 @@ if(BOOST_CMAKE) ${CMAKE_WORKSPACE_NAME}::regexp ) else() - find_package(Boost 1.70.0 REQUIRED chrono exception timer filesystem filesystem - unit_test_framework serialization regex ) + find_package(Boost 1.68.0 REQUIRED chrono exception timer filesystem + unit_test_framework serialization regex) cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_multiprecision ${Boost_LIBRARIES} @@ -75,23 +75,31 @@ cm_test_link_libraries(multiprecision_test_settings) # target_link_libraries(no_eh_support boost_throw_exception) # cm_target_link_test_libs(no_eh_support) -try_compile(GMP_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_gmp.cpp - LINK_LIBRARIES ${GMP_LIBRARIES} - CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${GMP_INCLUDES}") +if(GMP_FOUND) + try_compile(GMP_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_gmp.cpp + LINK_LIBRARIES ${GMP_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${GMP_INCLUDES}") +endif() -try_compile(MPFR_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfr.cpp - LINK_LIBRARIES ${MPFR_LIBRARIES} - CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPFR_INCLUDES}") +if(MPFR_FOUND) + try_compile(MPFR_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfr.cpp + LINK_LIBRARIES ${MPFR_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPFR_INCLUDES}") +endif() -try_compile(TOMMATH_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_tommath.cpp - LINK_LIBRARIES ${TomMath_LIBRARIES} - CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${TomMath_INCLUDES}") +if(TOMMATH_FOUND) + try_compile(TOMMATH_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_tommath.cpp + LINK_LIBRARIES ${TomMath_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${TomMath_INCLUDES}") +endif() try_compile(FLOAT128_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_float128.cpp) -try_compile(MPFI_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfi.cpp - LINK_LIBRARIES ${MPFI_LIBRARIES} - CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPFI_INCLUDES}") +if(MPFI_FOUND) + try_compile(MPFI_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_mpfi.cpp + LINK_LIBRARIES ${MPFI_LIBRARIES} + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPFI_INCLUDES}") +endif() try_compile(INTEL_QUAD_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_intel_quad.cpp CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'") @@ -100,18 +108,10 @@ try_compile(MPC_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../conf LINK_LIBRARIES ${MPC_LIBRARIES} CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${MPC_INCLUDES}") -try_compile(EIGEN_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_eigen.cpp - CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${EIGEN3_INCLUDE_DIR}") - -message(${EIGEN3_INCLUDE_DIR}) -message(GMP_COMPILED=${GMP_COMPILED}) -message(MPFR_COMPILED=${MPFR_COMPILED}) -message(TOMMATH_COMPILED=${TOMMATH_COMPILED}) -message(FLOAT128_COMPILED=${FLOAT128_COMPILED}) -message(MPFI_COMPILED=${MPFI_COMPILED}) -message(INTEL_QUAD_COMPILED=${INTEL_QUAD_COMPILED}) -message(MPC_COMPILED=${MPC_COMPILED}) -message(EIGEN_COMPILED=${EIGEN_COMPILED}) +if(EIGEN_FOUND) + try_compile(EIGEN_COMPILED ${CMAKE_BINARY_DIR} ${CURRENT_TEST_SOURCES_DIR}/../config/has_eigen.cpp + CMAKE_FLAGS "-DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" "-DINCLUDE_DIRECTORIES=${EIGEN3_INCLUDE_DIR}") +endif() #cm_test(NAME GMP_MY SOURCES ${CURRENT_TEST_SOURCES_DIR}/../config/has_float128.cpp) #target_link_libraries(GMP_MY ${Quadmath_LIBRARY}) @@ -125,7 +125,7 @@ target_link_libraries(multiprecision_test_test_arithmetic_backend_concept no_eh_ cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_1 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_1.cpp) target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_1 no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_2.cpp) -target_link_libraries( multiprecision_test_test_arithmetic_cpp_dec_float_2 no_eh_support) +target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_2 no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_3.cpp) target_link_libraries(multiprecision_test_test_arithmetic_cpp_dec_float_3 no_eh_support) cm_test(NAME multiprecision_test_test_arithmetic_cpp_dec_float_3m SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_cpp_dec_float_3m.cpp) @@ -254,15 +254,15 @@ if(MPFI_COMPILED) target_include_directories(multiprecision_test_test_arithmetic_mpfi_50 PRIVATE ${MPFI_INCLUDES}) endif() -if (INTEL_QUAD_COMPILED) +if(INTEL_QUAD_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_float_128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_float_128.cpp) endif() -if (FLOAT128_COMPILED) +if(FLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_float_128_quad SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_float_128.cpp) endif() -if (MPC_COMPILED) +if(MPC_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_mpc SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_mpc.cpp) target_link_libraries(multiprecision_test_test_arithmetic_mpc ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_include_directories(multiprecision_test_test_arithmetic_mpc PRIVATE ${GMP_INCLUDES}) @@ -270,25 +270,25 @@ if (MPC_COMPILED) target_link_libraries(multiprecision_test_test_mpfr_mpc_precisions ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_include_directories(multiprecision_test_test_mpfr_mpc_precisions PRIVATE ${GMP_INCLUDES}) endif() -if (MPFI_COMPILED) +if(MPFI_COMPILED) cm_test(NAME multiprecision_test_test_mpfi_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpfi_precisions.cpp) target_link_libraries(multiprecision_test_test_mpfi_precisions ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_include_directories(multiprecision_test_test_mpfi_precisions PRIVATE ${MPFI_INCLUDES}) endif() -if (GMP_COMPILED) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_mpf_precisions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mpf_precisions.cpp) target_link_libraries(multiprecision_test_test_mpf_precisions ${GMP_LIBRARIES}) target_include_directories(multiprecision_test_test_mpf_precisions PRIVATE ${GMP_INCLUDES}) endif() -if ((MPC_COMPILED) AND (FLOAT128_COMPILED)) +if((MPC_COMPILED) AND (FLOAT128_COMPILED)) cm_test(NAME multiprecision_test_test_complex SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_complex.cpp) endif() cm_test(NAME multiprecision_test_test_arithmetic_complex_adaptor SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex_adaptor.cpp) cm_test(NAME multiprecision_test_test_arithmetic_complex_adaptor_2 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex_adaptor_2.cpp) -if (FLOAT128_COMPILED) +if(FLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_arithmetic_complex128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_arithmetic_complex128.cpp) endif() @@ -448,11 +448,11 @@ if(TOMMATH_COMPILED) cm_test(NAME multiprecision_test_test_move_tommath SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) target_compile_definitions(multiprecision_test_test_move_tommath PUBLIC -DTEST_TOMMATH) target_link_libraries(multiprecision_test_test_move_tommath ${TomMath_LIBRARIES} no_eh_support) + target_compile_definitions(multiprecision_test_test_move_tommath PUBLIC -DTEST_CPP_INT) + target_link_libraries(multiprecision_test_test_move_tommath no_eh_support) endif() cm_test(NAME multiprecision_test_test_move_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_move.cpp) -target_compile_definitions(multiprecision_test_test_move_tommath PUBLIC -DTEST_CPP_INT) -target_link_libraries(multiprecision_test_test_move_tommath no_eh_support) if(GMP_COMPILED) cm_test(NAME multiprecision_test_test_gmp_conversions SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_gmp_conversions.cpp) @@ -495,7 +495,7 @@ cm_test(NAME multiprecision_test_test_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/t cm_test(NAME multiprecision_test_test_cpp_int_lit SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cpp_int_lit.cpp) target_link_libraries(multiprecision_test_test_cpp_int_lit no_eh_support) -if ((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPFI_COMPILED) AND (TOMMATH_COMPILED) AND (FLOAT128_COMPILED)) +if((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPFI_COMPILED) AND (TOMMATH_COMPILED) AND (FLOAT128_COMPILED)) cm_test(NAME multiprecision_test_test_convert_from_cpp_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_int.cpp) target_link_libraries(multiprecision_test_test_convert_from_cpp_int ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) @@ -503,57 +503,57 @@ if ((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPFI_COMPILED) AND (TOMMATH_COMPILED cm_test(NAME multiprecision_test_test_convert_from_mpz_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpz_int.cpp) target_link_libraries(multiprecision_test_test_convert_from_mpz_int ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_mpz_int PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_tom_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_tom_int.cpp) target_link_libraries(multiprecision_test_test_convert_from_tom_int ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_tom_int PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_cpp_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_rational.cpp) target_link_libraries(multiprecision_test_test_convert_from_cpp_rational ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_cpp_rational PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_gmp_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_gmp_rational.cpp) target_link_libraries(test_convert_from_gmp_rational ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_gmp_rational PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_tom_rational SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_tom_rational.cpp) target_link_libraries(test_convert_from_tom_rational ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_tom_rational PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_cpp_bin_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_bin_float.cpp) target_link_libraries(test_convert_from_cpp_bin_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_cpp_bin_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_cpp_dec_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_cpp_dec_float.cpp) target_link_libraries(test_convert_from_cpp_dec_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_cpp_dec_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_mpf_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpf_float.cpp) target_link_libraries(test_convert_from_mpf_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_mpf_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_mpfr_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpfr_float.cpp) target_link_libraries(test_convert_from_mpfr_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_mpfr_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_mpfi_float SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_mpfi_float.cpp) target_link_libraries(test_convert_from_mpfi_float ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_mpfi_float PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) cm_test(NAME multiprecision_test_test_convert_from_float128 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_convert_from_float128.cpp) target_link_libraries(test_convert_from_float128 ${QUADMATH_LIBRARIES} ${TomMath_LIBRARIES} - ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) + ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_test_convert_from_float128 PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) endif() @@ -594,7 +594,7 @@ endif() if(MPFI_COMPILED) cm_test(NAME multiprecision_test_test_float_io_mpfi SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_float_io.cpp) target_compile_definitions(multiprecision_test_test_float_io_mpfi PUBLIC -DTEST_MPFI_50) - target_link_libraries(multiprecision_test_test_float_io_mpfi ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} ${TomMath_LIBRARIES} no_eh_support) + target_link_libraries(multiprecision_test_test_float_io_mpfi ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} ${TomMath_LIBRARIES} no_eh_support) target_include_directories(multiprecision_test_test_float_io_mpfi PRIVATE ${GMP_INCLUDES} ${MPFI_INCLUDES}) endif() @@ -899,7 +899,7 @@ target_link_libraries(multiprecision_test_bug12039 no_eh_support) cm_test(NAME multiprecision_test_git_issue_30 SOURCES ${CURRENT_TEST_SOURCES_DIR}/git_issue_30.cpp COMPILE_ONLY) cm_test(NAME multiprecision_test_git_issue_98 SOURCES ${CURRENT_TEST_SOURCES_DIR}/git_issue_98.cpp COMPILE_ONLY) -if ((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPC_COMPILED) AND (FLOAT128_COMPILED)) +if((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPC_COMPILED) AND (FLOAT128_COMPILED)) cm_test(NAME multiprecision_test_git_issue_98 ${CURRENT_TEST_SOURCES_DIR}/git_issue_98.cpp COMPILE_ONLY) target_link_libraries(multiprecision_test_git_issue_98 ${QUADMATH_LIBRARIES} ${MPC_LIBRARIES} ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) target_compile_definitions(multiprecision_test_git_issue_98 PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPC -DFLOAT128_COMPILED) @@ -908,10 +908,10 @@ endif() cm_test(NAME multiprecision_test_issue_13301 SOURCES ${CURRENT_TEST_SOURCES_DIR}/issue_13301.cpp) cm_test(NAME multiprecision_test_issue_13148 SOURCES ${CURRENT_TEST_SOURCES_DIR}/issue_13148.cpp) -if ((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPFI_COMPILED) AND (TomMath_COMPILED) AND (FLOAT128_COMPILED)) +if((GMP_COMPILED) AND (MPFR_COMPILED) AND (MPFI_COMPILED) AND (TomMath_COMPILED) AND (FLOAT128_COMPILED)) cm_test(NAME multiprecision_test_test_hash ${CURRENT_TEST_SOURCES_DIR}/test_hash.cpp COMPILE_ONLY) target_link_libraries(multiprecision_test_test_hash ${QUADMATH_LIBRARIES} ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} - ${GMP_LIBRARIES} ${TomMath_LIBRARIES}) + ${GMP_LIBRARIES} ${TomMath_LIBRARIES}) target_compile_definitions(multiprecision_test_test_hash PRIVATE -DHAS_GMP -DHAS_MPFR -DHAS_MPFI -DHAS_TOMMATH -DFLOAT128_COMPILED) endif() @@ -1031,19 +1031,19 @@ endif() ]] file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/compile_fail/*.cpp) foreach(FILEB ${TEST_FILES}) - if ((GMP_COMPILED) AND (MPFR_COMPILED)) + if((GMP_COMPILED) AND (MPFR_COMPILED)) get_filename_component(NAME ${FILEB} NAME_WE) cm_test(NAME multiprecision_test_compile_fail_${NAME} SOURCES ${FILEB} COMPILE_ONLY WILL_FAIL) target_compile_definitions(multiprecision_test_compile_fail_${NAME} PRIVATE -DTEST_GMP -DTEST_MPFR) endif() endforeach() -if (BUILD_WITH_SOURCES_DIR) +if(BUILD_WITH_SOURCES_DIR) file(GLOB TEST_FILES ${CURRENT_TEST_SOURCES_DIR}/concepts/*.cpp) foreach(FILEB ${TEST_FILES}) get_filename_component(NAME ${FILEB} NAME_WE) - if (MPFR_COMPILED) + if(MPFR_COMPILED) cm_test(NAME multiprecision_test_concepts_${NAME}_mpfr_50 SOURCES ${FILEB} COMPILE_ONLY) target_compile_definitions(multiprecision_test_concepts_${NAME}_mpfr_50 PUBLIC -DTEST_MPFR_50) target_link_libraries(multiprecision_test_concepts_${NAME}_mpfr_50 ${MPFR_LIBRARIES}) @@ -1071,7 +1071,7 @@ if (BUILD_WITH_SOURCES_DIR) endif() - if (GMP_COMPILED) + if(GMP_COMPILED) cm_test(NAME multiprecision_test_concepts_${NAME}_mpf50 SOURCES ${FILEB} COMPILE_ONLY) target_compile_definitions(multiprecision_test_concepts_${NAME}_mpf50 PUBLIC -DTEST_MPF_50) target_link_libraries(multiprecision_test_concepts_${NAME}_mpf50 ${GMP_LIBRARIES}) @@ -1118,7 +1118,7 @@ target_link_libraries(multiprecision_test_cpp_bin_float_snips no_eh_support) cm_test(NAME multiprecision_test_debug_adaptor_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/debug_adaptor_snips.cpp) target_link_libraries(multiprecision_test_debug_adaptor_snips no_eh_support) -if (FLOAT128_COMPILED) +if(FLOAT128_COMPILED) #TODO: fix this #[ run float128_snips.cpp quadmath no_eh_eg_support : : : [ check-target-builds ../config//has_float128 : : no ] ] cm_test(NAME multiprecision_test_debug_adaptor_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/debug_adaptor_snips.cpp) @@ -1139,7 +1139,7 @@ target_link_libraries(multiprecision_test_floating_point_examples no_eh_support) cm_test(NAME multiprecision_test_integer_examples SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/integer_examples.cpp) target_link_libraries(multiprecision_test_integer_examples no_eh_support) -if (MPFI_COMPILED) +if(MPFI_COMPILED) cm_test(NAME multiprecision_test_logged_adaptor SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/logged_adaptor.cpp) target_link_libraries(multiprecision_test_logged_adaptor ${GMP_LIBRARIES} ${MPFR_LIBRARIES} ${MPFI_LIBRARIES} no_eh_support) target_include_directories(multiprecision_test_logged_adaptor PRIVATE ${GMP_INCLUDES} ${MPFI_INCLUDES}) @@ -1148,12 +1148,12 @@ endif() cm_test(NAME multiprecision_test_mixed_integer_arithmetic SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/mixed_integer_arithmetic.cpp) target_link_libraries(multiprecision_test_mixed_integer_arithmetic no_eh_support) -if (FLOAT128_COMPILED) +if(FLOAT128_COMPILED) #TODO: fix this #[ run numeric_limits_snips.cpp no_eh_eg_support /boost//test_exec_monitor : : : [ requires cxx11_numeric_limits ] [ check-target-builds ../config//has_float128 : quadmath ] ] endif() -if (GMP_COMPILED) +if(GMP_COMPILED) #TODO: enable this #cm_test(NAME multiprecision_test_random_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/random_snips.cpp) #target_link_libraries(multiprecision_test_random_snips ${GMP_LIBRARIES} no_eh_support) @@ -1163,28 +1163,28 @@ endif() cm_test(NAME multiprecision_test_safe_prime SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/safe_prime.cpp) target_link_libraries(multiprecision_test_safe_prime no_eh_support) -if (GMP_COMPILED) +if(GMP_COMPILED) cm_test(NAME multiprecision_test_gmp_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/gmp_snips.cpp) target_link_libraries(multiprecision_test_gmp_snips ${GMP_LIBRARIES} no_eh_support) target_include_directories(multiprecision_test_gmp_snips PRIVATE ${GMP_INCLUDES}) endif() -if (MPFI_COMPILED) +if(MPFI_COMPILED) cm_test(NAME multiprecision_test_mpfi_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/mpfi_snips.cpp) target_link_libraries(multiprecision_test_mpfi_snips ${GMP_LIBRARIES} ${MPFI_LIBRARIES} ${MPFR_LIBRARIES} no_eh_support) target_include_directories(multiprecision_test_mpfi_snips PRIVATE ${GMP_INCLUDES} ${MPFI_INCLUDES}) endif() -if (MPFR_COMPILED) +if(MPFR_COMPILED) cm_test(NAME multiprecision_test_mpfr_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/mpfr_snips.cpp) target_link_libraries(multiprecision_test_mpfr_snips ${GMP_LIBRARIES} ${MPFR_LIBRARIES} no_eh_support) target_include_directories(multiprecision_test_mpfr_snips PRIVATE ${GMP_INCLUDES}) endif() -if (TOMMATH_COMPILED) +if(TOMMATH_COMPILED) cm_test(NAME multiprecision_test_tommath_snips SOURCES ${CURRENT_TEST_SOURCES_DIR}/../example/tommath_snips.cpp) target_link_libraries(multiprecision_test_tommath_snips ${TomMath_LIBRARIES} no_eh_support) target_include_directories(multiprecision_test_tommath_snips PRIVATE ${TomMath_INCLUDES}) endif() -include_directories(${CMAKE_WORKSPACE_SOURCES_DIR}) +include_directories(${CMAKE_WORKSPACE_SOURCES_DIR}) \ No newline at end of file diff --git a/test/zerg.cpp b/test/test_modular.cpp similarity index 59% rename from test/zerg.cpp rename to test/test_modular.cpp index 8f846d119..aa4475272 100644 --- a/test/zerg.cpp +++ b/test/test_modular.cpp @@ -1,16 +1,20 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2019 Nil Foundation AG +// Copyright (c) 2018-2019 Mikhail Komarov +// Copyright (c) 2018-2019 Alexey Moskvin // -// Created by Zerg1996 on 2019-04-27. -// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// -//#include #include #include #include #include -int main() -{ +int main() { using namespace boost::multiprecision; using default_ops::eval_msb; @@ -29,4 +33,4 @@ int main() x = x * x2; std::cout << "Mult:" << x << std::endl; return 0; -} +} \ No newline at end of file From d362b652d6c948e0e0e74d9e5ba4612bc4c1f1c1 Mon Sep 17 00:00:00 2001 From: Mikhail Komarov Date: Sun, 14 Jul 2019 16:55:55 +0300 Subject: [PATCH 015/294] .clang_format-compliant reformatting done #2 --- .../concepts/mp_number_archetypes.hpp | 112 +- .../boost/multiprecision/cpp_bin_float.hpp | 4164 ++++++----- .../boost/multiprecision/cpp_bin_float/io.hpp | 1287 ++-- .../boost/multiprecision/cpp_dec_float.hpp | 5942 +++++++++------- include/boost/multiprecision/cpp_int/add.hpp | 326 +- .../boost/multiprecision/cpp_int/bitwise.hpp | 1627 +++-- .../multiprecision/cpp_int/comparison.hpp | 720 +- .../multiprecision/cpp_int/import_export.hpp | 520 +- .../boost/multiprecision/cpp_int/limits.hpp | 597 +- include/boost/multiprecision/cpp_int/misc.hpp | 1471 ++-- .../boost/multiprecision/cpp_int/multiply.hpp | 271 +- .../multiprecision/detail/default_ops.hpp | 6307 +++++++++-------- .../multiprecision/detail/dynamic_array.hpp | 43 +- .../boost/multiprecision/detail/et_ops.hpp | 1789 +++-- .../detail/functions/constants.hpp | 570 +- .../multiprecision/detail/functions/trig.hpp | 363 +- .../multiprecision/detail/integer_ops.hpp | 772 +- .../multiprecision/detail/number_base.hpp | 2865 ++++---- .../multiprecision/detail/ublas_interop.hpp | 135 +- .../multiprecision/detail/utype_helper.hpp | 178 +- include/boost/multiprecision/gmp.hpp | 4778 +++++++------ include/boost/multiprecision/integer.hpp | 359 +- .../boost/multiprecision/logged_adaptor.hpp | 905 +-- .../boost/multiprecision/modular_adaptor.hpp | 404 +- .../boost/multiprecision/modular_inverse.hpp | 345 +- .../multiprecision/montgomery_int/bitwise.hpp | 1424 ++-- .../montgomery_int/comparison.hpp | 1128 +-- .../multiprecision/montgomery_int/divide.hpp | 1057 +-- .../multiprecision/montgomery_int/misc.hpp | 1525 ++-- .../montgomery_int/montgomery_int.hpp | 4822 +++++++------ .../montgomery_int/multiply.hpp | 2363 +++--- .../montgomery_int/serialize.hpp | 377 +- .../multiprecision/montgomery_inverse.hpp | 217 +- .../multiprecision/montgomery_params.hpp | 202 +- include/boost/multiprecision/mpc.hpp | 2240 +++--- include/boost/multiprecision/mpfr.hpp | 5056 +++++++------ include/boost/multiprecision/number.hpp | 4453 ++++++------ include/boost/multiprecision/pow_mod.hpp | 318 +- include/boost/multiprecision/prime.hpp | 685 +- .../boost/multiprecision/rational_adaptor.hpp | 588 +- include/boost/multiprecision/ressol.hpp | 214 +- include/boost/multiprecision/tommath.hpp | 1311 ++-- 42 files changed, 35238 insertions(+), 29592 deletions(-) diff --git a/include/boost/multiprecision/concepts/mp_number_archetypes.hpp b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp index 30dca7d0c..d566f6e88 100644 --- a/include/boost/multiprecision/concepts/mp_number_archetypes.hpp +++ b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp @@ -6,67 +6,67 @@ #ifndef BOOST_MATH_CONCEPTS_ER_HPP #define BOOST_MATH_CONCEPTS_ER_HPP -#include -#include -#include -#include +#include #include -#include #include #include -#include +#include +#include +#include +#include +#include -namespace boost{ -namespace multiprecision{ -namespace concepts{ +namespace boost { +namespace multiprecision { +namespace concepts { #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:4244) +#pragma warning(disable : 4244) #endif struct number_backend_float_architype { - typedef mpl::list signed_types; - typedef mpl::list unsigned_types; - typedef mpl::list float_types; - typedef int exponent_type; + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + typedef int exponent_type; number_backend_float_architype() { m_value = 0; std::cout << "Default construct" << std::endl; } - number_backend_float_architype(const number_backend_float_architype& o) + number_backend_float_architype(const number_backend_float_architype &o) { std::cout << "Copy construct" << std::endl; m_value = o.m_value; } - number_backend_float_architype& operator = (const number_backend_float_architype& o) + number_backend_float_architype &operator=(const number_backend_float_architype &o) { m_value = o.m_value; std::cout << "Assignment (" << m_value << ")" << std::endl; return *this; } - number_backend_float_architype& operator = (boost::ulong_long_type i) + number_backend_float_architype &operator=(boost::ulong_long_type i) { m_value = i; std::cout << "UInt Assignment (" << i << ")" << std::endl; return *this; } - number_backend_float_architype& operator = (boost::long_long_type i) + number_backend_float_architype &operator=(boost::long_long_type i) { m_value = i; std::cout << "Int Assignment (" << i << ")" << std::endl; return *this; } - number_backend_float_architype& operator = (long double d) + number_backend_float_architype &operator=(long double d) { m_value = d; std::cout << "long double Assignment (" << d << ")" << std::endl; return *this; } - number_backend_float_architype& operator = (const char* s) + number_backend_float_architype &operator=(const char *s) { #ifndef BOOST_NO_EXCEPTIONS try @@ -75,7 +75,7 @@ struct number_backend_float_architype m_value = boost::lexical_cast(s); #ifndef BOOST_NO_EXCEPTIONS } - catch(const std::exception&) + catch (const std::exception &) { BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse input string: \"") + s + std::string("\" as a valid floating point number."))); } @@ -83,24 +83,24 @@ struct number_backend_float_architype std::cout << "const char* Assignment (" << s << ")" << std::endl; return *this; } - void swap(number_backend_float_architype& o) + void swap(number_backend_float_architype &o) { std::cout << "Swapping (" << m_value << " with " << o.m_value << ")" << std::endl; std::swap(m_value, o.m_value); } - std::string str(std::streamsize digits, std::ios_base::fmtflags f)const + std::string str(std::streamsize digits, std::ios_base::fmtflags f) const { std::stringstream ss; ss.flags(f); - if(digits) + if (digits) ss.precision(digits); else ss.precision(std::numeric_limits::digits10 + 3); - boost::intmax_t i = m_value; + boost::intmax_t i = m_value; boost::uintmax_t u = m_value; - if(!(f & std::ios_base::scientific) && m_value == i) + if (!(f & std::ios_base::scientific) && m_value == i) ss << i; - else if(!(f & std::ios_base::scientific) && m_value == u) + else if (!(f & std::ios_base::scientific) && m_value == u) ss << u; else ss << m_value; @@ -113,22 +113,22 @@ struct number_backend_float_architype std::cout << "Negating (" << m_value << ")" << std::endl; m_value = -m_value; } - int compare(const number_backend_float_architype& o)const + int compare(const number_backend_float_architype &o) const { std::cout << "Comparison" << std::endl; return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0); } - int compare(boost::long_long_type i)const + int compare(boost::long_long_type i) const { std::cout << "Comparison with int" << std::endl; return m_value > i ? 1 : (m_value < i ? -1 : 0); } - int compare(boost::ulong_long_type i)const + int compare(boost::ulong_long_type i) const { std::cout << "Comparison with unsigned" << std::endl; return m_value > i ? 1 : (m_value < i ? -1 : 0); } - int compare(long double d)const + int compare(long double d) const { std::cout << "Comparison with long double" << std::endl; return m_value > d ? 1 : (m_value < d ? -1 : 0); @@ -136,71 +136,71 @@ struct number_backend_float_architype long double m_value; }; -inline void eval_add(number_backend_float_architype& result, const number_backend_float_architype& o) +inline void eval_add(number_backend_float_architype &result, const number_backend_float_architype &o) { std::cout << "Addition (" << result.m_value << " += " << o.m_value << ")" << std::endl; result.m_value += o.m_value; } -inline void eval_subtract(number_backend_float_architype& result, const number_backend_float_architype& o) +inline void eval_subtract(number_backend_float_architype &result, const number_backend_float_architype &o) { std::cout << "Subtraction (" << result.m_value << " -= " << o.m_value << ")" << std::endl; result.m_value -= o.m_value; } -inline void eval_multiply(number_backend_float_architype& result, const number_backend_float_architype& o) +inline void eval_multiply(number_backend_float_architype &result, const number_backend_float_architype &o) { std::cout << "Multiplication (" << result.m_value << " *= " << o.m_value << ")" << std::endl; result.m_value *= o.m_value; } -inline void eval_divide(number_backend_float_architype& result, const number_backend_float_architype& o) +inline void eval_divide(number_backend_float_architype &result, const number_backend_float_architype &o) { std::cout << "Division (" << result.m_value << " /= " << o.m_value << ")" << std::endl; result.m_value /= o.m_value; } -inline void eval_convert_to(boost::ulong_long_type* result, const number_backend_float_architype& val) +inline void eval_convert_to(boost::ulong_long_type *result, const number_backend_float_architype &val) { *result = static_cast(val.m_value); } -inline void eval_convert_to(boost::long_long_type* result, const number_backend_float_architype& val) +inline void eval_convert_to(boost::long_long_type *result, const number_backend_float_architype &val) { *result = static_cast(val.m_value); } -inline void eval_convert_to(long double* result, number_backend_float_architype& val) +inline void eval_convert_to(long double *result, number_backend_float_architype &val) { *result = val.m_value; } -inline void eval_frexp(number_backend_float_architype& result, const number_backend_float_architype& arg, int* exp) +inline void eval_frexp(number_backend_float_architype &result, const number_backend_float_architype &arg, int *exp) { result = std::frexp(arg.m_value, exp); } -inline void eval_ldexp(number_backend_float_architype& result, const number_backend_float_architype& arg, int exp) +inline void eval_ldexp(number_backend_float_architype &result, const number_backend_float_architype &arg, int exp) { result = std::ldexp(arg.m_value, exp); } -inline void eval_floor(number_backend_float_architype& result, const number_backend_float_architype& arg) +inline void eval_floor(number_backend_float_architype &result, const number_backend_float_architype &arg) { result = std::floor(arg.m_value); } -inline void eval_ceil(number_backend_float_architype& result, const number_backend_float_architype& arg) +inline void eval_ceil(number_backend_float_architype &result, const number_backend_float_architype &arg) { result = std::ceil(arg.m_value); } -inline void eval_sqrt(number_backend_float_architype& result, const number_backend_float_architype& arg) +inline void eval_sqrt(number_backend_float_architype &result, const number_backend_float_architype &arg) { result = std::sqrt(arg.m_value); } -inline int eval_fpclassify(const number_backend_float_architype& arg) +inline int eval_fpclassify(const number_backend_float_architype &arg) { return (boost::math::fpclassify)(arg.m_value); } -inline std::size_t hash_value(const number_backend_float_architype& v) +inline std::size_t hash_value(const number_backend_float_architype &v) { boost::hash hasher; return hasher(v.m_value); @@ -208,23 +208,25 @@ inline std::size_t hash_value(const number_backend_float_architype& v) typedef boost::multiprecision::number mp_number_float_architype; -} // namespace +} // namespace concepts -template<> -struct number_category : public mpl::int_{}; +template <> +struct number_category : public mpl::int_ +{}; -}} // namespaces +}} // namespace boost::multiprecision -namespace std{ +namespace std { template class numeric_limits > : public std::numeric_limits { - typedef std::numeric_limits base_type; + typedef std::numeric_limits base_type; typedef boost::multiprecision::number number_type; -public: - static number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); } - static number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); } + + public: + static number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); } + static number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); } static number_type lowest() BOOST_NOEXCEPT { return -(max)(); } static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } static number_type round_error() BOOST_NOEXCEPT { return base_type::round_error(); } @@ -234,7 +236,7 @@ class numeric_limits -#include #include +#include #include +#include // -// Some includes we need from Boost.Math, since we rely on that library to provide these functions: +// Some includes we need from Boost.Math, since we rely on that library to +// provide these functions: // -#include #include +#include #include #include #include @@ -25,1808 +26,2178 @@ #include #endif -namespace boost{ namespace multiprecision{ namespace backends{ +namespace boost { +namespace multiprecision { +namespace backends { -enum digit_base_type -{ - digit_base_2 = 2, - digit_base_10 = 10 -}; +enum digit_base_type { digit_base_2 = 2, digit_base_10 = 10 }; #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:4522 6326) // multiple assignment operators specified, comparison of two constants +#pragma warning(disable : 4522 6326) // multiple assignment operators specified, + // comparison of two constants #endif -namespace detail{ +namespace detail { template -inline typename enable_if_c::value, bool>::type is_negative(U) { return false; } +inline typename enable_if_c::value, bool>::type is_negative(U) { + return false; +} template -inline typename disable_if_c::value, bool>::type is_negative(S s) { return s < 0; } +inline typename disable_if_c::value, bool>::type +is_negative(S s) { + return s < 0; +} -template ::value == number_kind_floating_point> -struct is_cpp_bin_float_implicitly_constructible_from_type -{ - static const bool value = false; +template ::value == number_kind_floating_point> +struct is_cpp_bin_float_implicitly_constructible_from_type { + static const bool value = false; }; template -struct is_cpp_bin_float_implicitly_constructible_from_type -{ - static const bool value = (std::numeric_limits::digits <= (int)bit_count) - && (std::numeric_limits::radix == 2) - && std::numeric_limits::is_specialized +struct is_cpp_bin_float_implicitly_constructible_from_type { + static const bool value = + (std::numeric_limits::digits <= (int)bit_count) && + (std::numeric_limits::radix == 2) && + std::numeric_limits::is_specialized #ifdef BOOST_HAS_FLOAT128 && !boost::is_same::value #endif - && (is_floating_point::value || is_number::value) - ; + && (is_floating_point::value || is_number::value); }; -template ::value == number_kind_floating_point> -struct is_cpp_bin_float_explicitly_constructible_from_type -{ - static const bool value = false; +template ::value == number_kind_floating_point> +struct is_cpp_bin_float_explicitly_constructible_from_type { + static const bool value = false; }; template -struct is_cpp_bin_float_explicitly_constructible_from_type -{ - static const bool value = (std::numeric_limits::digits > (int)bit_count) - && (std::numeric_limits::radix == 2) - && std::numeric_limits::is_specialized +struct is_cpp_bin_float_explicitly_constructible_from_type { + static const bool value = + (std::numeric_limits::digits > (int)bit_count) && + (std::numeric_limits::radix == 2) && + std::numeric_limits::is_specialized #ifdef BOOST_HAS_FLOAT128 && !boost::is_same::value #endif ; }; -} +} // namespace detail -template -class cpp_bin_float -{ +template +class cpp_bin_float { public: - static const unsigned bit_count = DigitBase == digit_base_2 ? Digits : (Digits * 1000uL) / 301uL + (((Digits * 1000uL) % 301) ? 2u : 1u); - typedef cpp_int_backend::value ? bit_count : 0, bit_count, is_void::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> rep_type; - typedef cpp_int_backend::value ? 2 * bit_count : 0, 2 * bit_count, is_void::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> double_rep_type; - - typedef typename rep_type::signed_types signed_types; - typedef typename rep_type::unsigned_types unsigned_types; - typedef boost::mpl::list float_types; - typedef Exponent exponent_type; - - static const exponent_type max_exponent_limit = boost::integer_traits::const_max - 2 * static_cast(bit_count); - static const exponent_type min_exponent_limit = boost::integer_traits::const_min + 2 * static_cast(bit_count); - - BOOST_STATIC_ASSERT_MSG(MinExponent >= min_exponent_limit, "Template parameter MinExponent is too negative for our internal logic to function correctly, sorry!"); - BOOST_STATIC_ASSERT_MSG(MaxExponent <= max_exponent_limit, "Template parameter MaxExponent is too large for our internal logic to function correctly, sorry!"); - BOOST_STATIC_ASSERT_MSG(MinExponent <= 0, "Template parameter MinExponent can not be positive!"); - BOOST_STATIC_ASSERT_MSG(MaxExponent >= 0, "Template parameter MaxExponent can not be negative!"); - - static const exponent_type max_exponent = MaxExponent == 0 ? max_exponent_limit : MaxExponent; - static const exponent_type min_exponent = MinExponent == 0 ? min_exponent_limit : MinExponent; - - static const exponent_type exponent_zero = max_exponent + 1; - static const exponent_type exponent_infinity = max_exponent + 2; - static const exponent_type exponent_nan = max_exponent + 3; + static const unsigned bit_count = + DigitBase == digit_base_2 + ? Digits + : (Digits * 1000uL) / 301uL + (((Digits * 1000uL) % 301) ? 2u : 1u); + typedef cpp_int_backend::value ? bit_count : 0, bit_count, + is_void::value ? unsigned_magnitude + : signed_magnitude, + unchecked, Allocator> + rep_type; + typedef cpp_int_backend< + is_void::value ? 2 * bit_count : 0, 2 * bit_count, + is_void::value ? unsigned_magnitude : signed_magnitude, + unchecked, Allocator> + double_rep_type; + + typedef typename rep_type::signed_types signed_types; + typedef typename rep_type::unsigned_types unsigned_types; + typedef boost::mpl::list float_types; + typedef Exponent exponent_type; + + static const exponent_type max_exponent_limit = + boost::integer_traits::const_max - + 2 * static_cast(bit_count); + static const exponent_type min_exponent_limit = + boost::integer_traits::const_min + + 2 * static_cast(bit_count); + + BOOST_STATIC_ASSERT_MSG(MinExponent >= min_exponent_limit, + "Template parameter MinExponent is too negative for " + "our internal logic to function correctly, sorry!"); + BOOST_STATIC_ASSERT_MSG(MaxExponent <= max_exponent_limit, + "Template parameter MaxExponent is too large for our " + "internal logic to function correctly, sorry!"); + BOOST_STATIC_ASSERT_MSG( + MinExponent <= 0, "Template parameter MinExponent can not be positive!"); + BOOST_STATIC_ASSERT_MSG( + MaxExponent >= 0, "Template parameter MaxExponent can not be negative!"); + + static const exponent_type max_exponent = + MaxExponent == 0 ? max_exponent_limit : MaxExponent; + static const exponent_type min_exponent = + MinExponent == 0 ? min_exponent_limit : MinExponent; + + static const exponent_type exponent_zero = max_exponent + 1; + static const exponent_type exponent_infinity = max_exponent + 2; + static const exponent_type exponent_nan = max_exponent + 3; private: + rep_type m_data; + exponent_type m_exponent; + bool m_sign; - rep_type m_data; - exponent_type m_exponent; - bool m_sign; public: - cpp_bin_float() BOOST_MP_NOEXCEPT_IF(noexcept(rep_type())) : m_data(), m_exponent(exponent_zero), m_sign(false) {} + cpp_bin_float() BOOST_MP_NOEXCEPT_IF(noexcept(rep_type())) + : m_data(), m_exponent(exponent_zero), m_sign(false) {} - cpp_bin_float(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(rep_type(std::declval()))) + cpp_bin_float(const cpp_bin_float &o) + BOOST_MP_NOEXCEPT_IF(noexcept(rep_type(std::declval()))) : m_data(o.m_data), m_exponent(o.m_exponent), m_sign(o.m_sign) {} - template - cpp_bin_float(const cpp_bin_float &o, typename boost::enable_if_c<(bit_count >= cpp_bin_float::bit_count)>::type const* = 0) - { - *this = o; - } - template - explicit cpp_bin_float(const cpp_bin_float &o, typename boost::disable_if_c<(bit_count >= cpp_bin_float::bit_count)>::type const* = 0) - : m_exponent(o.exponent()), m_sign(o.sign()) - { - *this = o; - } - template - cpp_bin_float(const Float& f, - typename boost::enable_if_c::value>::type const* = 0) - : m_data(), m_exponent(0), m_sign(false) - { - this->assign_float(f); - } - - template - explicit cpp_bin_float(const Float& f, - typename boost::enable_if_c::value>::type const* = 0) - : m_data(), m_exponent(0), m_sign(false) - { - this->assign_float(f); - } -#ifdef BOOST_HAS_FLOAT128 - template - cpp_bin_float(const Float& f, + template + cpp_bin_float( + const cpp_bin_float &o, typename boost::enable_if_c< - boost::is_same::value - && ((int)bit_count >= 113) - >::type const* = 0) - : m_data(), m_exponent(0), m_sign(false) - { - this->assign_float(f); - } - template - explicit cpp_bin_float(const Float& f, + (bit_count >= + cpp_bin_float::bit_count)>::type const * = + 0) { + *this = o; + } + template + explicit cpp_bin_float( + const cpp_bin_float &o, + typename boost::disable_if_c< + (bit_count >= + cpp_bin_float::bit_count)>::type const * = 0) + : m_exponent(o.exponent()), m_sign(o.sign()) { + *this = o; + } + template + cpp_bin_float(const Float &f, + typename boost::enable_if_c< + detail::is_cpp_bin_float_implicitly_constructible_from_type< + Float, bit_count>::value>::type const * = 0) + : m_data(), m_exponent(0), m_sign(false) { + this->assign_float(f); + } + + template + explicit cpp_bin_float( + const Float &f, typename boost::enable_if_c< - boost::is_same::value - && ((int)bit_count < 113) - >::type const* = 0) - : m_data(), m_exponent(0), m_sign(false) - { - this->assign_float(f); - } + detail::is_cpp_bin_float_explicitly_constructible_from_type< + Float, bit_count>::value>::type const * = 0) + : m_data(), m_exponent(0), m_sign(false) { + this->assign_float(f); + } +#ifdef BOOST_HAS_FLOAT128 + template + cpp_bin_float( + const Float &f, + typename boost::enable_if_c::value && + ((int)bit_count >= 113)>::type const * = 0) + : m_data(), m_exponent(0), m_sign(false) { + this->assign_float(f); + } + template + explicit cpp_bin_float( + const Float &f, + typename boost::enable_if_c::value && + ((int)bit_count < 113)>::type const * = 0) + : m_data(), m_exponent(0), m_sign(false) { + this->assign_float(f); + } #endif - cpp_bin_float& operator=(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval() = std::declval())) - { - m_data = o.m_data; - m_exponent = o.m_exponent; - m_sign = o.m_sign; - return *this; - } - - template - cpp_bin_float& operator=(const cpp_bin_float &f) - { - switch(eval_fpclassify(f)) - { - case FP_ZERO: - m_data = limb_type(0); - m_sign = f.sign(); - m_exponent = exponent_zero; - break; - case FP_NAN: - m_data = limb_type(0); - m_sign = false; - m_exponent = exponent_nan; - break;; - case FP_INFINITE: - m_data = limb_type(0); - m_sign = f.sign(); - m_exponent = exponent_infinity; - break; - default: - typename cpp_bin_float::rep_type b(f.bits()); - this->exponent() = f.exponent() + (E)bit_count - (E)cpp_bin_float::bit_count; - this->sign() = f.sign(); - copy_and_round(*this, b); - } - return *this; - } + cpp_bin_float &operator=(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF( + noexcept(std::declval() = std::declval())) { + m_data = o.m_data; + m_exponent = o.m_exponent; + m_sign = o.m_sign; + return *this; + } + + template + cpp_bin_float &operator=(const cpp_bin_float &f) { + switch (eval_fpclassify(f)) { + case FP_ZERO: + m_data = limb_type(0); + m_sign = f.sign(); + m_exponent = exponent_zero; + break; + case FP_NAN: + m_data = limb_type(0); + m_sign = false; + m_exponent = exponent_nan; + break; + ; + case FP_INFINITE: + m_data = limb_type(0); + m_sign = f.sign(); + m_exponent = exponent_infinity; + break; + default: + typename cpp_bin_float::rep_type b(f.bits()); + this->exponent() = f.exponent() + (E)bit_count - + (E)cpp_bin_float::bit_count; + this->sign() = f.sign(); + copy_and_round(*this, b); + } + return *this; + } #ifdef BOOST_HAS_FLOAT128 - template - typename boost::enable_if_c< + template + typename boost::enable_if_c< (number_category::value == number_kind_floating_point) - //&& (std::numeric_limits::digits <= (int)bit_count) - && ((std::numeric_limits::radix == 2) || (boost::is_same::value)), cpp_bin_float&>::type - operator=(const Float& f) + //&& (std::numeric_limits::digits <= (int)bit_count) + && ((std::numeric_limits::radix == 2) || + (boost::is_same::value)), + cpp_bin_float &>::type + operator=(const Float &f) #else - template - typename boost::enable_if_c< + template + typename boost::enable_if_c< (number_category::value == number_kind_floating_point) - //&& (std::numeric_limits::digits <= (int)bit_count) - && (std::numeric_limits::radix == 2), cpp_bin_float&>::type - operator=(const Float& f) + //&& (std::numeric_limits::digits <= (int)bit_count) + && (std::numeric_limits::radix == 2), + cpp_bin_float &>::type + operator=(const Float &f) #endif - { - return assign_float(f); - } + { + return assign_float(f); + } #ifdef BOOST_HAS_FLOAT128 - template - typename boost::enable_if_c::value, cpp_bin_float& >::type assign_float(Float f) - { - using default_ops::eval_add; - typedef typename boost::multiprecision::detail::canonical::type bf_int_type; - if(f == 0) - { - m_data = limb_type(0); - m_sign = (signbitq(f) > 0); - m_exponent = exponent_zero; - return *this; - } - else if(isnanq(f)) - { - m_data = limb_type(0); - m_sign = false; - m_exponent = exponent_nan; - return *this; - } - else if(isinfq(f)) - { - m_data = limb_type(0); - m_sign = (f < 0); - m_exponent = exponent_infinity; - return *this; - } - if(f < 0) - { - *this = -f; - this->negate(); - return *this; - } - - typedef typename mpl::front::type ui_type; - m_data = static_cast(0u); + template + typename boost::enable_if_c::value, + cpp_bin_float &>::type + assign_float(Float f) { + using default_ops::eval_add; + typedef typename boost::multiprecision::detail::canonical< + int, cpp_bin_float>::type bf_int_type; + if (f == 0) { + m_data = limb_type(0); + m_sign = (signbitq(f) > 0); + m_exponent = exponent_zero; + return *this; + } else if (isnanq(f)) { + m_data = limb_type(0); m_sign = false; - m_exponent = 0; - - static const int bits = sizeof(int) * CHAR_BIT - 1; - int e; - f = frexpq(f, &e); - while(f) - { - f = ldexpq(f, bits); - e -= bits; - int ipart = (int)truncq(f); - f -= ipart; - m_exponent += bits; - cpp_bin_float t; - t = static_cast(ipart); - eval_add(*this, t); - } - m_exponent += static_cast(e); + m_exponent = exponent_nan; + return *this; + } else if (isinfq(f)) { + m_data = limb_type(0); + m_sign = (f < 0); + m_exponent = exponent_infinity; + return *this; + } + if (f < 0) { + *this = -f; + this->negate(); return *this; - } + } + + typedef typename mpl::front::type ui_type; + m_data = static_cast(0u); + m_sign = false; + m_exponent = 0; + + static const int bits = sizeof(int) * CHAR_BIT - 1; + int e; + f = frexpq(f, &e); + while (f) { + f = ldexpq(f, bits); + e -= bits; + int ipart = (int)truncq(f); + f -= ipart; + m_exponent += bits; + cpp_bin_float t; + t = static_cast(ipart); + eval_add(*this, t); + } + m_exponent += static_cast(e); + return *this; + } #endif #ifdef BOOST_HAS_FLOAT128 - template - typename boost::enable_if_c::value && !is_same::value, cpp_bin_float&>::type assign_float(Float f) + template + typename boost::enable_if_c::value && + !is_same::value, + cpp_bin_float &>::type + assign_float(Float f) #else - template - typename boost::enable_if_c::value, cpp_bin_float&>::type assign_float(Float f) + template + typename boost::enable_if_c::value, + cpp_bin_float &>::type + assign_float(Float f) #endif - { - BOOST_MATH_STD_USING - using default_ops::eval_add; - typedef typename boost::multiprecision::detail::canonical::type bf_int_type; - - switch((boost::math::fpclassify)(f)) - { - case FP_ZERO: - m_data = limb_type(0); - m_sign = ((boost::math::signbit)(f) > 0); - m_exponent = exponent_zero; - return *this; - case FP_NAN: - m_data = limb_type(0); - m_sign = false; - m_exponent = exponent_nan; - return *this; - case FP_INFINITE: - m_data = limb_type(0); - m_sign = (f < 0); - m_exponent = exponent_infinity; - return *this; - } - if(f < 0) - { - *this = -f; - this->negate(); - return *this; - } - - typedef typename mpl::front::type ui_type; - m_data = static_cast(0u); + { + BOOST_MATH_STD_USING + using default_ops::eval_add; + typedef typename boost::multiprecision::detail::canonical< + int, cpp_bin_float>::type bf_int_type; + + switch ((boost::math::fpclassify)(f)) { + case FP_ZERO: + m_data = limb_type(0); + m_sign = ((boost::math::signbit)(f) > 0); + m_exponent = exponent_zero; + return *this; + case FP_NAN: + m_data = limb_type(0); m_sign = false; - m_exponent = 0; - - static const int bits = sizeof(int) * CHAR_BIT - 1; - int e; - f = frexp(f, &e); - while(f) - { - f = ldexp(f, bits); - e -= bits; + m_exponent = exponent_nan; + return *this; + case FP_INFINITE: + m_data = limb_type(0); + m_sign = (f < 0); + m_exponent = exponent_infinity; + return *this; + } + if (f < 0) { + *this = -f; + this->negate(); + return *this; + } + + typedef typename mpl::front::type ui_type; + m_data = static_cast(0u); + m_sign = false; + m_exponent = 0; + + static const int bits = sizeof(int) * CHAR_BIT - 1; + int e; + f = frexp(f, &e); + while (f) { + f = ldexp(f, bits); + e -= bits; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - int ipart = itrunc(f); + int ipart = itrunc(f); #else - int ipart = static_cast(f); + int ipart = static_cast(f); #endif - f -= ipart; - m_exponent += bits; - cpp_bin_float t; - t = static_cast(ipart); - eval_add(*this, t); - } - m_exponent += static_cast(e); + f -= ipart; + m_exponent += bits; + cpp_bin_float t; + t = static_cast(ipart); + eval_add(*this, t); + } + m_exponent += static_cast(e); + return *this; + } + + template + typename boost::enable_if_c< + (number_category::value == number_kind_floating_point) && + !boost::is_floating_point::value && is_number::value, + cpp_bin_float &>::type + assign_float(Float f) { + BOOST_MATH_STD_USING + using default_ops::eval_add; + using default_ops::eval_convert_to; + using default_ops::eval_get_sign; + using default_ops::eval_subtract; + + typedef typename boost::multiprecision::detail::canonical::type + f_int_type; + typedef typename boost::multiprecision::detail::canonical< + int, cpp_bin_float>::type bf_int_type; + + switch (eval_fpclassify(f)) { + case FP_ZERO: + m_data = limb_type(0); + m_sign = ((boost::math::signbit)(f) > 0); + m_exponent = exponent_zero; return *this; - } - - template - typename boost::enable_if_c< - (number_category::value == number_kind_floating_point) - && !boost::is_floating_point::value - && is_number::value, - cpp_bin_float&>::type assign_float(Float f) - { - BOOST_MATH_STD_USING - using default_ops::eval_add; - using default_ops::eval_get_sign; - using default_ops::eval_convert_to; - using default_ops::eval_subtract; - - typedef typename boost::multiprecision::detail::canonical::type f_int_type; - typedef typename boost::multiprecision::detail::canonical::type bf_int_type; - - switch(eval_fpclassify(f)) - { - case FP_ZERO: - m_data = limb_type(0); - m_sign = ((boost::math::signbit)(f) > 0); - m_exponent = exponent_zero; - return *this; - case FP_NAN: - m_data = limb_type(0); - m_sign = false; - m_exponent = exponent_nan; - return *this; - case FP_INFINITE: - m_data = limb_type(0); - m_sign = (f < 0); - m_exponent = exponent_infinity; - return *this; - } - if(eval_get_sign(f) < 0) - { - f.negate(); - *this = f; - this->negate(); - return *this; - } - - typedef typename mpl::front::type ui_type; - m_data = static_cast(0u); + case FP_NAN: + m_data = limb_type(0); m_sign = false; - m_exponent = 0; - - static const int bits = sizeof(int) * CHAR_BIT - 1; - int e; - eval_frexp(f, f, &e); - while(eval_get_sign(f) != 0) - { - eval_ldexp(f, f, bits); - e -= bits; - int ipart; - eval_convert_to(&ipart, f); - eval_subtract(f, static_cast(ipart)); - m_exponent += bits; - eval_add(*this, static_cast(ipart)); - } - m_exponent += e; - if(m_exponent > max_exponent) - m_exponent = exponent_infinity; - if(m_exponent < min_exponent) - { - m_data = limb_type(0u); - m_exponent = exponent_zero; - m_sign = ((boost::math::signbit)(f) > 0); - } - else if(eval_get_sign(m_data) == 0) - { - m_exponent = exponent_zero; - m_sign = ((boost::math::signbit)(f) > 0); - } + m_exponent = exponent_nan; return *this; - } - - template - typename boost::enable_if, cpp_bin_float&>::type operator=(const I& i) - { - using default_ops::eval_bit_test; - if(!i) - { - m_data = static_cast(0); - m_exponent = exponent_zero; - m_sign = false; - } - else - { - typedef typename make_unsigned::type ui_type; - ui_type fi = static_cast(boost::multiprecision::detail::unsigned_abs(i)); - typedef typename boost::multiprecision::detail::canonical::type ar_type; - m_data = static_cast(fi); - unsigned shift = msb(fi); - if(shift >= bit_count) - { - m_exponent = static_cast(shift); - m_data = static_cast(fi >> (shift + 1 - bit_count)); - } - else - { - m_exponent = static_cast(shift); - eval_left_shift(m_data, bit_count - shift - 1); - } - BOOST_ASSERT(eval_bit_test(m_data, bit_count-1)); - m_sign = detail::is_negative(i); - } + case FP_INFINITE: + m_data = limb_type(0); + m_sign = (f < 0); + m_exponent = exponent_infinity; return *this; - } - - cpp_bin_float& operator=(const char *s); - - void swap(cpp_bin_float &o) BOOST_NOEXCEPT - { - m_data.swap(o.m_data); - std::swap(m_exponent, o.m_exponent); - std::swap(m_sign, o.m_sign); - } - - std::string str(std::streamsize dig, std::ios_base::fmtflags f) const; - - void negate() - { - if(m_exponent != exponent_nan) - m_sign = !m_sign; - } - - int compare(const cpp_bin_float &o) const BOOST_NOEXCEPT - { - if(m_sign != o.m_sign) - return (m_exponent == exponent_zero) && (m_exponent == o.m_exponent) ? 0 : m_sign ? -1 : 1; - int result; - if(m_exponent == exponent_nan) - return -1; - else if(m_exponent != o.m_exponent) - { - if(m_exponent == exponent_zero) - result = -1; - else if(o.m_exponent == exponent_zero) - result = 1; - else - result = m_exponent > o.m_exponent ? 1 : -1; - } - else - result = m_data.compare(o.m_data); - if(m_sign) - result = -result; - return result; - } - template - int compare(const A& o) const BOOST_NOEXCEPT - { - cpp_bin_float b; - b = o; - return compare(b); - } - - rep_type& bits() { return m_data; } - const rep_type& bits()const { return m_data; } - exponent_type& exponent() { return m_exponent; } - const exponent_type& exponent()const { return m_exponent; } - bool& sign() { return m_sign; } - const bool& sign()const { return m_sign; } - void check_invariants() - { - using default_ops::eval_bit_test; - using default_ops::eval_is_zero; - if((m_exponent <= max_exponent) && (m_exponent >= min_exponent)) - { - BOOST_ASSERT(eval_bit_test(m_data, bit_count - 1)); + } + if (eval_get_sign(f) < 0) { + f.negate(); + *this = f; + this->negate(); + return *this; + } + + typedef typename mpl::front::type ui_type; + m_data = static_cast(0u); + m_sign = false; + m_exponent = 0; + + static const int bits = sizeof(int) * CHAR_BIT - 1; + int e; + eval_frexp(f, f, &e); + while (eval_get_sign(f) != 0) { + eval_ldexp(f, f, bits); + e -= bits; + int ipart; + eval_convert_to(&ipart, f); + eval_subtract(f, static_cast(ipart)); + m_exponent += bits; + eval_add(*this, static_cast(ipart)); + } + m_exponent += e; + if (m_exponent > max_exponent) + m_exponent = exponent_infinity; + if (m_exponent < min_exponent) { + m_data = limb_type(0u); + m_exponent = exponent_zero; + m_sign = ((boost::math::signbit)(f) > 0); + } else if (eval_get_sign(m_data) == 0) { + m_exponent = exponent_zero; + m_sign = ((boost::math::signbit)(f) > 0); + } + return *this; + } + + template + typename boost::enable_if, cpp_bin_float &>::type + operator=(const I &i) { + using default_ops::eval_bit_test; + if (!i) { + m_data = static_cast(0); + m_exponent = exponent_zero; + m_sign = false; + } else { + typedef typename make_unsigned::type ui_type; + ui_type fi = + static_cast(boost::multiprecision::detail::unsigned_abs(i)); + typedef typename boost::multiprecision::detail::canonical< + ui_type, rep_type>::type ar_type; + m_data = static_cast(fi); + unsigned shift = msb(fi); + if (shift >= bit_count) { + m_exponent = static_cast(shift); + m_data = static_cast(fi >> (shift + 1 - bit_count)); + } else { + m_exponent = static_cast(shift); + eval_left_shift(m_data, bit_count - shift - 1); } + BOOST_ASSERT(eval_bit_test(m_data, bit_count - 1)); + m_sign = detail::is_negative(i); + } + return *this; + } + + cpp_bin_float &operator=(const char *s); + + void swap(cpp_bin_float &o) BOOST_NOEXCEPT { + m_data.swap(o.m_data); + std::swap(m_exponent, o.m_exponent); + std::swap(m_sign, o.m_sign); + } + + std::string str(std::streamsize dig, std::ios_base::fmtflags f) const; + + void negate() { + if (m_exponent != exponent_nan) + m_sign = !m_sign; + } + + int compare(const cpp_bin_float &o) const BOOST_NOEXCEPT { + if (m_sign != o.m_sign) + return (m_exponent == exponent_zero) && (m_exponent == o.m_exponent) + ? 0 + : m_sign ? -1 : 1; + int result; + if (m_exponent == exponent_nan) + return -1; + else if (m_exponent != o.m_exponent) { + if (m_exponent == exponent_zero) + result = -1; + else if (o.m_exponent == exponent_zero) + result = 1; else - { - BOOST_ASSERT(m_exponent > max_exponent); - BOOST_ASSERT(m_exponent <= exponent_nan); - BOOST_ASSERT(eval_is_zero(m_data)); - } - } - template - void serialize(Archive & ar, const unsigned int /*version*/) - { - ar & boost::serialization::make_nvp("data", m_data); - ar & boost::serialization::make_nvp("exponent", m_exponent); - ar & boost::serialization::make_nvp("sign", m_sign); - } + result = m_exponent > o.m_exponent ? 1 : -1; + } else + result = m_data.compare(o.m_data); + if (m_sign) + result = -result; + return result; + } + template int compare(const A &o) const BOOST_NOEXCEPT { + cpp_bin_float b; + b = o; + return compare(b); + } + + rep_type &bits() { return m_data; } + const rep_type &bits() const { return m_data; } + exponent_type &exponent() { return m_exponent; } + const exponent_type &exponent() const { return m_exponent; } + bool &sign() { return m_sign; } + const bool &sign() const { return m_sign; } + void check_invariants() { + using default_ops::eval_bit_test; + using default_ops::eval_is_zero; + if ((m_exponent <= max_exponent) && (m_exponent >= min_exponent)) { + BOOST_ASSERT(eval_bit_test(m_data, bit_count - 1)); + } else { + BOOST_ASSERT(m_exponent > max_exponent); + BOOST_ASSERT(m_exponent <= exponent_nan); + BOOST_ASSERT(eval_is_zero(m_data)); + } + } + template + void serialize(Archive &ar, const unsigned int /*version*/) { + ar &boost::serialization::make_nvp("data", m_data); + ar &boost::serialization::make_nvp("exponent", m_exponent); + ar &boost::serialization::make_nvp("sign", m_sign); + } }; #ifdef BOOST_MSVC #pragma warning(pop) #endif -template -inline void copy_and_round(cpp_bin_float &res, Int &arg, int bits_to_keep = cpp_bin_float::bit_count) -{ - // Precondition: exponent of res must have been set before this function is called - // as we may need to adjust it based on how many bits_to_keep in arg are set. - using default_ops::eval_msb; - using default_ops::eval_lsb; - using default_ops::eval_left_shift; - using default_ops::eval_bit_test; - using default_ops::eval_right_shift; - using default_ops::eval_increment; - using default_ops::eval_get_sign; - - // cancellation may have resulted in arg being all zeros: - if(eval_get_sign(arg) == 0) - { - res.exponent() = cpp_bin_float::exponent_zero; - res.sign() = false; - res.bits() = static_cast(0u); - return; - } - int msb = eval_msb(arg); - if(static_cast(bits_to_keep) > msb + 1) - { - // Must have had cancellation in subtraction, - // or be converting from a narrower type, so shift left: - res.bits() = arg; - eval_left_shift(res.bits(), bits_to_keep - msb - 1); - res.exponent() -= static_cast(bits_to_keep - msb - 1); - } - else if(static_cast(bits_to_keep) < msb + 1) - { - // We have more bits_to_keep than we need, so round as required, - // first get the rounding bit: - bool roundup = eval_bit_test(arg, msb - bits_to_keep); - // Then check for a tie: - if(roundup && (msb - bits_to_keep == (int)eval_lsb(arg))) - { - // Ties round towards even: - if(!eval_bit_test(arg, msb - bits_to_keep + 1)) - roundup = false; - } - // Shift off the bits_to_keep we don't need: - eval_right_shift(arg, msb - bits_to_keep + 1); - res.exponent() += static_cast(msb - bits_to_keep + 1); - if(roundup) - { - eval_increment(arg); - if(bits_to_keep) - { - if(eval_bit_test(arg, bits_to_keep)) - { - // This happens very very rairly, all the bits left after - // truncation must be 1's and we're rounding up an order of magnitude: - eval_right_shift(arg, 1u); - ++res.exponent(); - } - } - else - { - // We get here when bits_to_keep is zero but we're rounding up, - // as a result we end up with a single digit that is a 1: - ++bits_to_keep; - } +template +inline void copy_and_round( + cpp_bin_float &res, + Int &arg, + int bits_to_keep = cpp_bin_float::bit_count) { + // Precondition: exponent of res must have been set before this function is + // called as we may need to adjust it based on how many bits_to_keep in arg + // are set. + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_increment; + using default_ops::eval_left_shift; + using default_ops::eval_lsb; + using default_ops::eval_msb; + using default_ops::eval_right_shift; + + // cancellation may have resulted in arg being all zeros: + if (eval_get_sign(arg) == 0) { + res.exponent() = cpp_bin_float::exponent_zero; + res.sign() = false; + res.bits() = static_cast(0u); + return; + } + int msb = eval_msb(arg); + if (static_cast(bits_to_keep) > msb + 1) { + // Must have had cancellation in subtraction, + // or be converting from a narrower type, so shift left: + res.bits() = arg; + eval_left_shift(res.bits(), bits_to_keep - msb - 1); + res.exponent() -= static_cast(bits_to_keep - msb - 1); + } else if (static_cast(bits_to_keep) < msb + 1) { + // We have more bits_to_keep than we need, so round as required, + // first get the rounding bit: + bool roundup = eval_bit_test(arg, msb - bits_to_keep); + // Then check for a tie: + if (roundup && (msb - bits_to_keep == (int)eval_lsb(arg))) { + // Ties round towards even: + if (!eval_bit_test(arg, msb - bits_to_keep + 1)) + roundup = false; + } + // Shift off the bits_to_keep we don't need: + eval_right_shift(arg, msb - bits_to_keep + 1); + res.exponent() += static_cast(msb - bits_to_keep + 1); + if (roundup) { + eval_increment(arg); + if (bits_to_keep) { + if (eval_bit_test(arg, bits_to_keep)) { + // This happens very very rairly, all the bits left after + // truncation must be 1's and we're rounding up an order of magnitude: + eval_right_shift(arg, 1u); + ++res.exponent(); + } + } else { + // We get here when bits_to_keep is zero but we're rounding up, + // as a result we end up with a single digit that is a 1: + ++bits_to_keep; } - if(bits_to_keep != cpp_bin_float::bit_count) - { - // Normalize result when we're rounding to fewer bits than we can hold, only happens in conversions - // to narrower types: - eval_left_shift(arg, cpp_bin_float::bit_count - bits_to_keep); - res.exponent() -= static_cast(cpp_bin_float::bit_count - bits_to_keep); - } - res.bits() = arg; - } - else - { - res.bits() = arg; - } - if(!bits_to_keep && !res.bits().limbs()[0]) - { - // We're keeping zero bits and did not round up, so result is zero: - res.exponent() = cpp_bin_float::exponent_zero; - return; - } - // Result must be normalized: - BOOST_ASSERT(((int)eval_msb(res.bits()) == cpp_bin_float::bit_count - 1)); - - if(res.exponent() > cpp_bin_float::max_exponent) - { - // Overflow: - res.exponent() = cpp_bin_float::exponent_infinity; - res.bits() = static_cast(0u); - } - else if(res.exponent() < cpp_bin_float::min_exponent) - { - // Underflow: - res.exponent() = cpp_bin_float::exponent_zero; - res.bits() = static_cast(0u); - } + } + if (bits_to_keep != cpp_bin_float::bit_count) { + // Normalize result when we're rounding to fewer bits than we can hold, + // only happens in conversions to narrower types: + eval_left_shift(arg, cpp_bin_float::bit_count - + bits_to_keep); + res.exponent() -= + static_cast(cpp_bin_float::bit_count - + bits_to_keep); + } + res.bits() = arg; + } else { + res.bits() = arg; + } + if (!bits_to_keep && !res.bits().limbs()[0]) { + // We're keeping zero bits and did not round up, so result is zero: + res.exponent() = cpp_bin_float::exponent_zero; + return; + } + // Result must be normalized: + BOOST_ASSERT(((int)eval_msb(res.bits()) == + cpp_bin_float::bit_count - + 1)); + + if (res.exponent() > cpp_bin_float::max_exponent) { + // Overflow: + res.exponent() = cpp_bin_float::exponent_infinity; + res.bits() = static_cast(0u); + } else if (res.exponent() < + cpp_bin_float::min_exponent) { + // Underflow: + res.exponent() = cpp_bin_float::exponent_zero; + res.bits() = static_cast(0u); + } } -template -inline void do_eval_add(cpp_bin_float &res, const cpp_bin_float &a, const cpp_bin_float &b) -{ - if(a.exponent() < b.exponent()) - { - bool s = a.sign(); - do_eval_add(res, b, a); - if(res.sign() != s) - res.negate(); - return; - } - - using default_ops::eval_add; - using default_ops::eval_bit_test; - - typedef typename cpp_bin_float::exponent_type exponent_type; - - typename cpp_bin_float::double_rep_type dt; - - // Special cases first: - switch(a.exponent()) - { - case cpp_bin_float::exponent_zero: - { - bool s = a.sign(); +template +inline void do_eval_add( + cpp_bin_float &res, + const cpp_bin_float &a, + const cpp_bin_float + &b) { + if (a.exponent() < b.exponent()) { + bool s = a.sign(); + do_eval_add(res, b, a); + if (res.sign() != s) + res.negate(); + return; + } + + using default_ops::eval_add; + using default_ops::eval_bit_test; + + typedef typename cpp_bin_float::exponent_type exponent_type; + + typename cpp_bin_float::double_rep_type dt; + + // Special cases first: + switch (a.exponent()) { + case cpp_bin_float::exponent_zero: { + bool s = a.sign(); + res = b; + res.sign() = s; + return; + } + case cpp_bin_float::exponent_infinity: + if (b.exponent() == cpp_bin_float::exponent_nan) res = b; - res.sign() = s; - return; - } - case cpp_bin_float::exponent_infinity: - if(b.exponent() == cpp_bin_float::exponent_nan) - res = b; - else - res = a; - return; // result is still infinite. - case cpp_bin_float::exponent_nan: - res = a; - return; // result is still a NaN. - } - switch(b.exponent()) - { - case cpp_bin_float::exponent_zero: + else res = a; - return; - case cpp_bin_float::exponent_infinity: - res = b; - if(res.sign()) - res.negate(); - return; // result is infinite. - case cpp_bin_float::exponent_nan: - res = b; - return; // result is a NaN. - } - - BOOST_STATIC_ASSERT(boost::integer_traits::const_max - cpp_bin_float::bit_count > cpp_bin_float::max_exponent); - - bool s = a.sign(); - dt = a.bits(); - if(a.exponent() > (int)cpp_bin_float::bit_count + b.exponent()) - { - res.exponent() = a.exponent(); - } - else - { - exponent_type e_diff = a.exponent() - b.exponent(); - BOOST_ASSERT(e_diff >= 0); - eval_left_shift(dt, e_diff); - res.exponent() = a.exponent() - e_diff; - eval_add(dt, b.bits()); - } - - copy_and_round(res, dt); - res.check_invariants(); - if(res.sign() != s) + return; // result is still infinite. + case cpp_bin_float::exponent_nan: + res = a; + return; // result is still a NaN. + } + switch (b.exponent()) { + case cpp_bin_float::exponent_zero: + res = a; + return; + case cpp_bin_float::exponent_infinity: + res = b; + if (res.sign()) res.negate(); + return; // result is infinite. + case cpp_bin_float::exponent_nan: + res = b; + return; // result is a NaN. + } + + BOOST_STATIC_ASSERT(boost::integer_traits::const_max - + cpp_bin_float::bit_count > + cpp_bin_float::max_exponent); + + bool s = a.sign(); + dt = a.bits(); + if (a.exponent() > (int)cpp_bin_float::bit_count + + b.exponent()) { + res.exponent() = a.exponent(); + } else { + exponent_type e_diff = a.exponent() - b.exponent(); + BOOST_ASSERT(e_diff >= 0); + eval_left_shift(dt, e_diff); + res.exponent() = a.exponent() - e_diff; + eval_add(dt, b.bits()); + } + + copy_and_round(res, dt); + res.check_invariants(); + if (res.sign() != s) + res.negate(); } -template -inline void do_eval_subtract(cpp_bin_float &res, const cpp_bin_float &a, const cpp_bin_float &b) -{ - using default_ops::eval_subtract; - using default_ops::eval_bit_test; - using default_ops::eval_decrement; - - typename cpp_bin_float::double_rep_type dt; - - // Special cases first: - switch(a.exponent()) - { - case cpp_bin_float::exponent_zero: - if(b.exponent() == cpp_bin_float::exponent_nan) - res = std::numeric_limits > >::quiet_NaN().backend(); - else - { - bool s = a.sign(); - res = b; - if(res.exponent() == cpp_bin_float::exponent_zero) - res.sign() = false; - else if(res.sign() == s) - res.negate(); - } - return; - case cpp_bin_float::exponent_infinity: - if((b.exponent() == cpp_bin_float::exponent_nan) || (b.exponent() == cpp_bin_float::exponent_infinity)) - res = std::numeric_limits > >::quiet_NaN().backend(); - else - res = a; - return; - case cpp_bin_float::exponent_nan: - res = a; - return; // result is still a NaN. - } - switch(b.exponent()) - { - case cpp_bin_float::exponent_zero: - res = a; - return; - case cpp_bin_float::exponent_infinity: - res.exponent() = cpp_bin_float::exponent_infinity; - res.sign() = !a.sign(); - res.bits() = static_cast(0u); - return; // result is a NaN. - case cpp_bin_float::exponent_nan: +template +inline void do_eval_subtract( + cpp_bin_float &res, + const cpp_bin_float &a, + const cpp_bin_float + &b) { + using default_ops::eval_bit_test; + using default_ops::eval_decrement; + using default_ops::eval_subtract; + + typename cpp_bin_float::double_rep_type dt; + + // Special cases first: + switch (a.exponent()) { + case cpp_bin_float::exponent_zero: + if (b.exponent() == cpp_bin_float::exponent_nan) + res = std::numeric_limits>>::quiet_NaN() + .backend(); + else { + bool s = a.sign(); res = b; - return; // result is still a NaN. - } - - bool s = a.sign(); - if((a.exponent() > b.exponent()) || ((a.exponent() == b.exponent()) && a.bits().compare(b.bits()) >= 0)) - { - dt = a.bits(); - if(a.exponent() <= (int)cpp_bin_float::bit_count + b.exponent()) - { - typename cpp_bin_float::exponent_type e_diff = a.exponent() - b.exponent(); - eval_left_shift(dt, e_diff); - res.exponent() = a.exponent() - e_diff; - eval_subtract(dt, b.bits()); - } - else if(a.exponent() == (int)cpp_bin_float::bit_count + b.exponent() + 1) - { - if(eval_lsb(b.bits()) != cpp_bin_float::bit_count - 1) - { - eval_left_shift(dt, 1); - eval_decrement(dt); - res.exponent() = a.exponent() - 1; - } - else - res.exponent() = a.exponent(); - } - else - res.exponent() = a.exponent(); - } - else - { - dt = b.bits(); - if(b.exponent() <= (int)cpp_bin_float::bit_count + a.exponent()) - { - typename cpp_bin_float::exponent_type e_diff = a.exponent() - b.exponent(); - eval_left_shift(dt, -e_diff); - res.exponent() = b.exponent() + e_diff; - eval_subtract(dt, a.bits()); - } - else if(b.exponent() == (int)cpp_bin_float::bit_count + a.exponent() + 1) - { - if(eval_lsb(a.bits()) != cpp_bin_float::bit_count - 1) - { - eval_left_shift(dt, 1); - eval_decrement(dt); - res.exponent() = b.exponent() - 1; - } - else - res.exponent() = b.exponent(); - } - else - res.exponent() = b.exponent(); - s = !s; - } - - copy_and_round(res, dt); - if(res.exponent() == cpp_bin_float::exponent_zero) - res.sign() = false; - else if(res.sign() != s) - res.negate(); - res.check_invariants(); + if (res.exponent() == cpp_bin_float::exponent_zero) + res.sign() = false; + else if (res.sign() == s) + res.negate(); + } + return; + case cpp_bin_float::exponent_infinity: + if ((b.exponent() == cpp_bin_float::exponent_nan) || + (b.exponent() == cpp_bin_float::exponent_infinity)) + res = std::numeric_limits>>::quiet_NaN() + .backend(); + else + res = a; + return; + case cpp_bin_float::exponent_nan: + res = a; + return; // result is still a NaN. + } + switch (b.exponent()) { + case cpp_bin_float::exponent_zero: + res = a; + return; + case cpp_bin_float::exponent_infinity: + res.exponent() = cpp_bin_float::exponent_infinity; + res.sign() = !a.sign(); + res.bits() = static_cast(0u); + return; // result is a NaN. + case cpp_bin_float::exponent_nan: + res = b; + return; // result is still a NaN. + } + + bool s = a.sign(); + if ((a.exponent() > b.exponent()) || + ((a.exponent() == b.exponent()) && a.bits().compare(b.bits()) >= 0)) { + dt = a.bits(); + if (a.exponent() <= (int)cpp_bin_float::bit_count + + b.exponent()) { + typename cpp_bin_float::exponent_type e_diff = + a.exponent() - b.exponent(); + eval_left_shift(dt, e_diff); + res.exponent() = a.exponent() - e_diff; + eval_subtract(dt, b.bits()); + } else if (a.exponent() == + (int)cpp_bin_float::bit_count + + b.exponent() + 1) { + if (eval_lsb(b.bits()) != cpp_bin_float::bit_count - + 1) { + eval_left_shift(dt, 1); + eval_decrement(dt); + res.exponent() = a.exponent() - 1; + } else + res.exponent() = a.exponent(); + } else + res.exponent() = a.exponent(); + } else { + dt = b.bits(); + if (b.exponent() <= (int)cpp_bin_float::bit_count + + a.exponent()) { + typename cpp_bin_float::exponent_type e_diff = + a.exponent() - b.exponent(); + eval_left_shift(dt, -e_diff); + res.exponent() = b.exponent() + e_diff; + eval_subtract(dt, a.bits()); + } else if (b.exponent() == + (int)cpp_bin_float::bit_count + + a.exponent() + 1) { + if (eval_lsb(a.bits()) != cpp_bin_float::bit_count - + 1) { + eval_left_shift(dt, 1); + eval_decrement(dt); + res.exponent() = b.exponent() - 1; + } else + res.exponent() = b.exponent(); + } else + res.exponent() = b.exponent(); + s = !s; + } + + copy_and_round(res, dt); + if (res.exponent() == cpp_bin_float::exponent_zero) + res.sign() = false; + else if (res.sign() != s) + res.negate(); + res.check_invariants(); } -template -inline void eval_add(cpp_bin_float &res, const cpp_bin_float &a, const cpp_bin_float &b) -{ - if(a.sign() == b.sign()) - do_eval_add(res, a, b); - else - do_eval_subtract(res, a, b); +template +inline void eval_add( + cpp_bin_float &res, + const cpp_bin_float &a, + const cpp_bin_float + &b) { + if (a.sign() == b.sign()) + do_eval_add(res, a, b); + else + do_eval_subtract(res, a, b); } -template -inline void eval_add(cpp_bin_float &res, const cpp_bin_float &a) -{ - return eval_add(res, res, a); +template +inline void +eval_add(cpp_bin_float &res, + const cpp_bin_float + &a) { + return eval_add(res, res, a); } -template -inline void eval_subtract(cpp_bin_float &res, const cpp_bin_float &a, const cpp_bin_float &b) -{ - if(a.sign() != b.sign()) - do_eval_add(res, a, b); - else - do_eval_subtract(res, a, b); +template +inline void eval_subtract( + cpp_bin_float &res, + const cpp_bin_float &a, + const cpp_bin_float + &b) { + if (a.sign() != b.sign()) + do_eval_add(res, a, b); + else + do_eval_subtract(res, a, b); } -template -inline void eval_subtract(cpp_bin_float &res, const cpp_bin_float &a) -{ - return eval_subtract(res, res, a); +template +inline void eval_subtract( + cpp_bin_float &res, + const cpp_bin_float + &a) { + return eval_subtract(res, res, a); } -template -inline void eval_multiply(cpp_bin_float &res, const cpp_bin_float &a, const cpp_bin_float &b) -{ - using default_ops::eval_bit_test; - using default_ops::eval_multiply; - - // Special cases first: - switch(a.exponent()) - { - case cpp_bin_float::exponent_zero: - { - if(b.exponent() == cpp_bin_float::exponent_nan) - res = b; - else if(b.exponent() == cpp_bin_float::exponent_infinity) - res = std::numeric_limits > >::quiet_NaN().backend(); - else - { - bool s = a.sign() != b.sign(); - res = a; - res.sign() = s; - } - return; - } - case cpp_bin_float::exponent_infinity: - switch(b.exponent()) - { - case cpp_bin_float::exponent_zero: - res = std::numeric_limits > >::quiet_NaN().backend(); - break; - case cpp_bin_float::exponent_nan: - res = b; - break; - default: - bool s = a.sign() != b.sign(); - res = a; - res.sign() = s; - break; - } - return; - case cpp_bin_float::exponent_nan: - res = a; - return; - } - if(b.exponent() > cpp_bin_float::max_exponent) - { +template +inline void eval_multiply( + cpp_bin_float &res, + const cpp_bin_float &a, + const cpp_bin_float + &b) { + using default_ops::eval_bit_test; + using default_ops::eval_multiply; + + // Special cases first: + switch (a.exponent()) { + case cpp_bin_float::exponent_zero: { + if (b.exponent() == cpp_bin_float::exponent_nan) + res = b; + else if (b.exponent() == + cpp_bin_float::exponent_infinity) + res = std::numeric_limits>>::quiet_NaN() + .backend(); + else { bool s = a.sign() != b.sign(); + res = a; + res.sign() = s; + } + return; + } + case cpp_bin_float::exponent_infinity: + switch (b.exponent()) { + case cpp_bin_float::exponent_zero: + res = std::numeric_limits>>::quiet_NaN() + .backend(); + break; + case cpp_bin_float::exponent_nan: res = b; + break; + default: + bool s = a.sign() != b.sign(); + res = a; res.sign() = s; + break; + } + return; + case cpp_bin_float::exponent_nan: + res = a; + return; + } + if (b.exponent() > cpp_bin_float::max_exponent) { + bool s = a.sign() != b.sign(); + res = b; + res.sign() = s; + return; + } + if ((a.exponent() > 0) && (b.exponent() > 0)) { + if (cpp_bin_float::max_exponent + + 2 - a.exponent() < + b.exponent()) { + // We will certainly overflow: + bool s = a.sign() != b.sign(); + res.exponent() = cpp_bin_float::exponent_infinity; + res.sign() = s; + res.bits() = static_cast(0u); return; - } - if((a.exponent() > 0) && (b.exponent() > 0)) - { - if(cpp_bin_float::max_exponent + 2 - a.exponent() < b.exponent()) - { - // We will certainly overflow: - bool s = a.sign() != b.sign(); - res.exponent() = cpp_bin_float::exponent_infinity; - res.sign() = s; - res.bits() = static_cast(0u); - return; - } - } - if((a.exponent() < 0) && (b.exponent() < 0)) - { - if(cpp_bin_float::min_exponent - 2 - a.exponent() > b.exponent()) - { - // We will certainly underflow: - res.exponent() = cpp_bin_float::exponent_zero; - res.sign() = a.sign() != b.sign(); - res.bits() = static_cast(0u); - return; - } - } - - typename cpp_bin_float::double_rep_type dt; - eval_multiply(dt, a.bits(), b.bits()); - res.exponent() = a.exponent() + b.exponent() - (Exponent)cpp_bin_float::bit_count + 1; - copy_and_round(res, dt); - res.check_invariants(); - res.sign() = a.sign() != b.sign(); + } + } + if ((a.exponent() < 0) && (b.exponent() < 0)) { + if (cpp_bin_float::min_exponent - + 2 - a.exponent() > + b.exponent()) { + // We will certainly underflow: + res.exponent() = cpp_bin_float::exponent_zero; + res.sign() = a.sign() != b.sign(); + res.bits() = static_cast(0u); + return; + } + } + + typename cpp_bin_float::double_rep_type dt; + eval_multiply(dt, a.bits(), b.bits()); + res.exponent() = a.exponent() + b.exponent() - + (Exponent)cpp_bin_float::bit_count + + 1; + copy_and_round(res, dt); + res.check_invariants(); + res.sign() = a.sign() != b.sign(); } -template -inline void eval_multiply(cpp_bin_float &res, const cpp_bin_float &a) -{ - eval_multiply(res, res, a); +template +inline void eval_multiply( + cpp_bin_float &res, + const cpp_bin_float + &a) { + eval_multiply(res, res, a); } -template -inline typename enable_if_c::value>::type eval_multiply(cpp_bin_float &res, const cpp_bin_float &a, const U &b) -{ - using default_ops::eval_bit_test; - using default_ops::eval_multiply; - - // Special cases first: - switch(a.exponent()) - { - case cpp_bin_float::exponent_zero: - { - bool s = a.sign(); - res = a; - res.sign() = s; - return; - } - case cpp_bin_float::exponent_infinity: - if(b == 0) - res = std::numeric_limits > >::quiet_NaN().backend(); - else - res = a; - return; - case cpp_bin_float::exponent_nan: +template +inline typename enable_if_c::value>::type eval_multiply( + cpp_bin_float &res, + const cpp_bin_float &a, + const U &b) { + using default_ops::eval_bit_test; + using default_ops::eval_multiply; + + // Special cases first: + switch (a.exponent()) { + case cpp_bin_float::exponent_zero: { + bool s = a.sign(); + res = a; + res.sign() = s; + return; + } + case cpp_bin_float::exponent_infinity: + if (b == 0) + res = std::numeric_limits>>::quiet_NaN() + .backend(); + else res = a; - return; - } - - typename cpp_bin_float::double_rep_type dt; - typedef typename boost::multiprecision::detail::canonical::double_rep_type>::type canon_ui_type; - eval_multiply(dt, a.bits(), static_cast(b)); - res.exponent() = a.exponent(); - copy_and_round(res, dt); - res.check_invariants(); - res.sign() = a.sign(); + return; + case cpp_bin_float::exponent_nan: + res = a; + return; + } + + typename cpp_bin_float::double_rep_type dt; + typedef typename boost::multiprecision::detail::canonical< + U, typename cpp_bin_float::double_rep_type>::type canon_ui_type; + eval_multiply(dt, a.bits(), static_cast(b)); + res.exponent() = a.exponent(); + copy_and_round(res, dt); + res.check_invariants(); + res.sign() = a.sign(); } -template -inline typename enable_if_c::value>::type eval_multiply(cpp_bin_float &res, const U &b) -{ - eval_multiply(res, res, b); +template +inline typename enable_if_c::value>::type eval_multiply( + cpp_bin_float &res, + const U &b) { + eval_multiply(res, res, b); } -template -inline typename enable_if_c::value>::type eval_multiply(cpp_bin_float &res, const cpp_bin_float &a, const S &b) -{ - typedef typename make_unsigned::type ui_type; - eval_multiply(res, a, static_cast(boost::multiprecision::detail::unsigned_abs(b))); - if(b < 0) - res.negate(); +template +inline typename enable_if_c::value>::type eval_multiply( + cpp_bin_float &res, + const cpp_bin_float &a, + const S &b) { + typedef typename make_unsigned::type ui_type; + eval_multiply( + res, a, + static_cast(boost::multiprecision::detail::unsigned_abs(b))); + if (b < 0) + res.negate(); } -template -inline typename enable_if_c::value>::type eval_multiply(cpp_bin_float &res, const S &b) -{ - eval_multiply(res, res, b); +template +inline typename enable_if_c::value>::type eval_multiply( + cpp_bin_float &res, + const S &b) { + eval_multiply(res, res, b); } -template -inline void eval_divide(cpp_bin_float &res, const cpp_bin_float &u, const cpp_bin_float &v) -{ +template +inline void eval_divide( + cpp_bin_float &res, + const cpp_bin_float &u, + const cpp_bin_float + &v) { #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:6326) // comparison of two constants +#pragma warning(disable : 6326) // comparison of two constants #endif - using default_ops::eval_subtract; - using default_ops::eval_qr; - using default_ops::eval_bit_test; - using default_ops::eval_get_sign; - using default_ops::eval_increment; - - // - // Special cases first: - // - switch(u.exponent()) - { - case cpp_bin_float::exponent_zero: - { - switch(v.exponent()) - { - case cpp_bin_float::exponent_zero: - case cpp_bin_float::exponent_nan: - res = std::numeric_limits > >::quiet_NaN().backend(); - return; - } - bool s = u.sign() != v.sign(); - res = u; - res.sign() = s; + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_increment; + using default_ops::eval_qr; + using default_ops::eval_subtract; + + // + // Special cases first: + // + switch (u.exponent()) { + case cpp_bin_float::exponent_zero: { + switch (v.exponent()) { + case cpp_bin_float::exponent_zero: + case cpp_bin_float::exponent_nan: + res = std::numeric_limits>>::quiet_NaN() + .backend(); return; - } - case cpp_bin_float::exponent_infinity: - { - switch(v.exponent()) - { - case cpp_bin_float::exponent_infinity: - case cpp_bin_float::exponent_nan: - res = std::numeric_limits > >::quiet_NaN().backend(); - return; - } - bool s = u.sign() != v.sign(); - res = u; - res.sign() = s; + } + bool s = u.sign() != v.sign(); + res = u; + res.sign() = s; + return; + } + case cpp_bin_float::exponent_infinity: { + switch (v.exponent()) { + case cpp_bin_float::exponent_infinity: + case cpp_bin_float::exponent_nan: + res = std::numeric_limits>>::quiet_NaN() + .backend(); return; - } - case cpp_bin_float::exponent_nan: - res = std::numeric_limits > >::quiet_NaN().backend(); - return; - } - switch(v.exponent()) - { - case cpp_bin_float::exponent_zero: - { - bool s = u.sign() != v.sign(); - res = std::numeric_limits > >::infinity().backend(); - res.sign() = s; - return; - } - case cpp_bin_float::exponent_infinity: - res.exponent() = cpp_bin_float::exponent_zero; - res.bits() = limb_type(0); + } + bool s = u.sign() != v.sign(); + res = u; + res.sign() = s; + return; + } + case cpp_bin_float::exponent_nan: + res = std::numeric_limits>>::quiet_NaN() + .backend(); + return; + } + switch (v.exponent()) { + case cpp_bin_float::exponent_zero: { + bool s = u.sign() != v.sign(); + res = std::numeric_limits>>::infinity() + .backend(); + res.sign() = s; + return; + } + case cpp_bin_float::exponent_infinity: + res.exponent() = cpp_bin_float::exponent_zero; + res.bits() = limb_type(0); + res.sign() = u.sign() != v.sign(); + return; + case cpp_bin_float::exponent_nan: + res = std::numeric_limits>>::quiet_NaN() + .backend(); + return; + } + + // We can scale u and v so that both are integers, then perform integer + // division to obtain quotient q and remainder r, such that: + // + // q * v + r = u + // + // and hense: + // + // q + r/v = u/v + // + // From this, assuming q has cpp_bin_float::bit_count bits we only need to determine whether r/v + // is less than, equal to, or greater than 0.5 to determine rounding - this we + // can do with a shift and comparison. + // + // We can set the exponent and sign of the result up front: + // + if ((v.exponent() < 0) && (u.exponent() > 0)) { + // Check for overflow: + if (cpp_bin_float::max_exponent + + v.exponent() < + u.exponent() - 1) { + res.exponent() = cpp_bin_float::exponent_infinity; res.sign() = u.sign() != v.sign(); + res.bits() = static_cast(0u); return; - case cpp_bin_float::exponent_nan: - res = std::numeric_limits > >::quiet_NaN().backend(); + } + } else if ((v.exponent() > 0) && (u.exponent() < 0)) { + // Check for underflow: + if (cpp_bin_float::min_exponent + + v.exponent() > + u.exponent()) { + // We will certainly underflow: + res.exponent() = cpp_bin_float::exponent_zero; + res.sign() = u.sign() != v.sign(); + res.bits() = static_cast(0u); return; - } - - // We can scale u and v so that both are integers, then perform integer - // division to obtain quotient q and remainder r, such that: - // - // q * v + r = u - // - // and hense: - // - // q + r/v = u/v - // - // From this, assuming q has cpp_bin_float::bit_count - // bits we only need to determine whether - // r/v is less than, equal to, or greater than 0.5 to determine rounding - - // this we can do with a shift and comparison. - // - // We can set the exponent and sign of the result up front: - // - if((v.exponent() < 0) && (u.exponent() > 0)) - { - // Check for overflow: - if(cpp_bin_float::max_exponent + v.exponent() < u.exponent() - 1) - { - res.exponent() = cpp_bin_float::exponent_infinity; - res.sign() = u.sign() != v.sign(); - res.bits() = static_cast(0u); - return; - } - } - else if((v.exponent() > 0) && (u.exponent() < 0)) - { - // Check for underflow: - if(cpp_bin_float::min_exponent + v.exponent() > u.exponent()) - { - // We will certainly underflow: - res.exponent() = cpp_bin_float::exponent_zero; - res.sign() = u.sign() != v.sign(); - res.bits() = static_cast(0u); - return; - } - } - res.exponent() = u.exponent() - v.exponent() - 1; - res.sign() = u.sign() != v.sign(); - // - // Now get the quotient and remainder: - // - typename cpp_bin_float::double_rep_type t(u.bits()), t2(v.bits()), q, r; - eval_left_shift(t, cpp_bin_float::bit_count); - eval_qr(t, t2, q, r); - // - // We now have either "cpp_bin_float::bit_count" - // or "cpp_bin_float::bit_count+1" significant - // bits in q. - // - static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; - if(eval_bit_test(q, cpp_bin_float::bit_count)) - { - // - // OK we have cpp_bin_float::bit_count+1 bits, - // so we already have rounding info, - // we just need to changes things if the last bit is 1 and either the - // remainder is non-zero (ie we do not have a tie) or the quotient would - // be odd if it were shifted to the correct number of bits (ie a tiebreak). - // - BOOST_ASSERT((eval_msb(q) == cpp_bin_float::bit_count)); - if((q.limbs()[0] & 1u) && (eval_get_sign(r) || (q.limbs()[0] & 2u))) - { - eval_increment(q); - } - } - else - { - // - // We have exactly "cpp_bin_float::bit_count" bits in q. - // Get rounding info, which we can get by comparing 2r with v. - // We want to call copy_and_round to handle rounding and general cleanup, - // so we'll left shift q and add some fake digits on the end to represent - // how we'll be rounding. - // - BOOST_ASSERT((eval_msb(q) == cpp_bin_float::bit_count - 1)); - static const unsigned lshift = (cpp_bin_float::bit_count < limb_bits) ? 2 : limb_bits; - eval_left_shift(q, lshift); - res.exponent() -= lshift; - eval_left_shift(r, 1u); - int c = r.compare(v.bits()); - if(c == 0) - q.limbs()[0] |= static_cast(1u) << (lshift - 1); - else if(c > 0) - q.limbs()[0] |= (static_cast(1u) << (lshift - 1)) + static_cast(1u); - } - copy_and_round(res, q); + } + } + res.exponent() = u.exponent() - v.exponent() - 1; + res.sign() = u.sign() != v.sign(); + // + // Now get the quotient and remainder: + // + typename cpp_bin_float::double_rep_type t(u.bits()), + t2(v.bits()), q, r; + eval_left_shift(t, cpp_bin_float::bit_count); + eval_qr(t, t2, q, r); + // + // We now have either "cpp_bin_float::bit_count" or "cpp_bin_float::bit_count+1" significant bits in q. + // + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + if (eval_bit_test(q, cpp_bin_float::bit_count)) { + // + // OK we have cpp_bin_float::bit_count+1 bits, so we already have rounding info, we just need + // to changes things if the last bit is 1 and either the remainder is + // non-zero (ie we do not have a tie) or the quotient would be odd if it + // were shifted to the correct number of bits (ie a tiebreak). + // + BOOST_ASSERT( + (eval_msb(q) == cpp_bin_float::bit_count)); + if ((q.limbs()[0] & 1u) && (eval_get_sign(r) || (q.limbs()[0] & 2u))) { + eval_increment(q); + } + } else { + // + // We have exactly "cpp_bin_float::bit_count" bits in q. Get rounding info, which we can get by + // comparing 2r with v. We want to call copy_and_round to handle rounding + // and general cleanup, so we'll left shift q and add some fake digits on + // the end to represent how we'll be rounding. + // + BOOST_ASSERT( + (eval_msb(q) == cpp_bin_float::bit_count - + 1)); + static const unsigned lshift = + (cpp_bin_float::bit_count < limb_bits) + ? 2 + : limb_bits; + eval_left_shift(q, lshift); + res.exponent() -= lshift; + eval_left_shift(r, 1u); + int c = r.compare(v.bits()); + if (c == 0) + q.limbs()[0] |= static_cast(1u) << (lshift - 1); + else if (c > 0) + q.limbs()[0] |= (static_cast(1u) << (lshift - 1)) + + static_cast(1u); + } + copy_and_round(res, q); #ifdef BOOST_MSVC #pragma warning(pop) #endif } -template -inline void eval_divide(cpp_bin_float &res, const cpp_bin_float &arg) -{ - eval_divide(res, res, arg); +template +inline void eval_divide( + cpp_bin_float &res, + const cpp_bin_float + &arg) { + eval_divide(res, res, arg); } -template -inline typename enable_if_c::value>::type eval_divide(cpp_bin_float &res, const cpp_bin_float &u, const U &v) -{ +template +inline typename enable_if_c::value>::type eval_divide( + cpp_bin_float &res, + const cpp_bin_float &u, + const U &v) { #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:6326) // comparison of two constants +#pragma warning(disable : 6326) // comparison of two constants #endif - using default_ops::eval_subtract; - using default_ops::eval_qr; - using default_ops::eval_bit_test; - using default_ops::eval_get_sign; - using default_ops::eval_increment; - - // - // Special cases first: - // - switch(u.exponent()) - { - case cpp_bin_float::exponent_zero: - { - if(v == 0) - { - res = std::numeric_limits > >::quiet_NaN().backend(); - return; - } - bool s = u.sign() != (v < 0); - res = u; - res.sign() = s; + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_increment; + using default_ops::eval_qr; + using default_ops::eval_subtract; + + // + // Special cases first: + // + switch (u.exponent()) { + case cpp_bin_float::exponent_zero: { + if (v == 0) { + res = std::numeric_limits>>::quiet_NaN() + .backend(); return; - } - case cpp_bin_float::exponent_infinity: - res = u; - return; - case cpp_bin_float::exponent_nan: - res = std::numeric_limits > >::quiet_NaN().backend(); - return; - } - if(v == 0) - { - bool s = u.sign(); - res = std::numeric_limits > >::infinity().backend(); - res.sign() = s; - return; - } - - // We can scale u and v so that both are integers, then perform integer - // division to obtain quotient q and remainder r, such that: - // - // q * v + r = u - // - // and hense: - // - // q + r/v = u/v - // - // From this, assuming q has "cpp_bin_float::bit_count" cpp_bin_float::bit_count, we only need to determine whether - // r/v is less than, equal to, or greater than 0.5 to determine rounding - - // this we can do with a shift and comparison. - // - // We can set the exponent and sign of the result up front: - // - int gb = msb(v); - res.exponent() = u.exponent() - static_cast(gb) - static_cast(1); - res.sign() = u.sign(); - // - // Now get the quotient and remainder: - // - typename cpp_bin_float::double_rep_type t(u.bits()), q, r; - eval_left_shift(t, gb + 1); - eval_qr(t, number::double_rep_type>::canonical_value(v), q, r); - // - // We now have either "cpp_bin_float::bit_count" or "cpp_bin_float::bit_count+1" significant cpp_bin_float::bit_count in q. - // - static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; - if(eval_bit_test(q, cpp_bin_float::bit_count)) - { - // - // OK we have cpp_bin_float::bit_count+1 cpp_bin_float::bit_count, so we already have rounding info, - // we just need to changes things if the last bit is 1 and the - // remainder is non-zero (ie we do not have a tie). - // - BOOST_ASSERT((eval_msb(q) == cpp_bin_float::bit_count)); - if((q.limbs()[0] & 1u) && eval_get_sign(r)) - { - eval_increment(q); - } - } - else - { - // - // We have exactly "cpp_bin_float::bit_count" cpp_bin_float::bit_count in q. - // Get rounding info, which we can get by comparing 2r with v. - // We want to call copy_and_round to handle rounding and general cleanup, - // so we'll left shift q and add some fake cpp_bin_float::bit_count on the end to represent - // how we'll be rounding. - // - BOOST_ASSERT((eval_msb(q) == cpp_bin_float::bit_count - 1)); - static const unsigned lshift = cpp_bin_float::bit_count < limb_bits ? 2 : limb_bits; - eval_left_shift(q, lshift); - res.exponent() -= lshift; - eval_left_shift(r, 1u); - int c = r.compare(number::double_rep_type>::canonical_value(v)); - if(c == 0) - q.limbs()[0] |= static_cast(1u) << (lshift - 1); - else if(c > 0) - q.limbs()[0] |= (static_cast(1u) << (lshift - 1)) + static_cast(1u); - } - copy_and_round(res, q); + } + bool s = u.sign() != (v < 0); + res = u; + res.sign() = s; + return; + } + case cpp_bin_float::exponent_infinity: + res = u; + return; + case cpp_bin_float::exponent_nan: + res = std::numeric_limits>>::quiet_NaN() + .backend(); + return; + } + if (v == 0) { + bool s = u.sign(); + res = std::numeric_limits>>::infinity() + .backend(); + res.sign() = s; + return; + } + + // We can scale u and v so that both are integers, then perform integer + // division to obtain quotient q and remainder r, such that: + // + // q * v + r = u + // + // and hense: + // + // q + r/v = u/v + // + // From this, assuming q has "cpp_bin_float::bit_count" cpp_bin_float::bit_count, we only need to determine + // whether r/v is less than, equal to, or greater than 0.5 to determine + // rounding - this we can do with a shift and comparison. + // + // We can set the exponent and sign of the result up front: + // + int gb = msb(v); + res.exponent() = + u.exponent() - static_cast(gb) - static_cast(1); + res.sign() = u.sign(); + // + // Now get the quotient and remainder: + // + typename cpp_bin_float::double_rep_type t(u.bits()), + q, r; + eval_left_shift(t, gb + 1); + eval_qr( + t, + number< + typename cpp_bin_float::double_rep_type>::canonical_value(v), + q, r); + // + // We now have either "cpp_bin_float::bit_count" or "cpp_bin_float::bit_count+1" significant cpp_bin_float::bit_count in q. + // + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + if (eval_bit_test(q, cpp_bin_float::bit_count)) { + // + // OK we have cpp_bin_float::bit_count+1 cpp_bin_float::bit_count, so we already have rounding info, we just need to + // changes things if the last bit is 1 and the remainder is non-zero (ie we + // do not have a tie). + // + BOOST_ASSERT( + (eval_msb(q) == cpp_bin_float::bit_count)); + if ((q.limbs()[0] & 1u) && eval_get_sign(r)) { + eval_increment(q); + } + } else { + // + // We have exactly "cpp_bin_float::bit_count" cpp_bin_float::bit_count in q. Get rounding info, which we can + // get by comparing 2r with v. We want to call copy_and_round to handle + // rounding and general cleanup, so we'll left shift q and add some fake + // cpp_bin_float::bit_count on the end to represent how we'll be rounding. + // + BOOST_ASSERT( + (eval_msb(q) == cpp_bin_float::bit_count - + 1)); + static const unsigned lshift = + cpp_bin_float::bit_count < limb_bits + ? 2 + : limb_bits; + eval_left_shift(q, lshift); + res.exponent() -= lshift; + eval_left_shift(r, 1u); + int c = r.compare( + number< + typename cpp_bin_float::double_rep_type>::canonical_value(v)); + if (c == 0) + q.limbs()[0] |= static_cast(1u) << (lshift - 1); + else if (c > 0) + q.limbs()[0] |= (static_cast(1u) << (lshift - 1)) + + static_cast(1u); + } + copy_and_round(res, q); #ifdef BOOST_MSVC #pragma warning(pop) #endif } -template -inline typename enable_if_c::value>::type eval_divide(cpp_bin_float &res, const U &v) -{ - eval_divide(res, res, v); +template +inline typename enable_if_c::value>::type eval_divide( + cpp_bin_float &res, + const U &v) { + eval_divide(res, res, v); } -template -inline typename enable_if_c::value>::type eval_divide(cpp_bin_float &res, const cpp_bin_float &u, const S &v) -{ - typedef typename make_unsigned::type ui_type; - eval_divide(res, u, static_cast(boost::multiprecision::detail::unsigned_abs(v))); - if(v < 0) - res.negate(); +template +inline typename enable_if_c::value>::type eval_divide( + cpp_bin_float &res, + const cpp_bin_float &u, + const S &v) { + typedef typename make_unsigned::type ui_type; + eval_divide( + res, u, + static_cast(boost::multiprecision::detail::unsigned_abs(v))); + if (v < 0) + res.negate(); } -template -inline typename enable_if_c::value>::type eval_divide(cpp_bin_float &res, const S &v) -{ - eval_divide(res, res, v); +template +inline typename enable_if_c::value>::type eval_divide( + cpp_bin_float &res, + const S &v) { + eval_divide(res, res, v); } -template -inline int eval_get_sign(const cpp_bin_float &arg) -{ - return arg.exponent() == cpp_bin_float::exponent_zero ? 0 : arg.sign() ? -1 : 1; +template +inline int eval_get_sign(const cpp_bin_float &arg) { + return arg.exponent() == cpp_bin_float::exponent_zero + ? 0 + : arg.sign() ? -1 : 1; } -template -inline bool eval_is_zero(const cpp_bin_float &arg) -{ - return arg.exponent() == cpp_bin_float::exponent_zero; +template +inline bool eval_is_zero(const cpp_bin_float &arg) { + return arg.exponent() == cpp_bin_float::exponent_zero; } -template -inline bool eval_eq(const cpp_bin_float &a, cpp_bin_float &b) -{ - if(a.exponent() == b.exponent()) - { - if(a.exponent() == cpp_bin_float::exponent_zero) - return true; - return (a.sign() == b.sign()) - && (a.bits().compare(b.bits()) == 0) - && (a.exponent() != cpp_bin_float::exponent_nan); - } - return false; +template +inline bool eval_eq( + const cpp_bin_float &a, + cpp_bin_float &b) { + if (a.exponent() == b.exponent()) { + if (a.exponent() == cpp_bin_float::exponent_zero) + return true; + return (a.sign() == b.sign()) && (a.bits().compare(b.bits()) == 0) && + (a.exponent() != cpp_bin_float::exponent_nan); + } + return false; } -template -inline void eval_convert_to(boost::long_long_type *res, const cpp_bin_float &arg) -{ - switch(arg.exponent()) - { - case cpp_bin_float::exponent_zero: - *res = 0; - return; - case cpp_bin_float::exponent_nan: - BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer.")); - case cpp_bin_float::exponent_infinity: - *res = (std::numeric_limits::max)(); - if(arg.sign()) - *res = -*res; - return; - } - typedef typename mpl::if_c < sizeof(typename cpp_bin_float::exponent_type) < sizeof(int), int, typename cpp_bin_float::exponent_type > ::type shift_type; - typename cpp_bin_float::rep_type man(arg.bits()); - shift_type shift - = (shift_type)cpp_bin_float::bit_count - 1 - arg.exponent(); - if(shift > (shift_type)cpp_bin_float::bit_count - 1) - { - *res = 0; - return; - } - if(arg.sign() && (arg.compare((std::numeric_limits::min)()) <= 0)) - { - *res = (std::numeric_limits::min)(); - return; - } - else if(!arg.sign() && (arg.compare((std::numeric_limits::max)()) >= 0)) - { +template +inline void eval_convert_to(boost::long_long_type *res, + const cpp_bin_float &arg) { + switch (arg.exponent()) { + case cpp_bin_float::exponent_zero: + *res = 0; + return; + case cpp_bin_float::exponent_nan: + BOOST_THROW_EXCEPTION( + std::runtime_error("Could not convert NaN to integer.")); + case cpp_bin_float::exponent_infinity: + *res = (std::numeric_limits::max)(); + if (arg.sign()) + *res = -*res; + return; + } + typedef typename mpl::if_c< + sizeof(typename cpp_bin_float::exponent_type) < sizeof(int), + int, + typename cpp_bin_float::exponent_type>::type shift_type; + typename cpp_bin_float::rep_type man(arg.bits()); + shift_type shift = + (shift_type)cpp_bin_float::bit_count - + 1 - arg.exponent(); + if (shift > (shift_type)cpp_bin_float::bit_count - + 1) { + *res = 0; + return; + } + if (arg.sign() && + (arg.compare((std::numeric_limits::min)()) <= 0)) { + *res = (std::numeric_limits::min)(); + return; + } else if (!arg.sign() && + (arg.compare( + (std::numeric_limits::max)()) >= 0)) { + *res = (std::numeric_limits::max)(); + return; + } + + if (shift < 0) { + if (cpp_bin_float::bit_count - + shift <= + std::numeric_limits::digits) { + // We have more bits in long_long_type than the float, so it's OK to left + // shift: + eval_convert_to(res, man); + *res <<= -shift; + } else { *res = (std::numeric_limits::max)(); return; - } - - if (shift < 0) - { - if (cpp_bin_float::bit_count - shift <= std::numeric_limits::digits) - { - // We have more bits in long_long_type than the float, so it's OK to left shift: - eval_convert_to(res, man); - *res <<= -shift; - } - else - { - *res = (std::numeric_limits::max)(); - return; - } - } - else - { - eval_right_shift(man, shift); - eval_convert_to(res, man); - } - if(arg.sign()) - { - *res = -*res; - } + } + } else { + eval_right_shift(man, shift); + eval_convert_to(res, man); + } + if (arg.sign()) { + *res = -*res; + } } -template -inline void eval_convert_to(boost::ulong_long_type *res, const cpp_bin_float &arg) -{ - switch(arg.exponent()) - { - case cpp_bin_float::exponent_zero: - *res = 0; - return; - case cpp_bin_float::exponent_nan: - BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer.")); - case cpp_bin_float::exponent_infinity: - *res = (std::numeric_limits::max)(); - return; - } - typename cpp_bin_float::rep_type man(arg.bits()); - typedef typename mpl::if_c < sizeof(typename cpp_bin_float::exponent_type) < sizeof(int), int, typename cpp_bin_float::exponent_type > ::type shift_type; - shift_type shift - = (shift_type)cpp_bin_float::bit_count - 1 - arg.exponent(); - if(shift > (shift_type)cpp_bin_float::bit_count - 1) - { - *res = 0; - return; - } - else if(shift < 0) - { - if (cpp_bin_float::bit_count - shift <= std::numeric_limits::digits) - { - // We have more bits in ulong_long_type than the float, so it's OK to left shift: - eval_convert_to(res, man); - *res <<= -shift; - return; - } - *res = (std::numeric_limits::max)(); +template +inline void eval_convert_to(boost::ulong_long_type *res, + const cpp_bin_float &arg) { + switch (arg.exponent()) { + case cpp_bin_float::exponent_zero: + *res = 0; + return; + case cpp_bin_float::exponent_nan: + BOOST_THROW_EXCEPTION( + std::runtime_error("Could not convert NaN to integer.")); + case cpp_bin_float::exponent_infinity: + *res = (std::numeric_limits::max)(); + return; + } + typename cpp_bin_float::rep_type man(arg.bits()); + typedef typename mpl::if_c< + sizeof(typename cpp_bin_float::exponent_type) < sizeof(int), + int, + typename cpp_bin_float::exponent_type>::type shift_type; + shift_type shift = + (shift_type)cpp_bin_float::bit_count - + 1 - arg.exponent(); + if (shift > (shift_type)cpp_bin_float::bit_count - + 1) { + *res = 0; + return; + } else if (shift < 0) { + if (cpp_bin_float::bit_count - + shift <= + std::numeric_limits::digits) { + // We have more bits in ulong_long_type than the float, so it's OK to left + // shift: + eval_convert_to(res, man); + *res <<= -shift; return; - } - eval_right_shift(man, shift); - eval_convert_to(res, man); + } + *res = (std::numeric_limits::max)(); + return; + } + eval_right_shift(man, shift); + eval_convert_to(res, man); } -template -inline typename boost::enable_if_c::value>::type eval_convert_to(Float *res, const cpp_bin_float &original_arg) -{ - typedef cpp_bin_float::digits, digit_base_2, void, Exponent, MinE, MaxE> conv_type; - typedef typename common_type::type common_exp_type; - // - // Special cases first: - // - switch(original_arg.exponent()) - { - case cpp_bin_float::exponent_zero: - *res = 0; - if(original_arg.sign()) - *res = -*res; - return; - case cpp_bin_float::exponent_nan: - *res = std::numeric_limits::quiet_NaN(); - return; - case cpp_bin_float::exponent_infinity: - *res = (std::numeric_limits::infinity)(); - if(original_arg.sign()) - *res = -*res; - return; - } - // - // Check for super large exponent that must be converted to infinity: - // - if(original_arg.exponent() > std::numeric_limits::max_exponent) - { - *res = std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : (std::numeric_limits::max)(); - if(original_arg.sign()) - *res = -*res; - return; - } - // - // Figure out how many digits we will have in our result, - // allowing for a possibly denormalized result: - // - common_exp_type digits_to_round_to = std::numeric_limits::digits; - if(original_arg.exponent() < std::numeric_limits::min_exponent - 1) - { - common_exp_type diff = original_arg.exponent(); - diff -= std::numeric_limits::min_exponent - 1; - digits_to_round_to += diff; - } - if(digits_to_round_to < 0) - { - // Result must be zero: - *res = 0; - if(original_arg.sign()) - *res = -*res; - return; - } - // - // Perform rounding first, then afterwards extract the digits: - // - cpp_bin_float::digits, digit_base_2, Allocator, Exponent, MinE, MaxE> arg; - typename cpp_bin_float::rep_type bits(original_arg.bits()); - arg.exponent() = original_arg.exponent(); - copy_and_round(arg, bits, (int)digits_to_round_to); - common_exp_type e = arg.exponent(); - e -= cpp_bin_float::bit_count - 1; - static const unsigned limbs_needed = std::numeric_limits::digits / (sizeof(*arg.bits().limbs()) * CHAR_BIT) - + (std::numeric_limits::digits % (sizeof(*arg.bits().limbs()) * CHAR_BIT) ? 1 : 0); - unsigned first_limb_needed = arg.bits().size() - limbs_needed; - *res = 0; - e += first_limb_needed * sizeof(*arg.bits().limbs()) * CHAR_BIT; - while(first_limb_needed < arg.bits().size()) - { - *res += std::ldexp(static_cast(arg.bits().limbs()[first_limb_needed]), static_cast(e)); - ++first_limb_needed; - e += sizeof(*arg.bits().limbs()) * CHAR_BIT; - } - if(original_arg.sign()) +template +inline typename boost::enable_if_c::value>::type +eval_convert_to(Float *res, + const cpp_bin_float &original_arg) { + typedef cpp_bin_float::digits, digit_base_2, void, + Exponent, MinE, MaxE> + conv_type; + typedef typename common_type::type + common_exp_type; + // + // Special cases first: + // + switch (original_arg.exponent()) { + case cpp_bin_float::exponent_zero: + *res = 0; + if (original_arg.sign()) + *res = -*res; + return; + case cpp_bin_float::exponent_nan: + *res = std::numeric_limits::quiet_NaN(); + return; + case cpp_bin_float::exponent_infinity: + *res = (std::numeric_limits::infinity)(); + if (original_arg.sign()) + *res = -*res; + return; + } + // + // Check for super large exponent that must be converted to infinity: + // + if (original_arg.exponent() > std::numeric_limits::max_exponent) { + *res = std::numeric_limits::has_infinity + ? std::numeric_limits::infinity() + : (std::numeric_limits::max)(); + if (original_arg.sign()) + *res = -*res; + return; + } + // + // Figure out how many digits we will have in our result, + // allowing for a possibly denormalized result: + // + common_exp_type digits_to_round_to = std::numeric_limits::digits; + if (original_arg.exponent() < std::numeric_limits::min_exponent - 1) { + common_exp_type diff = original_arg.exponent(); + diff -= std::numeric_limits::min_exponent - 1; + digits_to_round_to += diff; + } + if (digits_to_round_to < 0) { + // Result must be zero: + *res = 0; + if (original_arg.sign()) *res = -*res; + return; + } + // + // Perform rounding first, then afterwards extract the digits: + // + cpp_bin_float::digits, digit_base_2, Allocator, + Exponent, MinE, MaxE> + arg; + typename cpp_bin_float::rep_type bits(original_arg.bits()); + arg.exponent() = original_arg.exponent(); + copy_and_round(arg, bits, (int)digits_to_round_to); + common_exp_type e = arg.exponent(); + e -= cpp_bin_float::bit_count - + 1; + static const unsigned limbs_needed = + std::numeric_limits::digits / + (sizeof(*arg.bits().limbs()) * CHAR_BIT) + + (std::numeric_limits::digits % + (sizeof(*arg.bits().limbs()) * CHAR_BIT) + ? 1 + : 0); + unsigned first_limb_needed = arg.bits().size() - limbs_needed; + *res = 0; + e += first_limb_needed * sizeof(*arg.bits().limbs()) * CHAR_BIT; + while (first_limb_needed < arg.bits().size()) { + *res += + std::ldexp(static_cast(arg.bits().limbs()[first_limb_needed]), + static_cast(e)); + ++first_limb_needed; + e += sizeof(*arg.bits().limbs()) * CHAR_BIT; + } + if (original_arg.sign()) + *res = -*res; } -template -inline void eval_frexp(cpp_bin_float &res, const cpp_bin_float &arg, Exponent *e) -{ - switch(arg.exponent()) - { - case cpp_bin_float::exponent_zero: - case cpp_bin_float::exponent_nan: - case cpp_bin_float::exponent_infinity: - *e = 0; - res = arg; - return; - } - res = arg; - *e = arg.exponent() + 1; - res.exponent() = -1; +template +inline void eval_frexp( + cpp_bin_float &res, + const cpp_bin_float + &arg, + Exponent *e) { + switch (arg.exponent()) { + case cpp_bin_float::exponent_zero: + case cpp_bin_float::exponent_nan: + case cpp_bin_float::exponent_infinity: + *e = 0; + res = arg; + return; + } + res = arg; + *e = arg.exponent() + 1; + res.exponent() = -1; } -template -inline void eval_frexp(cpp_bin_float &res, const cpp_bin_float &arg, I *pe) -{ - Exponent e; - eval_frexp(res, arg, &e); - if((e > (std::numeric_limits::max)()) || (e < (std::numeric_limits::min)())) - { - BOOST_THROW_EXCEPTION(std::runtime_error("Exponent was outside of the range of the argument type to frexp.")); - } - *pe = static_cast(e); +template +inline void eval_frexp( + cpp_bin_float &res, + const cpp_bin_float + &arg, + I *pe) { + Exponent e; + eval_frexp(res, arg, &e); + if ((e > (std::numeric_limits::max)()) || + (e < (std::numeric_limits::min)())) { + BOOST_THROW_EXCEPTION(std::runtime_error( + "Exponent was outside of the range of the argument type to frexp.")); + } + *pe = static_cast(e); } -template -inline void eval_ldexp(cpp_bin_float &res, const cpp_bin_float &arg, Exponent e) -{ - switch(arg.exponent()) - { - case cpp_bin_float::exponent_zero: - case cpp_bin_float::exponent_nan: - case cpp_bin_float::exponent_infinity: - res = arg; - return; - } - if((e > 0) && (cpp_bin_float::max_exponent - e < arg.exponent())) - { - // Overflow: - res = std::numeric_limits > >::infinity().backend(); - res.sign() = arg.sign(); - } - else if((e < 0) && (cpp_bin_float::min_exponent - e > arg.exponent())) - { - // Underflow: - res = limb_type(0); - } - else - { - res = arg; - res.exponent() += e; - } +template +inline void eval_ldexp( + cpp_bin_float &res, + const cpp_bin_float + &arg, + Exponent e) { + switch (arg.exponent()) { + case cpp_bin_float::exponent_zero: + case cpp_bin_float::exponent_nan: + case cpp_bin_float::exponent_infinity: + res = arg; + return; + } + if ((e > 0) && (cpp_bin_float::max_exponent - + e < + arg.exponent())) { + // Overflow: + res = std::numeric_limits>>::infinity() + .backend(); + res.sign() = arg.sign(); + } else if ((e < 0) && (cpp_bin_float::min_exponent - + e > + arg.exponent())) { + // Underflow: + res = limb_type(0); + } else { + res = arg; + res.exponent() += e; + } } -template -inline typename enable_if_c::value>::type eval_ldexp(cpp_bin_float &res, const cpp_bin_float &arg, I e) -{ - typedef typename make_signed::type si_type; - if(e > static_cast((std::numeric_limits::max)())) - res = std::numeric_limits > >::infinity().backend(); - else - eval_ldexp(res, arg, static_cast(e)); +template +inline typename enable_if_c::value>::type eval_ldexp( + cpp_bin_float &res, + const cpp_bin_float + &arg, + I e) { + typedef typename make_signed::type si_type; + if (e > static_cast((std::numeric_limits::max)())) + res = std::numeric_limits>>::infinity() + .backend(); + else + eval_ldexp(res, arg, static_cast(e)); } -template -inline typename enable_if_c::value>::type eval_ldexp(cpp_bin_float &res, const cpp_bin_float &arg, I e) -{ - if((e > (std::numeric_limits::max)()) || (e < (std::numeric_limits::min)())) - { - res = std::numeric_limits > >::infinity().backend(); - if(e < 0) - res.negate(); - } - else - eval_ldexp(res, arg, static_cast(e)); +template +inline typename enable_if_c::value>::type eval_ldexp( + cpp_bin_float &res, + const cpp_bin_float + &arg, + I e) { + if ((e > (std::numeric_limits::max)()) || + (e < (std::numeric_limits::min)())) { + res = std::numeric_limits>>::infinity() + .backend(); + if (e < 0) + res.negate(); + } else + eval_ldexp(res, arg, static_cast(e)); } /* -* Sign manipulation -*/ - -template -inline void eval_abs(cpp_bin_float &res, const cpp_bin_float &arg) -{ - res = arg; - res.sign() = false; + * Sign manipulation + */ + +template +inline void +eval_abs(cpp_bin_float &res, + const cpp_bin_float + &arg) { + res = arg; + res.sign() = false; } -template -inline void eval_fabs(cpp_bin_float &res, const cpp_bin_float &arg) -{ - res = arg; - res.sign() = false; +template +inline void eval_fabs( + cpp_bin_float &res, + const cpp_bin_float + &arg) { + res = arg; + res.sign() = false; } -template -inline int eval_fpclassify(const cpp_bin_float &arg) -{ - switch(arg.exponent()) - { - case cpp_bin_float::exponent_zero: - return FP_ZERO; - case cpp_bin_float::exponent_infinity: - return FP_INFINITE; - case cpp_bin_float::exponent_nan: - return FP_NAN; - } - return FP_NORMAL; +template +inline int eval_fpclassify(const cpp_bin_float &arg) { + switch (arg.exponent()) { + case cpp_bin_float::exponent_zero: + return FP_ZERO; + case cpp_bin_float::exponent_infinity: + return FP_INFINITE; + case cpp_bin_float::exponent_nan: + return FP_NAN; + } + return FP_NORMAL; } -template -inline void eval_sqrt(cpp_bin_float &res, const cpp_bin_float &arg) -{ - using default_ops::eval_integer_sqrt; - using default_ops::eval_bit_test; - using default_ops::eval_increment; - switch(arg.exponent()) - { - case cpp_bin_float::exponent_nan: +template +inline void eval_sqrt( + cpp_bin_float &res, + const cpp_bin_float + &arg) { + using default_ops::eval_bit_test; + using default_ops::eval_increment; + using default_ops::eval_integer_sqrt; + switch (arg.exponent()) { + case cpp_bin_float::exponent_nan: + errno = EDOM; + // fallthrough... + case cpp_bin_float::exponent_zero: + res = arg; + return; + case cpp_bin_float::exponent_infinity: + if (arg.sign()) { + res = std::numeric_limits>>::quiet_NaN() + .backend(); errno = EDOM; - // fallthrough... - case cpp_bin_float::exponent_zero: + } else res = arg; - return; - case cpp_bin_float::exponent_infinity: - if(arg.sign()) - { - res = std::numeric_limits > >::quiet_NaN().backend(); - errno = EDOM; - } - else - res = arg; - return; - } - if(arg.sign()) - { - res = std::numeric_limits > >::quiet_NaN().backend(); - errno = EDOM; - return; - } - - typename cpp_bin_float::double_rep_type t(arg.bits()), r, s; - eval_left_shift(t, arg.exponent() & 1 ? cpp_bin_float::bit_count : cpp_bin_float::bit_count - 1); - eval_integer_sqrt(s, r, t); - - if(!eval_bit_test(s, cpp_bin_float::bit_count)) - { - // We have exactly the right number of cpp_bin_float::bit_count in the result, round as required: - if(s.compare(r) < 0) - { - eval_increment(s); - } - } - typename cpp_bin_float::exponent_type ae = arg.exponent(); - res.exponent() = ae / 2; - if((ae & 1) && (ae < 0)) - --res.exponent(); - copy_and_round(res, s); + return; + } + if (arg.sign()) { + res = std::numeric_limits>>::quiet_NaN() + .backend(); + errno = EDOM; + return; + } + + typename cpp_bin_float::double_rep_type t(arg.bits()), + r, s; + eval_left_shift(t, arg.exponent() & 1 + ? cpp_bin_float::bit_count + : cpp_bin_float::bit_count - + 1); + eval_integer_sqrt(s, r, t); + + if (!eval_bit_test(s, cpp_bin_float::bit_count)) { + // We have exactly the right number of cpp_bin_float::bit_count in the result, round as + // required: + if (s.compare(r) < 0) { + eval_increment(s); + } + } + typename cpp_bin_float::exponent_type ae = arg.exponent(); + res.exponent() = ae / 2; + if ((ae & 1) && (ae < 0)) + --res.exponent(); + copy_and_round(res, s); } -template -inline void eval_floor(cpp_bin_float &res, const cpp_bin_float &arg) -{ - using default_ops::eval_increment; - switch(arg.exponent()) - { - case cpp_bin_float::exponent_nan: - errno = EDOM; - // fallthrough... - case cpp_bin_float::exponent_zero: - case cpp_bin_float::exponent_infinity: - res = arg; - return; - } - typedef typename mpl::if_c < sizeof(typename cpp_bin_float::exponent_type) < sizeof(int), int, typename cpp_bin_float::exponent_type > ::type shift_type; - shift_type shift = - (shift_type)cpp_bin_float::bit_count - arg.exponent() - 1; - if((arg.exponent() > (shift_type)cpp_bin_float::max_exponent) || (shift <= 0)) - { - // Either arg is already an integer, or a special value: - res = arg; - return; - } - if(shift >= (shift_type)cpp_bin_float::bit_count) - { - res = static_cast(arg.sign() ? -1 : 0); - return; - } - bool fractional = (shift_type)eval_lsb(arg.bits()) < shift; - res = arg; - eval_right_shift(res.bits(), shift); - if(fractional && res.sign()) - { - eval_increment(res.bits()); - if(eval_msb(res.bits()) != cpp_bin_float::bit_count - 1 - shift) - { - // Must have extended result by one bit in the increment: - --shift; - ++res.exponent(); - } - } - eval_left_shift(res.bits(), shift); +template +inline void eval_floor( + cpp_bin_float &res, + const cpp_bin_float + &arg) { + using default_ops::eval_increment; + switch (arg.exponent()) { + case cpp_bin_float::exponent_nan: + errno = EDOM; + // fallthrough... + case cpp_bin_float::exponent_zero: + case cpp_bin_float::exponent_infinity: + res = arg; + return; + } + typedef typename mpl::if_c< + sizeof(typename cpp_bin_float::exponent_type) < sizeof(int), + int, + typename cpp_bin_float::exponent_type>::type shift_type; + shift_type shift = + (shift_type)cpp_bin_float::bit_count - + arg.exponent() - 1; + if ((arg.exponent() > + (shift_type)cpp_bin_float::max_exponent) || + (shift <= 0)) { + // Either arg is already an integer, or a special value: + res = arg; + return; + } + if (shift >= (shift_type)cpp_bin_float::bit_count) { + res = static_cast(arg.sign() ? -1 : 0); + return; + } + bool fractional = (shift_type)eval_lsb(arg.bits()) < shift; + res = arg; + eval_right_shift(res.bits(), shift); + if (fractional && res.sign()) { + eval_increment(res.bits()); + if (eval_msb(res.bits()) != cpp_bin_float::bit_count - + 1 - shift) { + // Must have extended result by one bit in the increment: + --shift; + ++res.exponent(); + } + } + eval_left_shift(res.bits(), shift); } -template -inline void eval_ceil(cpp_bin_float &res, const cpp_bin_float &arg) -{ - using default_ops::eval_increment; - switch(arg.exponent()) - { - case cpp_bin_float::exponent_infinity: - errno = EDOM; - // fallthrough... - case cpp_bin_float::exponent_zero: - case cpp_bin_float::exponent_nan: - res = arg; - return; - } - typedef typename mpl::if_c < sizeof(typename cpp_bin_float::exponent_type) < sizeof(int), int, typename cpp_bin_float::exponent_type > ::type shift_type; - shift_type shift = (shift_type)cpp_bin_float::bit_count - arg.exponent() - 1; - if((arg.exponent() > (shift_type)cpp_bin_float::max_exponent) || (shift <= 0)) - { - // Either arg is already an integer, or a special value: - res = arg; - return; - } - if(shift >= (shift_type)cpp_bin_float::bit_count) - { - bool s = arg.sign(); // takes care of signed zeros - res = static_cast(arg.sign() ? 0 : 1); - res.sign() = s; - return; - } - bool fractional = (shift_type)eval_lsb(arg.bits()) < shift; - res = arg; - eval_right_shift(res.bits(), shift); - if(fractional && !res.sign()) - { - eval_increment(res.bits()); - if(eval_msb(res.bits()) != cpp_bin_float::bit_count - 1 - shift) - { - // Must have extended result by one bit in the increment: - --shift; - ++res.exponent(); - } - } - eval_left_shift(res.bits(), shift); +template +inline void eval_ceil( + cpp_bin_float &res, + const cpp_bin_float + &arg) { + using default_ops::eval_increment; + switch (arg.exponent()) { + case cpp_bin_float::exponent_infinity: + errno = EDOM; + // fallthrough... + case cpp_bin_float::exponent_zero: + case cpp_bin_float::exponent_nan: + res = arg; + return; + } + typedef typename mpl::if_c< + sizeof(typename cpp_bin_float::exponent_type) < sizeof(int), + int, + typename cpp_bin_float::exponent_type>::type shift_type; + shift_type shift = + (shift_type)cpp_bin_float::bit_count - + arg.exponent() - 1; + if ((arg.exponent() > + (shift_type)cpp_bin_float::max_exponent) || + (shift <= 0)) { + // Either arg is already an integer, or a special value: + res = arg; + return; + } + if (shift >= (shift_type)cpp_bin_float::bit_count) { + bool s = arg.sign(); // takes care of signed zeros + res = static_cast(arg.sign() ? 0 : 1); + res.sign() = s; + return; + } + bool fractional = (shift_type)eval_lsb(arg.bits()) < shift; + res = arg; + eval_right_shift(res.bits(), shift); + if (fractional && !res.sign()) { + eval_increment(res.bits()); + if (eval_msb(res.bits()) != cpp_bin_float::bit_count - + 1 - shift) { + // Must have extended result by one bit in the increment: + --shift; + ++res.exponent(); + } + } + eval_left_shift(res.bits(), shift); } -template -int eval_signbit(const cpp_bin_float& val) -{ - return val.sign(); +template +int eval_signbit(const cpp_bin_float &val) { + return val.sign(); } -template -inline std::size_t hash_value(const cpp_bin_float& val) -{ - std::size_t result = hash_value(val.bits()); - boost::hash_combine(result, val.exponent()); - boost::hash_combine(result, val.sign()); - return result; +template +inline std::size_t +hash_value(const cpp_bin_float &val) { + std::size_t result = hash_value(val.bits()); + boost::hash_combine(result, val.exponent()); + boost::hash_combine(result, val.sign()); + return result; } - } // namespace backends #ifdef BOOST_NO_SFINAE_EXPR -namespace detail{ - -template -struct is_explicitly_convertible, backends::cpp_bin_float > : public mpl::true_ {}; -template -struct is_explicitly_convertible > : public boost::is_floating_point {}; - -} +namespace detail { + +template +struct is_explicitly_convertible< + backends::cpp_bin_float, + backends::cpp_bin_float> : public mpl::true_ {}; +template +struct is_explicitly_convertible< + FloatT, backends::cpp_bin_float> + : public boost::is_floating_point {}; + +} // namespace detail #endif -template -inline boost::multiprecision::number, ExpressionTemplates> -copysign BOOST_PREVENT_MACRO_SUBSTITUTION( - const boost::multiprecision::number, ExpressionTemplates>& a, - const boost::multiprecision::number, ExpressionTemplates>& b) -{ - boost::multiprecision::number, ExpressionTemplates> res(a); - res.backend().sign() = b.backend().sign(); - return res; +template +inline boost::multiprecision::number< + boost::multiprecision::backends::cpp_bin_float, + ExpressionTemplates> + copysign BOOST_PREVENT_MACRO_SUBSTITUTION( + const boost::multiprecision::number< + boost::multiprecision::backends::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, + ExpressionTemplates> &a, + const boost::multiprecision::number< + boost::multiprecision::backends::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, + ExpressionTemplates> &b) { + boost::multiprecision::number< + boost::multiprecision::backends::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, + ExpressionTemplates> + res(a); + res.backend().sign() = b.backend().sign(); + return res; } using backends::cpp_bin_float; -using backends::digit_base_2; using backends::digit_base_10; +using backends::digit_base_2; -template -struct number_category > : public boost::mpl::int_{}; - -template -struct expression_template_default > -{ - static const expression_template_option value = is_void::value ? et_off : et_on; +template +struct number_category< + cpp_bin_float> + : public boost::mpl::int_< + boost::multiprecision::number_kind_floating_point> {}; + +template +struct expression_template_default< + cpp_bin_float> { + static const expression_template_option value = + is_void::value ? et_off : et_on; }; -typedef number > cpp_bin_float_50; -typedef number > cpp_bin_float_100; - -typedef number, et_off> cpp_bin_float_single; -typedef number, et_off> cpp_bin_float_double; -typedef number, et_off> cpp_bin_float_double_extended; -typedef number, et_off> cpp_bin_float_quad; -typedef number, et_off> cpp_bin_float_oct; +typedef number> cpp_bin_float_50; +typedef number> cpp_bin_float_100; + +typedef number, + et_off> + cpp_bin_float_single; +typedef number, + et_off> + cpp_bin_float_double; +typedef number, + et_off> + cpp_bin_float_double_extended; +typedef number, + et_off> + cpp_bin_float_quad; +typedef number, + et_off> + cpp_bin_float_oct; } // namespace multiprecision namespace math { - using boost::multiprecision::signbit; - using boost::multiprecision::copysign; +using boost::multiprecision::copysign; +using boost::multiprecision::signbit; } // namespace math @@ -1835,210 +2206,399 @@ namespace math { #include #include -namespace std{ +namespace std { // -// numeric_limits [partial] specializations for the types declared in this header: +// numeric_limits [partial] specializations for the types declared in this +// header: // -template -class numeric_limits, ExpressionTemplates> > -{ - typedef boost::multiprecision::number, ExpressionTemplates> number_type; +template +class numeric_limits, + ExpressionTemplates>> { + typedef boost::multiprecision::number< + boost::multiprecision::cpp_bin_float, + ExpressionTemplates> + number_type; + public: - BOOST_STATIC_CONSTEXPR bool is_specialized = true; - static number_type (min)() - { - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - value.first = true; - typedef typename boost::mpl::front::type ui_type; - value.second.backend() = ui_type(1u); - value.second.backend().exponent() = boost::multiprecision::cpp_bin_float::min_exponent; - } - return value.second; - } - static number_type (max)() - { - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - value.first = true; - if(boost::is_void::value) - eval_complement(value.second.backend().bits(), value.second.backend().bits()); - else - { - // We jump through hoops here using the backend type directly just to keep VC12 happy - // (ie compiler workaround, for very strange compiler bug): - using boost::multiprecision::default_ops::eval_add; - using boost::multiprecision::default_ops::eval_decrement; - using boost::multiprecision::default_ops::eval_left_shift; - typedef typename number_type::backend_type::rep_type int_backend_type; - typedef typename boost::mpl::front::type ui_type; - int_backend_type i; - i = ui_type(1u); - eval_left_shift(i, boost::multiprecision::cpp_bin_float::bit_count - 1); - int_backend_type j(i); - eval_decrement(i); - eval_add(j, i); - value.second.backend().bits() = j; - } - value.second.backend().exponent() = boost::multiprecision::cpp_bin_float::max_exponent; + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + static number_type(min)() { + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + value.first = true; + typedef typename boost::mpl::front< + typename number_type::backend_type::unsigned_types>::type ui_type; + value.second.backend() = ui_type(1u); + value.second.backend().exponent() = boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent; + } + return value.second; + } + static number_type(max)() { + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + value.first = true; + if (boost::is_void::value) + eval_complement(value.second.backend().bits(), + value.second.backend().bits()); + else { + // We jump through hoops here using the backend type directly just to + // keep VC12 happy (ie compiler workaround, for very strange compiler + // bug): + using boost::multiprecision::default_ops::eval_add; + using boost::multiprecision::default_ops::eval_decrement; + using boost::multiprecision::default_ops::eval_left_shift; + typedef typename number_type::backend_type::rep_type int_backend_type; + typedef typename boost::mpl::front< + typename int_backend_type::unsigned_types>::type ui_type; + int_backend_type i; + i = ui_type(1u); + eval_left_shift( + i, + boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - + 1); + int_backend_type j(i); + eval_decrement(i); + eval_add(j, i); + value.second.backend().bits() = j; } - return value.second; - } - BOOST_STATIC_CONSTEXPR number_type lowest() - { - return -(max)(); - } - BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::cpp_bin_float::bit_count; - BOOST_STATIC_CONSTEXPR int digits10 = (digits - 1) * 301 / 1000; - // Is this really correct??? - BOOST_STATIC_CONSTEXPR int max_digits10 = (digits * 301 / 1000) + 3; - BOOST_STATIC_CONSTEXPR bool is_signed = true; - BOOST_STATIC_CONSTEXPR bool is_integer = false; - BOOST_STATIC_CONSTEXPR bool is_exact = false; - BOOST_STATIC_CONSTEXPR int radix = 2; - static number_type epsilon() - { - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - // We jump through hoops here just to keep VC12 happy (ie compiler workaround, for very strange compiler bug): - typedef typename boost::mpl::front::type ui_type; - value.first = true; - value.second.backend() = ui_type(1u); - value.second = ldexp(value.second, 1 - (int)digits); - } - return value.second; - } - // What value should this be???? - static number_type round_error() - { - // returns 0.5 - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - value.first = true; - // We jump through hoops here just to keep VC12 happy (ie compiler workaround, for very strange compiler bug): - typedef typename boost::mpl::front::type ui_type; - value.second.backend() = ui_type(1u); - value.second = ldexp(value.second, -1); - } - return value.second; - } - BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float::exponent_type min_exponent = boost::multiprecision::cpp_bin_float::min_exponent; - BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float::exponent_type min_exponent10 = (min_exponent / 1000) * 301L; - BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float::exponent_type max_exponent = boost::multiprecision::cpp_bin_float::max_exponent; - BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float::exponent_type max_exponent10 = (max_exponent / 1000) * 301L; - BOOST_STATIC_CONSTEXPR bool has_infinity = true; - BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true; - BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; - BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; - BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; - static number_type infinity() - { - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - value.first = true; - value.second.backend().exponent() = boost::multiprecision::cpp_bin_float::exponent_infinity; - } - return value.second; - } - static number_type quiet_NaN() - { - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - value.first = true; - value.second.backend().exponent() = boost::multiprecision::cpp_bin_float::exponent_nan; - } - return value.second; - } - BOOST_STATIC_CONSTEXPR number_type signaling_NaN() - { - return number_type(0); - } - BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); } - BOOST_STATIC_CONSTEXPR bool is_iec559 = false; - BOOST_STATIC_CONSTEXPR bool is_bounded = true; - BOOST_STATIC_CONSTEXPR bool is_modulo = false; - BOOST_STATIC_CONSTEXPR bool traps = true; - BOOST_STATIC_CONSTEXPR bool tinyness_before = false; - BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest; + value.second.backend().exponent() = boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent; + } + return value.second; + } + BOOST_STATIC_CONSTEXPR number_type lowest() { return -(max)(); } + BOOST_STATIC_CONSTEXPR int digits = + boost::multiprecision::cpp_bin_float::bit_count; + BOOST_STATIC_CONSTEXPR int digits10 = (digits - 1) * 301 / 1000; + // Is this really correct??? + BOOST_STATIC_CONSTEXPR int max_digits10 = (digits * 301 / 1000) + 3; + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = false; + BOOST_STATIC_CONSTEXPR int radix = 2; + static number_type epsilon() { + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + // We jump through hoops here just to keep VC12 happy (ie compiler + // workaround, for very strange compiler bug): + typedef typename boost::mpl::front< + typename number_type::backend_type::unsigned_types>::type ui_type; + value.first = true; + value.second.backend() = ui_type(1u); + value.second = ldexp(value.second, 1 - (int)digits); + } + return value.second; + } + // What value should this be???? + static number_type round_error() { + // returns 0.5 + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + value.first = true; + // We jump through hoops here just to keep VC12 happy (ie compiler + // workaround, for very strange compiler bug): + typedef typename boost::mpl::front< + typename number_type::backend_type::unsigned_types>::type ui_type; + value.second.backend() = ui_type(1u); + value.second = ldexp(value.second, -1); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, + MaxE>::exponent_type min_exponent = + boost::multiprecision::cpp_bin_float::min_exponent; + BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type + min_exponent10 = (min_exponent / 1000) * 301L; + BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, + MaxE>::exponent_type max_exponent = + boost::multiprecision::cpp_bin_float::max_exponent; + BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type + max_exponent10 = (max_exponent / 1000) * 301L; + BOOST_STATIC_CONSTEXPR bool has_infinity = true; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() { + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + value.first = true; + value.second.backend().exponent() = + boost::multiprecision::cpp_bin_float::exponent_infinity; + } + return value.second; + } + static number_type quiet_NaN() { + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + value.first = true; + value.second.backend().exponent() = boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan; + } + return value.second; + } + BOOST_STATIC_CONSTEXPR number_type signaling_NaN() { return number_type(0); } + BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = true; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = true; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest; + private: - struct data_initializer - { - data_initializer() - { - std::numeric_limits > >::epsilon(); - std::numeric_limits > >::round_error(); - (std::numeric_limits > >::min)(); - (std::numeric_limits > >::max)(); - std::numeric_limits > >::infinity(); - std::numeric_limits > >::quiet_NaN(); - } - void do_nothing()const{} - }; - static const data_initializer initializer; + struct data_initializer { + data_initializer() { + std::numeric_limits< + boost::multiprecision::number>>::epsilon(); + std::numeric_limits< + boost::multiprecision::number>>:: + round_error(); + (std::numeric_limits< + boost::multiprecision::number>>::min)(); + (std::numeric_limits< + boost::multiprecision::number>>::max)(); + std::numeric_limits< + boost::multiprecision::number>>::infinity(); + std::numeric_limits< + boost::multiprecision::number>>:: + quiet_NaN(); + } + void do_nothing() const {} + }; + static const data_initializer initializer; }; -template -const typename numeric_limits, ExpressionTemplates> >::data_initializer numeric_limits, ExpressionTemplates> >::initializer; +template +const typename numeric_limits, + ExpressionTemplates>>::data_initializer + numeric_limits, + ExpressionTemplates>>::initializer; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; -template -BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float::exponent_type numeric_limits, ExpressionTemplates> >::min_exponent; -template -BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float::exponent_type numeric_limits, ExpressionTemplates> >::min_exponent10; -template -BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float::exponent_type numeric_limits, ExpressionTemplates> >::max_exponent; -template -BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float::exponent_type numeric_limits, ExpressionTemplates> >::max_exponent10; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; -template -BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; -template -BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::radix; +template +BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type + numeric_limits, + ExpressionTemplates>>::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type + numeric_limits, + ExpressionTemplates>>::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type + numeric_limits, + ExpressionTemplates>>::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float< + Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type + numeric_limits, + ExpressionTemplates>>::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style + numeric_limits, + ExpressionTemplates>>::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style + numeric_limits, + ExpressionTemplates>>::round_style; #endif diff --git a/include/boost/multiprecision/cpp_bin_float/io.hpp b/include/boost/multiprecision/cpp_bin_float/io.hpp index 43b016a73..e5f4f9411 100644 --- a/include/boost/multiprecision/cpp_bin_float/io.hpp +++ b/include/boost/multiprecision/cpp_bin_float/io.hpp @@ -6,695 +6,744 @@ #ifndef BOOST_MP_CPP_BIN_FLOAT_IO_HPP #define BOOST_MP_CPP_BIN_FLOAT_IO_HPP -namespace boost{ namespace multiprecision{ namespace cpp_bf_io_detail{ +namespace boost { +namespace multiprecision { +namespace cpp_bf_io_detail { #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable : 4127) // conditional expression is constant #endif - // -// Multiplies a by b and shifts the result so it fits inside max_bits bits, +// Multiplies a by b and shifts the result so it fits inside max_bits bits, // returns by how much the result was shifted. // template -inline I restricted_multiply(cpp_int& result, const cpp_int& a, const cpp_int& b, I max_bits, boost::int64_t& error) -{ - result = a * b; - I gb = msb(result); - I rshift = 0; - if(gb > max_bits) - { - rshift = gb - max_bits; - I lb = lsb(result); - int roundup = 0; - // The error rate increases by the error of both a and b, - // this may be overly pessimistic in many case as we're assuming - // that a and b have the same level of uncertainty... - if(lb < rshift) - error = error ? error * 2 : 1; - if(rshift) - { - BOOST_ASSERT(rshift < INT_MAX); - if(bit_test(result, static_cast(rshift - 1))) - { - if(lb == rshift - 1) - roundup = 1; - else - roundup = 2; - } - result >>= rshift; +inline I restricted_multiply(cpp_int &result, const cpp_int &a, + const cpp_int &b, I max_bits, + boost::int64_t &error) { + result = a * b; + I gb = msb(result); + I rshift = 0; + if (gb > max_bits) { + rshift = gb - max_bits; + I lb = lsb(result); + int roundup = 0; + // The error rate increases by the error of both a and b, + // this may be overly pessimistic in many case as we're assuming + // that a and b have the same level of uncertainty... + if (lb < rshift) + error = error ? error * 2 : 1; + if (rshift) { + BOOST_ASSERT(rshift < INT_MAX); + if (bit_test(result, static_cast(rshift - 1))) { + if (lb == rshift - 1) + roundup = 1; + else + roundup = 2; } - if((roundup == 2) || ((roundup == 1) && (result.backend().limbs()[0] & 1))) - ++result; - } - return rshift; + result >>= rshift; + } + if ((roundup == 2) || ((roundup == 1) && (result.backend().limbs()[0] & 1))) + ++result; + } + return rshift; } // // Computes a^e shifted to the right so it fits in max_bits, returns how far // to the right we are shifted. // template -inline I restricted_pow(cpp_int& result, const cpp_int& a, I e, I max_bits, boost::int64_t& error) -{ - BOOST_ASSERT(&result != &a); - I exp = 0; - if(e == 1) - { - result = a; - return exp; - } - else if(e == 2) - { - return restricted_multiply(result, a, a, max_bits, error); - } - else if(e == 3) - { - exp = restricted_multiply(result, a, a, max_bits, error); - exp += restricted_multiply(result, result, a, max_bits, error); - return exp; - } - I p = e / 2; - exp = restricted_pow(result, a, p, max_bits, error); - exp *= 2; - exp += restricted_multiply(result, result, result, max_bits, error); - if(e & 1) - exp += restricted_multiply(result, result, a, max_bits, error); - return exp; +inline I restricted_pow(cpp_int &result, const cpp_int &a, I e, I max_bits, + boost::int64_t &error) { + BOOST_ASSERT(&result != &a); + I exp = 0; + if (e == 1) { + result = a; + return exp; + } else if (e == 2) { + return restricted_multiply(result, a, a, max_bits, error); + } else if (e == 3) { + exp = restricted_multiply(result, a, a, max_bits, error); + exp += restricted_multiply(result, result, a, max_bits, error); + return exp; + } + I p = e / 2; + exp = restricted_pow(result, a, p, max_bits, error); + exp *= 2; + exp += restricted_multiply(result, result, result, max_bits, error); + if (e & 1) + exp += restricted_multiply(result, result, a, max_bits, error); + return exp; } -inline int get_round_mode(const cpp_int& what, boost::int64_t location, boost::int64_t error) -{ - // - // Can we round what at /location/, if the error in what is /error/ in - // units of 0.5ulp. Return: - // - // -1: Can't round. - // 0: leave as is. - // 1: tie. - // 2: round up. - // - BOOST_ASSERT(location >= 0); - BOOST_ASSERT(location < INT_MAX); - boost::int64_t error_radius = error & 1 ? (1 + error) / 2 : error / 2; - if(error_radius && ((int)msb(error_radius) >= location)) +inline int get_round_mode(const cpp_int &what, boost::int64_t location, + boost::int64_t error) { + // + // Can we round what at /location/, if the error in what is /error/ in + // units of 0.5ulp. Return: + // + // -1: Can't round. + // 0: leave as is. + // 1: tie. + // 2: round up. + // + BOOST_ASSERT(location >= 0); + BOOST_ASSERT(location < INT_MAX); + boost::int64_t error_radius = error & 1 ? (1 + error) / 2 : error / 2; + if (error_radius && ((int)msb(error_radius) >= location)) + return -1; + if (bit_test(what, static_cast(location))) { + if ((int)lsb(what) == location) + return error ? -1 : 1; // Either a tie or can't round depending on whether + // we have any error + if (!error) + return 2; // no error, round up. + cpp_int t = what - error_radius; + if ((int)lsb(t) >= location) return -1; - if(bit_test(what, static_cast(location))) - { - if((int)lsb(what) == location) - return error ? -1 : 1; // Either a tie or can't round depending on whether we have any error - if(!error) - return 2; // no error, round up. - cpp_int t = what - error_radius; - if((int)lsb(t) >= location) - return -1; - return 2; - } - else if(error) - { - cpp_int t = what + error_radius; - return bit_test(t, static_cast(location)) ? -1 : 0; - } - return 0; + return 2; + } else if (error) { + cpp_int t = what + error_radius; + return bit_test(t, static_cast(location)) ? -1 : 0; + } + return 0; } -inline int get_round_mode(cpp_int& r, cpp_int& d, boost::int64_t error, const cpp_int& q) -{ - // - // Lets suppose we have an inexact division by d+delta, where the true - // value for the divisor is d, and with |delta| <= error/2, then - // we have calculated q and r such that: - // - // n r - // --- = q + ----------- - // d + error d + error - // - // Rearranging for n / d we get: - // - // n delta*q + r - // --- = q + ------------- - // d d - // - // So rounding depends on whether 2r + error * q > d. - // - // We return: - // 0 = down down. - // 1 = tie. - // 2 = round up. - // -1 = couldn't decide. - // - r <<= 1; - int c = r.compare(d); - if(c == 0) - return error ? -1 : 1; - if(c > 0) - { - if(error) - { - r -= error * q; - return r.compare(d) > 0 ? 2 : -1; - } - return 2; - } - if(error) - { - r += error * q; - return r.compare(d) < 0 ? 0 : -1; - } - return 0; +inline int get_round_mode(cpp_int &r, cpp_int &d, boost::int64_t error, + const cpp_int &q) { + // + // Lets suppose we have an inexact division by d+delta, where the true + // value for the divisor is d, and with |delta| <= error/2, then + // we have calculated q and r such that: + // + // n r + // --- = q + ----------- + // d + error d + error + // + // Rearranging for n / d we get: + // + // n delta*q + r + // --- = q + ------------- + // d d + // + // So rounding depends on whether 2r + error * q > d. + // + // We return: + // 0 = down down. + // 1 = tie. + // 2 = round up. + // -1 = couldn't decide. + // + r <<= 1; + int c = r.compare(d); + if (c == 0) + return error ? -1 : 1; + if (c > 0) { + if (error) { + r -= error * q; + return r.compare(d) > 0 ? 2 : -1; + } + return 2; + } + if (error) { + r += error * q; + return r.compare(d) < 0 ? 0 : -1; + } + return 0; } -} // namespace +} // namespace cpp_bf_io_detail -namespace backends{ +namespace backends { -template -cpp_bin_float& cpp_bin_float::operator=(const char *s) -{ - cpp_int n; - boost::intmax_t decimal_exp = 0; - boost::intmax_t digits_seen = 0; - static const boost::intmax_t max_digits_seen = 4 + (cpp_bin_float::bit_count * 301L) / 1000; - bool ss = false; - // - // Extract the sign: - // - if(*s == '-') - { - ss = true; - ++s; - } - else if(*s == '+') - ++s; - // - // Special cases first: - // - if((std::strcmp(s, "nan") == 0) || (std::strcmp(s, "NaN") == 0) || (std::strcmp(s, "NAN") == 0)) - { - return *this = std::numeric_limits > >::quiet_NaN().backend(); - } - if((std::strcmp(s, "inf") == 0) || (std::strcmp(s, "Inf") == 0) || (std::strcmp(s, "INF") == 0) || (std::strcmp(s, "infinity") == 0) || (std::strcmp(s, "Infinity") == 0) || (std::strcmp(s, "INFINITY") == 0)) - { - *this = std::numeric_limits > >::infinity().backend(); - if(ss) - negate(); - return *this; - } - // - // Digits before the point: - // - while(*s && (*s >= '0') && (*s <= '9')) - { - n *= 10u; - n += *s - '0'; - if(digits_seen || (*s != '0')) - ++digits_seen; - ++s; - } - // The decimal point (we really should localise this!!) - if(*s && (*s == '.')) +template +cpp_bin_float & +cpp_bin_float:: +operator=(const char *s) { + cpp_int n; + boost::intmax_t decimal_exp = 0; + boost::intmax_t digits_seen = 0; + static const boost::intmax_t max_digits_seen = + 4 + (cpp_bin_float::bit_count * + 301L) / + 1000; + bool ss = false; + // + // Extract the sign: + // + if (*s == '-') { + ss = true; + ++s; + } else if (*s == '+') + ++s; + // + // Special cases first: + // + if ((std::strcmp(s, "nan") == 0) || (std::strcmp(s, "NaN") == 0) || + (std::strcmp(s, "NAN") == 0)) { + return *this = std::numeric_limits< + number>>::quiet_NaN() + .backend(); + } + if ((std::strcmp(s, "inf") == 0) || (std::strcmp(s, "Inf") == 0) || + (std::strcmp(s, "INF") == 0) || (std::strcmp(s, "infinity") == 0) || + (std::strcmp(s, "Infinity") == 0) || (std::strcmp(s, "INFINITY") == 0)) { + *this = std::numeric_limits>>::infinity() + .backend(); + if (ss) + negate(); + return *this; + } + // + // Digits before the point: + // + while (*s && (*s >= '0') && (*s <= '9')) { + n *= 10u; + n += *s - '0'; + if (digits_seen || (*s != '0')) + ++digits_seen; + ++s; + } + // The decimal point (we really should localise this!!) + if (*s && (*s == '.')) + ++s; + // + // Digits after the point: + // + while (*s && (*s >= '0') && (*s <= '9')) { + n *= 10u; + n += *s - '0'; + --decimal_exp; + if (digits_seen || (*s != '0')) + ++digits_seen; + ++s; + if (digits_seen > max_digits_seen) + break; + } + // + // Digits we're skipping: + // + while (*s && (*s >= '0') && (*s <= '9')) + ++s; + // + // See if there's an exponent: + // + if (*s && ((*s == 'e') || (*s == 'E'))) { + ++s; + boost::intmax_t e = 0; + bool es = false; + if (*s && (*s == '-')) { + es = true; ++s; - // - // Digits after the point: - // - while(*s && (*s >= '0') && (*s <= '9')) - { - n *= 10u; - n += *s - '0'; - --decimal_exp; - if(digits_seen || (*s != '0')) - ++digits_seen; + } else if (*s && (*s == '+')) ++s; - if(digits_seen > max_digits_seen) - break; - } - // - // Digits we're skipping: - // - while(*s && (*s >= '0') && (*s <= '9')) + while (*s && (*s >= '0') && (*s <= '9')) { + e *= 10u; + e += *s - '0'; ++s; - // - // See if there's an exponent: - // - if(*s && ((*s == 'e') || (*s == 'E'))) - { - ++s; - boost::intmax_t e = 0; - bool es = false; - if(*s && (*s == '-')) - { - es = true; - ++s; - } - else if(*s && (*s == '+')) - ++s; - while(*s && (*s >= '0') && (*s <= '9')) - { - e *= 10u; - e += *s - '0'; - ++s; - } - if(es) - e = -e; - decimal_exp += e; - } - if(*s) - { - // - // Oops unexpected input at the end of the number: - // - BOOST_THROW_EXCEPTION(std::runtime_error("Unable to parse string as a valid floating point number.")); - } - if(n == 0) - { - // Result is necessarily zero: - *this = static_cast(0u); - return *this; - } + } + if (es) + e = -e; + decimal_exp += e; + } + if (*s) { + // + // Oops unexpected input at the end of the number: + // + BOOST_THROW_EXCEPTION(std::runtime_error( + "Unable to parse string as a valid floating point number.")); + } + if (n == 0) { + // Result is necessarily zero: + *this = static_cast(0u); + return *this; + } - static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; - // - // Set our working precision - this is heuristic based, we want - // a value as small as possible > cpp_bin_float::bit_count to avoid large computations - // and excessive memory usage, but we also want to avoid having to - // up the computation and start again at a higher precision. - // So we round cpp_bin_float::bit_count up to the nearest whole number of limbs, and add - // one limb for good measure. This works very well for small exponents, - // but for larger exponents we may may need to restart, we could add some - // extra precision right from the start for larger exponents, but this - // seems to be slightly slower in the *average* case: - // + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + // + // Set our working precision - this is heuristic based, we want + // a value as small as possible > cpp_bin_float::bit_count to avoid large computations and excessive + // memory usage, but we also want to avoid having to up the computation and + // start again at a higher precision. So we round cpp_bin_float::bit_count up to the nearest + // whole number of limbs, and add one limb for good measure. This works very + // well for small exponents, but for larger exponents we may may need to + // restart, we could add some extra precision right from the start for larger + // exponents, but this seems to be slightly slower in the *average* case: + // #ifdef BOOST_MP_STRESS_IO - boost::intmax_t max_bits = cpp_bin_float::bit_count + 32; + boost::intmax_t max_bits = cpp_bin_float::bit_count + + 32; #else - boost::intmax_t max_bits = cpp_bin_float::bit_count + ((cpp_bin_float::bit_count % limb_bits) ? (limb_bits - cpp_bin_float::bit_count % limb_bits) : 0) + limb_bits; + boost::intmax_t max_bits = + cpp_bin_float::bit_count + + ((cpp_bin_float::bit_count % + limb_bits) + ? (limb_bits - cpp_bin_float::bit_count % + limb_bits) + : 0) + + limb_bits; #endif - boost::int64_t error = 0; - boost::intmax_t calc_exp = 0; - boost::intmax_t final_exponent = 0; + boost::int64_t error = 0; + boost::intmax_t calc_exp = 0; + boost::intmax_t final_exponent = 0; - if(decimal_exp >= 0) - { - // Nice and simple, the result is an integer... - do - { - cpp_int t; - if(decimal_exp) - { - calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(t, cpp_int(5), decimal_exp, max_bits, error); - calc_exp += boost::multiprecision::cpp_bf_io_detail::restricted_multiply(t, t, n, max_bits, error); - } - else - t = n; - final_exponent = (boost::int64_t)cpp_bin_float::bit_count - 1 + decimal_exp + calc_exp; - int rshift = msb(t) - cpp_bin_float::bit_count + 1; - if(rshift > 0) - { - final_exponent += rshift; - int roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(t, rshift - 1, error); - t >>= rshift; - if((roundup == 2) || ((roundup == 1) && t.backend().limbs()[0] & 1)) - ++t; - else if(roundup < 0) - { + if (decimal_exp >= 0) { + // Nice and simple, the result is an integer... + do { + cpp_int t; + if (decimal_exp) { + calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow( + t, cpp_int(5), decimal_exp, max_bits, error); + calc_exp += + boost::multiprecision::cpp_bf_io_detail::restricted_multiply( + t, t, n, max_bits, error); + } else + t = n; + final_exponent = + (boost::int64_t)cpp_bin_float::bit_count - + 1 + decimal_exp + calc_exp; + int rshift = msb(t) - + cpp_bin_float::bit_count + + 1; + if (rshift > 0) { + final_exponent += rshift; + int roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode( + t, rshift - 1, error); + t >>= rshift; + if ((roundup == 2) || ((roundup == 1) && t.backend().limbs()[0] & 1)) + ++t; + else if (roundup < 0) { #ifdef BOOST_MP_STRESS_IO - max_bits += 32; + max_bits += 32; #else - max_bits *= 2; + max_bits *= 2; #endif - error = 0; - continue; - } - } - else - { - BOOST_ASSERT(!error); - } - if(final_exponent > cpp_bin_float::max_exponent) - { - exponent() = cpp_bin_float::max_exponent; - final_exponent -= cpp_bin_float::max_exponent; - } - else if(final_exponent < cpp_bin_float::min_exponent) - { - // Underflow: - exponent() = cpp_bin_float::min_exponent; - final_exponent -= cpp_bin_float::min_exponent; - } - else - { - exponent() = static_cast(final_exponent); - final_exponent = 0; - } - copy_and_round(*this, t.backend()); - break; + error = 0; + continue; + } + } else { + BOOST_ASSERT(!error); } - while(true); + if (final_exponent > cpp_bin_float::max_exponent) { + exponent() = cpp_bin_float::max_exponent; + final_exponent -= cpp_bin_float::max_exponent; + } else if (final_exponent < + cpp_bin_float::min_exponent) { + // Underflow: + exponent() = cpp_bin_float::min_exponent; + final_exponent -= cpp_bin_float::min_exponent; + } else { + exponent() = static_cast(final_exponent); + final_exponent = 0; + } + copy_and_round(*this, t.backend()); + break; + } while (true); - if(ss != sign()) - negate(); - } - else - { - // Result is the ratio of two integers: we need to organise the - // division so as to produce at least an N-bit result which we can - // round according to the remainder. - //cpp_int d = pow(cpp_int(5), -decimal_exp); - do - { - cpp_int d; - calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(d, cpp_int(5), -decimal_exp, max_bits, error); - int shift = (int)cpp_bin_float::bit_count - msb(n) + msb(d); - final_exponent = cpp_bin_float::bit_count - 1 + decimal_exp - calc_exp; - if(shift > 0) - { - n <<= shift; - final_exponent -= static_cast(shift); - } - cpp_int q, r; - divide_qr(n, d, q, r); - int gb = msb(q); - BOOST_ASSERT((gb >= static_cast(cpp_bin_float::bit_count) - 1)); - // - // Check for rounding conditions we have to - // handle ourselves: - // - int roundup = 0; - if(gb == cpp_bin_float::bit_count - 1) - { - // Exactly the right number of bits, use the remainder to round: - roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(r, d, error, q); - } - else if(bit_test(q, gb - (int)cpp_bin_float::bit_count) && ((int)lsb(q) == (gb - (int)cpp_bin_float::bit_count))) - { - // Too many bits in q and the bits in q indicate a tie, but we can break that using r, - // note that the radius of error in r is error/2 * q: - int lshift = gb - (int)cpp_bin_float::bit_count + 1; - q >>= lshift; - final_exponent += static_cast(lshift); - BOOST_ASSERT((msb(q) >= cpp_bin_float::bit_count - 1)); - if(error && (r < (error / 2) * q)) - roundup = -1; - else if(error && (r + (error / 2) * q >= d)) - roundup = -1; - else - roundup = r ? 2 : 1; - } - else if(error && (((error / 2) * q + r >= d) || (r < (error / 2) * q))) - { - // We might have been rounding up, or got the wrong quotient: can't tell! - roundup = -1; - } - if(roundup < 0) - { + if (ss != sign()) + negate(); + } else { + // Result is the ratio of two integers: we need to organise the + // division so as to produce at least an N-bit result which we can + // round according to the remainder. + // cpp_int d = pow(cpp_int(5), -decimal_exp); + do { + cpp_int d; + calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow( + d, cpp_int(5), -decimal_exp, max_bits, error); + int shift = (int)cpp_bin_float::bit_count - + msb(n) + msb(d); + final_exponent = cpp_bin_float::bit_count - + 1 + decimal_exp - calc_exp; + if (shift > 0) { + n <<= shift; + final_exponent -= static_cast(shift); + } + cpp_int q, r; + divide_qr(n, d, q, r); + int gb = msb(q); + BOOST_ASSERT((gb >= static_cast( + cpp_bin_float::bit_count) - + 1)); + // + // Check for rounding conditions we have to + // handle ourselves: + // + int roundup = 0; + if (gb == cpp_bin_float::bit_count - + 1) { + // Exactly the right number of bits, use the remainder to round: + roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode( + r, d, error, q); + } else if (bit_test( + q, + gb - + (int)cpp_bin_float::bit_count) && + ((int)lsb(q) == + (gb - (int)cpp_bin_float::bit_count))) { + // Too many bits in q and the bits in q indicate a tie, but we can break + // that using r, note that the radius of error in r is error/2 * q: + int lshift = gb - + (int)cpp_bin_float::bit_count + + 1; + q >>= lshift; + final_exponent += static_cast(lshift); + BOOST_ASSERT((msb(q) >= cpp_bin_float::bit_count - + 1)); + if (error && (r < (error / 2) * q)) + roundup = -1; + else if (error && (r + (error / 2) * q >= d)) + roundup = -1; + else + roundup = r ? 2 : 1; + } else if (error && + (((error / 2) * q + r >= d) || (r < (error / 2) * q))) { + // We might have been rounding up, or got the wrong quotient: can't + // tell! + roundup = -1; + } + if (roundup < 0) { #ifdef BOOST_MP_STRESS_IO - max_bits += 32; + max_bits += 32; #else - max_bits *= 2; + max_bits *= 2; #endif - error = 0; - if(shift > 0) - { - n >>= shift; - final_exponent += static_cast(shift); - } - continue; - } - else if((roundup == 2) || ((roundup == 1) && q.backend().limbs()[0] & 1)) - ++q; - if(final_exponent > cpp_bin_float::max_exponent) - { - // Overflow: - exponent() = cpp_bin_float::max_exponent; - final_exponent -= cpp_bin_float::max_exponent; - } - else if(final_exponent < cpp_bin_float::min_exponent) - { - // Underflow: - exponent() = cpp_bin_float::min_exponent; - final_exponent -= cpp_bin_float::min_exponent; - } - else - { - exponent() = static_cast(final_exponent); - final_exponent = 0; - } - copy_and_round(*this, q.backend()); - if(ss != sign()) - negate(); - break; + error = 0; + if (shift > 0) { + n >>= shift; + final_exponent += static_cast(shift); + } + continue; + } else if ((roundup == 2) || + ((roundup == 1) && q.backend().limbs()[0] & 1)) + ++q; + if (final_exponent > cpp_bin_float::max_exponent) { + // Overflow: + exponent() = cpp_bin_float::max_exponent; + final_exponent -= cpp_bin_float::max_exponent; + } else if (final_exponent < + cpp_bin_float::min_exponent) { + // Underflow: + exponent() = cpp_bin_float::min_exponent; + final_exponent -= cpp_bin_float::min_exponent; + } else { + exponent() = static_cast(final_exponent); + final_exponent = 0; } - while(true); - } - // - // Check for scaling and/or over/under-flow: - // - final_exponent += exponent(); - if(final_exponent > cpp_bin_float::max_exponent) - { - // Overflow: - exponent() = cpp_bin_float::exponent_infinity; - bits() = limb_type(0); - } - else if(final_exponent < cpp_bin_float::min_exponent) - { - // Underflow: - exponent() = cpp_bin_float::exponent_zero; - bits() = limb_type(0); - sign() = 0; - } - else - { - exponent() = static_cast(final_exponent); - } - return *this; + copy_and_round(*this, q.backend()); + if (ss != sign()) + negate(); + break; + } while (true); + } + // + // Check for scaling and/or over/under-flow: + // + final_exponent += exponent(); + if (final_exponent > cpp_bin_float::max_exponent) { + // Overflow: + exponent() = cpp_bin_float::exponent_infinity; + bits() = limb_type(0); + } else if (final_exponent < + cpp_bin_float::min_exponent) { + // Underflow: + exponent() = cpp_bin_float::exponent_zero; + bits() = limb_type(0); + sign() = 0; + } else { + exponent() = static_cast(final_exponent); + } + return *this; } -template -std::string cpp_bin_float::str(std::streamsize dig, std::ios_base::fmtflags f) const -{ - if(dig == 0) - dig = std::numeric_limits > >::max_digits10; +template +std::string +cpp_bin_float::str( + std::streamsize dig, std::ios_base::fmtflags f) const { + if (dig == 0) + dig = std::numeric_limits>>::max_digits10; - bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; - bool fixed = !scientific && (f & std::ios_base::fixed); + bool scientific = + (f & std::ios_base::scientific) == std::ios_base::scientific; + bool fixed = !scientific && (f & std::ios_base::fixed); - std::string s; + std::string s; - if(exponent() <= cpp_bin_float::max_exponent) - { - // How far to left-shift in order to demormalise the mantissa: - boost::intmax_t shift = (boost::intmax_t)cpp_bin_float::bit_count - (boost::intmax_t)exponent() - 1; - boost::intmax_t digits_wanted = static_cast(dig); - boost::intmax_t base10_exp = exponent() >= 0 ? static_cast(std::floor(0.30103 * exponent())) : static_cast(std::ceil(0.30103 * exponent())); - // - // For fixed formatting we want /dig/ digits after the decimal point, - // so if the exponent is zero, allowing for the one digit before the - // decimal point, we want 1 + dig digits etc. - // - if(fixed) - digits_wanted += 1 + base10_exp; - if(scientific) - digits_wanted += 1; - if(digits_wanted < -1) - { - // Fixed precision, no significant digits, and nothing to round! - s = "0"; - if(sign()) - s.insert(static_cast(0), 1, '-'); - boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, true); - return s; - } - // - // power10 is the base10 exponent we need to multiply/divide by in order - // to convert our denormalised number to an integer with the right number of digits: - // - boost::intmax_t power10 = digits_wanted - base10_exp - 1; - // - // If we calculate 5^power10 rather than 10^power10 we need to move - // 2^power10 into /shift/ - // - shift -= power10; - cpp_int i; - int roundup = 0; // 0=no rounding, 1=tie, 2=up - static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; - // - // Set our working precision - this is heuristic based, we want - // a value as small as possible > cpp_bin_float::bit_count to avoid large computations - // and excessive memory usage, but we also want to avoid having to - // up the computation and start again at a higher precision. - // So we round cpp_bin_float::bit_count up to the nearest whole number of limbs, and add - // one limb for good measure. This works very well for small exponents, - // but for larger exponents we add a few extra limbs to max_bits: - // + if (exponent() <= cpp_bin_float::max_exponent) { + // How far to left-shift in order to demormalise the mantissa: + boost::intmax_t shift = + (boost::intmax_t)cpp_bin_float::bit_count - + (boost::intmax_t)exponent() - 1; + boost::intmax_t digits_wanted = static_cast(dig); + boost::intmax_t base10_exp = + exponent() >= 0 + ? static_cast(std::floor(0.30103 * exponent())) + : static_cast(std::ceil(0.30103 * exponent())); + // + // For fixed formatting we want /dig/ digits after the decimal point, + // so if the exponent is zero, allowing for the one digit before the + // decimal point, we want 1 + dig digits etc. + // + if (fixed) + digits_wanted += 1 + base10_exp; + if (scientific) + digits_wanted += 1; + if (digits_wanted < -1) { + // Fixed precision, no significant digits, and nothing to round! + s = "0"; + if (sign()) + s.insert(static_cast(0), 1, '-'); + boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, + true); + return s; + } + // + // power10 is the base10 exponent we need to multiply/divide by in order + // to convert our denormalised number to an integer with the right number of + // digits: + // + boost::intmax_t power10 = digits_wanted - base10_exp - 1; + // + // If we calculate 5^power10 rather than 10^power10 we need to move + // 2^power10 into /shift/ + // + shift -= power10; + cpp_int i; + int roundup = 0; // 0=no rounding, 1=tie, 2=up + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + // + // Set our working precision - this is heuristic based, we want + // a value as small as possible > cpp_bin_float::bit_count to avoid large computations + // and excessive memory usage, but we also want to avoid having to + // up the computation and start again at a higher precision. + // So we round cpp_bin_float::bit_count up to the nearest whole number of limbs, and add one + // limb for good measure. This works very well for small exponents, but for + // larger exponents we add a few extra limbs to max_bits: + // #ifdef BOOST_MP_STRESS_IO - boost::intmax_t max_bits = cpp_bin_float::bit_count + 32; + boost::intmax_t max_bits = cpp_bin_float::bit_count + + 32; #else - boost::intmax_t max_bits = cpp_bin_float::bit_count + ((cpp_bin_float::bit_count % limb_bits) ? (limb_bits - cpp_bin_float::bit_count % limb_bits) : 0) + limb_bits; - if(power10) - max_bits += (msb(boost::multiprecision::detail::abs(power10)) / 8) * limb_bits; + boost::intmax_t max_bits = + cpp_bin_float::bit_count + + ((cpp_bin_float::bit_count % + limb_bits) + ? (limb_bits - cpp_bin_float::bit_count % + limb_bits) + : 0) + + limb_bits; + if (power10) + max_bits += + (msb(boost::multiprecision::detail::abs(power10)) / 8) * limb_bits; #endif - do - { - boost::int64_t error = 0; - boost::intmax_t calc_exp = 0; - // - // Our integer result is: bits() * 2^-shift * 5^power10 - // - i = bits(); - if(shift < 0) - { - if(power10 >= 0) - { - // We go straight to the answer with all integer arithmetic, - // the result is always exact and never needs rounding: - BOOST_ASSERT(power10 <= (boost::intmax_t)INT_MAX); - i <<= -shift; - if(power10) - i *= pow(cpp_int(5), static_cast(power10)); - } - else if(power10 < 0) - { - cpp_int d; - calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(d, cpp_int(5), -power10, max_bits, error); - shift += calc_exp; - BOOST_ASSERT(shift < 0); // Must still be true! - i <<= -shift; - cpp_int r; - divide_qr(i, d, i, r); - roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(r, d, error, i); - if(roundup < 0) - { + do { + boost::int64_t error = 0; + boost::intmax_t calc_exp = 0; + // + // Our integer result is: bits() * 2^-shift * 5^power10 + // + i = bits(); + if (shift < 0) { + if (power10 >= 0) { + // We go straight to the answer with all integer arithmetic, + // the result is always exact and never needs rounding: + BOOST_ASSERT(power10 <= (boost::intmax_t)INT_MAX); + i <<= -shift; + if (power10) + i *= pow(cpp_int(5), static_cast(power10)); + } else if (power10 < 0) { + cpp_int d; + calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow( + d, cpp_int(5), -power10, max_bits, error); + shift += calc_exp; + BOOST_ASSERT(shift < 0); // Must still be true! + i <<= -shift; + cpp_int r; + divide_qr(i, d, i, r); + roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode( + r, d, error, i); + if (roundup < 0) { #ifdef BOOST_MP_STRESS_IO - max_bits += 32; + max_bits += 32; #else - max_bits *= 2; + max_bits *= 2; #endif - shift = (boost::intmax_t)cpp_bin_float::bit_count - exponent() - 1 - power10; - continue; - } - } - } - else - { - // - // Our integer is bits() * 2^-shift * 10^power10 - // - if(power10 > 0) - { - if(power10) - { - cpp_int t; - calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(t, cpp_int(5), power10, max_bits, error); - calc_exp += boost::multiprecision::cpp_bf_io_detail::restricted_multiply(i, i, t, max_bits, error); - shift -= calc_exp; - } - if((shift < 0) || ((shift == 0) && error)) - { - // We only get here if we were asked for a crazy number of decimal digits - - // more than are present in a 2^max_bits number. + shift = (boost::intmax_t) + cpp_bin_float::bit_count - + exponent() - 1 - power10; + continue; + } + } + } else { + // + // Our integer is bits() * 2^-shift * 10^power10 + // + if (power10 > 0) { + if (power10) { + cpp_int t; + calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow( + t, cpp_int(5), power10, max_bits, error); + calc_exp += + boost::multiprecision::cpp_bf_io_detail::restricted_multiply( + i, i, t, max_bits, error); + shift -= calc_exp; + } + if ((shift < 0) || ((shift == 0) && error)) { + // We only get here if we were asked for a crazy number of decimal + // digits - more than are present in a 2^max_bits number. #ifdef BOOST_MP_STRESS_IO - max_bits += 32; + max_bits += 32; #else - max_bits *= 2; + max_bits *= 2; #endif - shift = (boost::intmax_t)cpp_bin_float::bit_count - exponent() - 1 - power10; - continue; - } - if(shift) - { - roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(i, shift - 1, error); - if(roundup < 0) - { + shift = (boost::intmax_t) + cpp_bin_float::bit_count - + exponent() - 1 - power10; + continue; + } + if (shift) { + roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode( + i, shift - 1, error); + if (roundup < 0) { #ifdef BOOST_MP_STRESS_IO - max_bits += 32; + max_bits += 32; #else - max_bits *= 2; + max_bits *= 2; #endif - shift = (boost::intmax_t)cpp_bin_float::bit_count - exponent() - 1 - power10; - continue; - } - i >>= shift; - } - } - else - { - // We're right shifting, *and* dividing by 5^-power10, - // so 5^-power10 can never be that large or we'd simply - // get zero as a result, and that case is already handled above: - cpp_int r; - BOOST_ASSERT(-power10 < INT_MAX); - cpp_int d = pow(cpp_int(5), static_cast(-power10)); - d <<= shift; - divide_qr(i, d, i, r); - r <<= 1; - int c = r.compare(d); - roundup = c < 0 ? 0 : c == 0 ? 1 : 2; + shift = (boost::intmax_t) + cpp_bin_float::bit_count - + exponent() - 1 - power10; + continue; } - } - s = i.str(0, std::ios_base::fmtflags(0)); - // - // Check if we got the right number of digits, this - // is really a test of whether we calculated the - // decimal exponent correctly: - // - boost::intmax_t digits_got = i ? static_cast(s.size()) : 0; - if(digits_got != digits_wanted) - { - base10_exp += digits_got - digits_wanted; - if(fixed) - digits_wanted = digits_got; // strange but true. - power10 = digits_wanted - base10_exp - 1; - shift = (boost::intmax_t)cpp_bin_float::bit_count - exponent() - 1 - power10; - if(fixed) - break; - roundup = 0; - } - else - break; + i >>= shift; + } + } else { + // We're right shifting, *and* dividing by 5^-power10, + // so 5^-power10 can never be that large or we'd simply + // get zero as a result, and that case is already handled above: + cpp_int r; + BOOST_ASSERT(-power10 < INT_MAX); + cpp_int d = pow(cpp_int(5), static_cast(-power10)); + d <<= shift; + divide_qr(i, d, i, r); + r <<= 1; + int c = r.compare(d); + roundup = c < 0 ? 0 : c == 0 ? 1 : 2; + } } - while(true); + s = i.str(0, std::ios_base::fmtflags(0)); // - // Check whether we need to round up: note that we could equally round up - // the integer /i/ above, but since we need to perform the rounding *after* - // the conversion to a string and the digit count check, we might as well - // do it here: + // Check if we got the right number of digits, this + // is really a test of whether we calculated the + // decimal exponent correctly: // - if((roundup == 2) || ((roundup == 1) && ((s[s.size() - 1] - '0') & 1))) - { - boost::multiprecision::detail::round_string_up_at(s, static_cast(s.size() - 1), base10_exp); - } + boost::intmax_t digits_got = + i ? static_cast(s.size()) : 0; + if (digits_got != digits_wanted) { + base10_exp += digits_got - digits_wanted; + if (fixed) + digits_wanted = digits_got; // strange but true. + power10 = digits_wanted - base10_exp - 1; + shift = + (boost::intmax_t)cpp_bin_float::bit_count - + exponent() - 1 - power10; + if (fixed) + break; + roundup = 0; + } else + break; + } while (true); + // + // Check whether we need to round up: note that we could equally round up + // the integer /i/ above, but since we need to perform the rounding *after* + // the conversion to a string and the digit count check, we might as well + // do it here: + // + if ((roundup == 2) || ((roundup == 1) && ((s[s.size() - 1] - '0') & 1))) { + boost::multiprecision::detail::round_string_up_at( + s, static_cast(s.size() - 1), base10_exp); + } - if(sign()) - s.insert(static_cast(0), 1, '-'); + if (sign()) + s.insert(static_cast(0), 1, '-'); - boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, false); - } - else - { - switch(exponent()) - { - case exponent_zero: - s = sign() ? "-0" : f & std::ios_base::showpos ? "+0" : "0"; - boost::multiprecision::detail::format_float_string(s, 0, dig, f, true); - break; - case exponent_nan: - s = "nan"; - break; - case exponent_infinity: - s = sign() ? "-inf" : f & std::ios_base::showpos ? "+inf" : "inf"; - break; - } - } - return s; + boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, + false); + } else { + switch (exponent()) { + case exponent_zero: + s = sign() ? "-0" : f & std::ios_base::showpos ? "+0" : "0"; + boost::multiprecision::detail::format_float_string(s, 0, dig, f, true); + break; + case exponent_nan: + s = "nan"; + break; + case exponent_infinity: + s = sign() ? "-inf" : f & std::ios_base::showpos ? "+inf" : "inf"; + break; + } + } + return s; } #ifdef BOOST_MSVC #pragma warning(pop) #endif -}}} // namespaces +} // namespace backends +} // namespace multiprecision +} // namespace boost #endif - diff --git a/include/boost/multiprecision/cpp_dec_float.hpp b/include/boost/multiprecision/cpp_dec_float.hpp index 113e70f0d..e28625de1 100644 --- a/include/boost/multiprecision/cpp_dec_float.hpp +++ b/include/boost/multiprecision/cpp_dec_float.hpp @@ -5,12 +5,15 @@ // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // This work is based on an earlier work: -// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", -// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function +// Calculations", in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. +// http://doi.acm.org/10.1145/1916461.1916469 // -// Note that there are no "noexcept" specifications on the functions in this file: there are too many -// calls to lexical_cast (and similar) to easily analyse the code for correctness. So until compilers -// can detect noexcept misuse at compile time, the only realistic option is to simply not use it here. +// Note that there are no "noexcept" specifications on the functions in this +// file: there are too many calls to lexical_cast (and similar) to easily +// analyse the code for correctness. So until compilers can detect noexcept +// misuse at compile time, the only realistic option is to simply not use it +// here. // #ifndef BOOST_MP_CPP_DEC_FLOAT_BACKEND_HPP @@ -26,19 +29,20 @@ #endif #include #include -#include #include #include +#include // // Headers required for Boost.Math integration: // #include // -// Some includes we need from Boost.Math, since we rely on that library to provide these functions: +// Some includes we need from Boost.Math, since we rely on that library to +// provide these functions: // -#include #include +#include #include #include #include @@ -46,3113 +50,3675 @@ #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:6326) // comparison of two constants +#pragma warning(disable : 6326) // comparison of two constants #endif -namespace boost{ -namespace multiprecision{ -namespace backends{ +namespace boost { +namespace multiprecision { +namespace backends { -template +template class cpp_dec_float; -} // namespace +} // namespace backends template -struct number_category > : public mpl::int_{}; +struct number_category< + backends::cpp_dec_float> + : public mpl::int_ {}; -namespace backends{ +namespace backends { template -class cpp_dec_float -{ +class cpp_dec_float { private: - static const boost::int32_t cpp_dec_float_digits10_setting = Digits10; + static const boost::int32_t cpp_dec_float_digits10_setting = Digits10; - // We need at least 16-bits in the exponent type to do anything sensible: - BOOST_STATIC_ASSERT_MSG(boost::is_signed::value, "ExponentType must be a signed built in integer type."); - BOOST_STATIC_ASSERT_MSG(sizeof(ExponentType) > 1, "ExponentType is too small."); + // We need at least 16-bits in the exponent type to do anything sensible: + BOOST_STATIC_ASSERT_MSG( + boost::is_signed::value, + "ExponentType must be a signed built in integer type."); + BOOST_STATIC_ASSERT_MSG(sizeof(ExponentType) > 1, + "ExponentType is too small."); public: - typedef mpl::list signed_types; - typedef mpl::list unsigned_types; - typedef mpl::list float_types; - typedef ExponentType exponent_type; - - static const boost::int32_t cpp_dec_float_radix = 10L; - static const boost::int32_t cpp_dec_float_digits10_limit_lo = 9L; - static const boost::int32_t cpp_dec_float_digits10_limit_hi = boost::integer_traits::const_max - 100; - static const boost::int32_t cpp_dec_float_digits10 = ((cpp_dec_float_digits10_setting < cpp_dec_float_digits10_limit_lo) ? cpp_dec_float_digits10_limit_lo : ((cpp_dec_float_digits10_setting > cpp_dec_float_digits10_limit_hi) ? cpp_dec_float_digits10_limit_hi : cpp_dec_float_digits10_setting)); - static const ExponentType cpp_dec_float_max_exp10 = (static_cast(1) << (std::numeric_limits::digits - 5)); - static const ExponentType cpp_dec_float_min_exp10 = -cpp_dec_float_max_exp10; - static const ExponentType cpp_dec_float_max_exp = cpp_dec_float_max_exp10; - static const ExponentType cpp_dec_float_min_exp = cpp_dec_float_min_exp10; - - BOOST_STATIC_ASSERT((cpp_dec_float::cpp_dec_float_max_exp10 == -cpp_dec_float::cpp_dec_float_min_exp10)); + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + typedef ExponentType exponent_type; + + static const boost::int32_t cpp_dec_float_radix = 10L; + static const boost::int32_t cpp_dec_float_digits10_limit_lo = 9L; + static const boost::int32_t cpp_dec_float_digits10_limit_hi = + boost::integer_traits::const_max - 100; + static const boost::int32_t cpp_dec_float_digits10 = + ((cpp_dec_float_digits10_setting < cpp_dec_float_digits10_limit_lo) + ? cpp_dec_float_digits10_limit_lo + : ((cpp_dec_float_digits10_setting > cpp_dec_float_digits10_limit_hi) + ? cpp_dec_float_digits10_limit_hi + : cpp_dec_float_digits10_setting)); + static const ExponentType cpp_dec_float_max_exp10 = + (static_cast(1) + << (std::numeric_limits::digits - 5)); + static const ExponentType cpp_dec_float_min_exp10 = -cpp_dec_float_max_exp10; + static const ExponentType cpp_dec_float_max_exp = cpp_dec_float_max_exp10; + static const ExponentType cpp_dec_float_min_exp = cpp_dec_float_min_exp10; + + BOOST_STATIC_ASSERT((cpp_dec_float::cpp_dec_float_max_exp10 == + -cpp_dec_float::cpp_dec_float_min_exp10)); private: - static const boost::int32_t cpp_dec_float_elem_digits10 = 8L; - static const boost::int32_t cpp_dec_float_elem_mask = 100000000L; - - BOOST_STATIC_ASSERT(0 == cpp_dec_float_max_exp10 % cpp_dec_float_elem_digits10); - - // There are three guard limbs. - // 1) The first limb has 'play' from 1...8 decimal digits. - // 2) The last limb also has 'play' from 1...8 decimal digits. - // 3) One limb can get lost when justifying after multiply, - // as only half of the triangle is multiplied and a carry - // from below is missing. - static const boost::int32_t cpp_dec_float_elem_number_request = static_cast((cpp_dec_float_digits10 / cpp_dec_float_elem_digits10) + (((cpp_dec_float_digits10 % cpp_dec_float_elem_digits10) != 0) ? 1 : 0)); - - // The number of elements needed (with a minimum of two) plus three added guard limbs. - static const boost::int32_t cpp_dec_float_elem_number = static_cast(((cpp_dec_float_elem_number_request < 2L) ? 2L : cpp_dec_float_elem_number_request) + 3L); + static const boost::int32_t cpp_dec_float_elem_digits10 = 8L; + static const boost::int32_t cpp_dec_float_elem_mask = 100000000L; + + BOOST_STATIC_ASSERT(0 == + cpp_dec_float_max_exp10 % cpp_dec_float_elem_digits10); + + // There are three guard limbs. + // 1) The first limb has 'play' from 1...8 decimal digits. + // 2) The last limb also has 'play' from 1...8 decimal digits. + // 3) One limb can get lost when justifying after multiply, + // as only half of the triangle is multiplied and a carry + // from below is missing. + static const boost::int32_t cpp_dec_float_elem_number_request = + static_cast( + (cpp_dec_float_digits10 / cpp_dec_float_elem_digits10) + + (((cpp_dec_float_digits10 % cpp_dec_float_elem_digits10) != 0) ? 1 + : 0)); + + // The number of elements needed (with a minimum of two) plus three added + // guard limbs. + static const boost::int32_t cpp_dec_float_elem_number = + static_cast(((cpp_dec_float_elem_number_request < 2L) + ? 2L + : cpp_dec_float_elem_number_request) + + 3L); public: - static const boost::int32_t cpp_dec_float_total_digits10 = static_cast(cpp_dec_float_elem_number * cpp_dec_float_elem_digits10); + static const boost::int32_t cpp_dec_float_total_digits10 = + static_cast(cpp_dec_float_elem_number * + cpp_dec_float_elem_digits10); private: - - typedef enum enum_fpclass_type - { - cpp_dec_float_finite, - cpp_dec_float_inf, - cpp_dec_float_NaN - } - fpclass_type; + typedef enum enum_fpclass_type { + cpp_dec_float_finite, + cpp_dec_float_inf, + cpp_dec_float_NaN + } fpclass_type; #ifndef BOOST_NO_CXX11_HDR_ARRAY - typedef typename mpl::if_, + typedef typename mpl::if_< + is_void, std::array, - detail::dynamic_array - >::type array_type; + detail::dynamic_array>::type array_type; #else - typedef typename mpl::if_, + typedef typename mpl::if_< + is_void, boost::array, - detail::dynamic_array - >::type array_type; + detail::dynamic_array>::type array_type; #endif - array_type data; - ExponentType exp; - bool neg; - fpclass_type fpclass; - boost::int32_t prec_elem; - - // - // Special values constructor: - // - cpp_dec_float(fpclass_type c) : - data(), - exp (static_cast(0)), - neg (false), - fpclass (c), - prec_elem(cpp_dec_float_elem_number) { } - - // - // Static data initializer: - // - struct initializer - { - initializer() - { - cpp_dec_float::nan(); - cpp_dec_float::inf(); - (cpp_dec_float::min)(); - (cpp_dec_float::max)(); - cpp_dec_float::zero(); - cpp_dec_float::one(); - cpp_dec_float::two(); - cpp_dec_float::half(); - cpp_dec_float::double_min(); - cpp_dec_float::double_max(); - cpp_dec_float::long_double_max(); - cpp_dec_float::long_double_min(); - cpp_dec_float::long_long_max(); - cpp_dec_float::long_long_min(); - cpp_dec_float::ulong_long_max(); - cpp_dec_float::eps(); - cpp_dec_float::pow2(0); - } - void do_nothing(){} - }; - - static initializer init; + array_type data; + ExponentType exp; + bool neg; + fpclass_type fpclass; + boost::int32_t prec_elem; + + // + // Special values constructor: + // + cpp_dec_float(fpclass_type c) + : data(), exp(static_cast(0)), neg(false), fpclass(c), + prec_elem(cpp_dec_float_elem_number) {} + + // + // Static data initializer: + // + struct initializer { + initializer() { + cpp_dec_float::nan(); + cpp_dec_float::inf(); + (cpp_dec_float::min)(); + (cpp_dec_float::max)(); + cpp_dec_float::zero(); + cpp_dec_float::one(); + cpp_dec_float::two(); + cpp_dec_float::half(); + cpp_dec_float::double_min(); + cpp_dec_float::double_max(); + cpp_dec_float::long_double_max(); + cpp_dec_float::long_double_min(); + cpp_dec_float::long_long_max(); + cpp_dec_float::long_long_min(); + cpp_dec_float::ulong_long_max(); + cpp_dec_float::eps(); + cpp_dec_float::pow2(0); + } + void do_nothing() {} + }; + + static initializer init; public: - // Constructors - cpp_dec_float() BOOST_MP_NOEXCEPT_IF(noexcept(array_type())) : - data(), - exp (static_cast(0)), - neg (false), - fpclass (cpp_dec_float_finite), - prec_elem(cpp_dec_float_elem_number) { } - - cpp_dec_float(const char* s) : - data(), - exp (static_cast(0)), - neg (false), - fpclass (cpp_dec_float_finite), - prec_elem(cpp_dec_float_elem_number) - { - *this = s; - } - - template - cpp_dec_float(I i, typename enable_if >::type* = 0) : - data(), - exp (static_cast(0)), - neg (false), - fpclass (cpp_dec_float_finite), - prec_elem(cpp_dec_float_elem_number) - { - from_unsigned_long_long(i); - } - - template - cpp_dec_float(I i, typename enable_if >::type* = 0) : - data(), - exp (static_cast(0)), - neg (false), - fpclass (cpp_dec_float_finite), - prec_elem(cpp_dec_float_elem_number) - { - if(i < 0) - { - from_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(i)); - negate(); - } - else - from_unsigned_long_long(i); - } - - cpp_dec_float(const cpp_dec_float& f) BOOST_MP_NOEXCEPT_IF(noexcept(array_type(std::declval()))) : - data (f.data), - exp (f.exp), - neg (f.neg), - fpclass (f.fpclass), - prec_elem(f.prec_elem) { } - - template - cpp_dec_float(const cpp_dec_float& f, typename enable_if_c::type* = 0) : - data(), - exp (f.exp), - neg (f.neg), - fpclass (static_cast(static_cast(f.fpclass))), - prec_elem(cpp_dec_float_elem_number) - { - std::copy(f.data.begin(), f.data.begin() + f.prec_elem, data.begin()); - } - template - explicit cpp_dec_float(const cpp_dec_float& f, typename disable_if_c::type* = 0) : - data(), - exp (f.exp), - neg (f.neg), - fpclass (static_cast(static_cast(f.fpclass))), - prec_elem(cpp_dec_float_elem_number) - { - // TODO: this doesn't round! - std::copy(f.data.begin(), f.data.begin() + prec_elem, data.begin()); - } - - template - cpp_dec_float(const F val, typename enable_if_c::value + // Constructors + cpp_dec_float() BOOST_MP_NOEXCEPT_IF(noexcept(array_type())) + : data(), exp(static_cast(0)), neg(false), + fpclass(cpp_dec_float_finite), prec_elem(cpp_dec_float_elem_number) {} + + cpp_dec_float(const char *s) + : data(), exp(static_cast(0)), neg(false), + fpclass(cpp_dec_float_finite), prec_elem(cpp_dec_float_elem_number) { + *this = s; + } + + template + cpp_dec_float(I i, typename enable_if>::type * = 0) + : data(), exp(static_cast(0)), neg(false), + fpclass(cpp_dec_float_finite), prec_elem(cpp_dec_float_elem_number) { + from_unsigned_long_long(i); + } + + template + cpp_dec_float(I i, typename enable_if>::type * = 0) + : data(), exp(static_cast(0)), neg(false), + fpclass(cpp_dec_float_finite), prec_elem(cpp_dec_float_elem_number) { + if (i < 0) { + from_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(i)); + negate(); + } else + from_unsigned_long_long(i); + } + + cpp_dec_float(const cpp_dec_float &f) BOOST_MP_NOEXCEPT_IF( + noexcept(array_type(std::declval()))) + : data(f.data), exp(f.exp), neg(f.neg), fpclass(f.fpclass), + prec_elem(f.prec_elem) {} + + template + cpp_dec_float(const cpp_dec_float &f, + typename enable_if_c::type * = 0) + : data(), exp(f.exp), neg(f.neg), + fpclass(static_cast(static_cast(f.fpclass))), + prec_elem(cpp_dec_float_elem_number) { + std::copy(f.data.begin(), f.data.begin() + f.prec_elem, data.begin()); + } + template + explicit cpp_dec_float(const cpp_dec_float &f, + typename disable_if_c::type * = 0) + : data(), exp(f.exp), neg(f.neg), + fpclass(static_cast(static_cast(f.fpclass))), + prec_elem(cpp_dec_float_elem_number) { + // TODO: this doesn't round! + std::copy(f.data.begin(), f.data.begin() + prec_elem, data.begin()); + } + + template + cpp_dec_float(const F val, + typename enable_if_c::value #ifdef BOOST_HAS_FLOAT128 - && !boost::is_same::value + && !boost::is_same::value #endif - >::type* = 0) : - data(), - exp (static_cast(0)), - neg (false), - fpclass (cpp_dec_float_finite), - prec_elem(cpp_dec_float_elem_number) - { - *this = val; - } - - cpp_dec_float(const double mantissa, const ExponentType exponent); - - std::size_t hash()const - { - std::size_t result = 0; - for(int i = 0; i < prec_elem; ++i) - boost::hash_combine(result, data[i]); - boost::hash_combine(result, exp); - boost::hash_combine(result, neg); - boost::hash_combine(result, fpclass); - return result; - } - - // Specific special values. - static const cpp_dec_float& nan() - { - static const cpp_dec_float val(cpp_dec_float_NaN); - init.do_nothing(); - return val; - } - - static const cpp_dec_float& inf() - { - static const cpp_dec_float val(cpp_dec_float_inf); - init.do_nothing(); - return val; - } - - static const cpp_dec_float& (max)() - { - init.do_nothing(); - static cpp_dec_float val_max = std::string("1.0e" + boost::lexical_cast(cpp_dec_float_max_exp10)).c_str(); - return val_max; - } - - static const cpp_dec_float& (min)() - { - init.do_nothing(); - static cpp_dec_float val_min = std::string("1.0e" + boost::lexical_cast(cpp_dec_float_min_exp10)).c_str(); - return val_min; - } - - static const cpp_dec_float& zero() - { - init.do_nothing(); - static cpp_dec_float val(static_cast(0u)); - return val; - } - - static const cpp_dec_float& one() - { - init.do_nothing(); - static cpp_dec_float val(static_cast(1u)); - return val; - } - - static const cpp_dec_float& two() - { - init.do_nothing(); - static cpp_dec_float val(static_cast(2u)); - return val; - } - - static const cpp_dec_float& half() - { - init.do_nothing(); - static cpp_dec_float val(0.5L); - return val; - } - - static const cpp_dec_float& double_min() - { - init.do_nothing(); - static cpp_dec_float val(static_cast((std::numeric_limits::min)())); - return val; - } - - static const cpp_dec_float& double_max() - { - init.do_nothing(); - static cpp_dec_float val(static_cast((std::numeric_limits::max)())); - return val; - } - - static const cpp_dec_float& long_double_min() - { - init.do_nothing(); + >::type * = 0) + : data(), exp(static_cast(0)), neg(false), + fpclass(cpp_dec_float_finite), prec_elem(cpp_dec_float_elem_number) { + *this = val; + } + + cpp_dec_float(const double mantissa, const ExponentType exponent); + + std::size_t hash() const { + std::size_t result = 0; + for (int i = 0; i < prec_elem; ++i) + boost::hash_combine(result, data[i]); + boost::hash_combine(result, exp); + boost::hash_combine(result, neg); + boost::hash_combine(result, fpclass); + return result; + } + + // Specific special values. + static const cpp_dec_float &nan() { + static const cpp_dec_float val(cpp_dec_float_NaN); + init.do_nothing(); + return val; + } + + static const cpp_dec_float &inf() { + static const cpp_dec_float val(cpp_dec_float_inf); + init.do_nothing(); + return val; + } + + static const cpp_dec_float &(max)() { + init.do_nothing(); + static cpp_dec_float val_max = + std::string("1.0e" + + boost::lexical_cast(cpp_dec_float_max_exp10)) + .c_str(); + return val_max; + } + + static const cpp_dec_float &(min)() { + init.do_nothing(); + static cpp_dec_float val_min = + std::string("1.0e" + + boost::lexical_cast(cpp_dec_float_min_exp10)) + .c_str(); + return val_min; + } + + static const cpp_dec_float &zero() { + init.do_nothing(); + static cpp_dec_float val(static_cast(0u)); + return val; + } + + static const cpp_dec_float &one() { + init.do_nothing(); + static cpp_dec_float val(static_cast(1u)); + return val; + } + + static const cpp_dec_float &two() { + init.do_nothing(); + static cpp_dec_float val(static_cast(2u)); + return val; + } + + static const cpp_dec_float &half() { + init.do_nothing(); + static cpp_dec_float val(0.5L); + return val; + } + + static const cpp_dec_float &double_min() { + init.do_nothing(); + static cpp_dec_float val( + static_cast((std::numeric_limits::min)())); + return val; + } + + static const cpp_dec_float &double_max() { + init.do_nothing(); + static cpp_dec_float val( + static_cast((std::numeric_limits::max)())); + return val; + } + + static const cpp_dec_float &long_double_min() { + init.do_nothing(); #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - static cpp_dec_float val(static_cast((std::numeric_limits::min)())); + static cpp_dec_float val( + static_cast((std::numeric_limits::min)())); #else - static cpp_dec_float val((std::numeric_limits::min)()); + static cpp_dec_float val((std::numeric_limits::min)()); #endif - return val; - } + return val; + } - static const cpp_dec_float& long_double_max() - { - init.do_nothing(); + static const cpp_dec_float &long_double_max() { + init.do_nothing(); #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - static cpp_dec_float val(static_cast((std::numeric_limits::max)())); + static cpp_dec_float val( + static_cast((std::numeric_limits::max)())); #else - static cpp_dec_float val((std::numeric_limits::max)()); + static cpp_dec_float val((std::numeric_limits::max)()); #endif - return val; - } - - static const cpp_dec_float& long_long_max() - { - init.do_nothing(); - static cpp_dec_float val((std::numeric_limits::max)()); - return val; - } - - static const cpp_dec_float& long_long_min() - { - init.do_nothing(); - static cpp_dec_float val((std::numeric_limits::min)()); - return val; - } - - static const cpp_dec_float& ulong_long_max() - { - init.do_nothing(); - static cpp_dec_float val((std::numeric_limits::max)()); - return val; - } - - static const cpp_dec_float& eps() - { - init.do_nothing(); - static cpp_dec_float val(1.0, 1 - static_cast(cpp_dec_float_digits10)); - return val; - } - - // Basic operations. - cpp_dec_float& operator=(const cpp_dec_float& v) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval() = std::declval())) - { - data = v.data; - exp = v.exp; - neg = v.neg; - fpclass = v.fpclass; - prec_elem = v.prec_elem; - return *this; - } - - template - cpp_dec_float& operator=(const cpp_dec_float& f) - { - exp = f.exp; - neg = f.neg; - fpclass = static_cast(static_cast(f.fpclass)); - unsigned elems = (std::min)(f.prec_elem, cpp_dec_float_elem_number); - std::copy(f.data.begin(), f.data.begin() + elems, data.begin()); - std::fill(data.begin() + elems, data.end(), 0); - prec_elem = cpp_dec_float_elem_number; - return *this; - } - - cpp_dec_float& operator=(boost::long_long_type v) - { - if(v < 0) - { - from_unsigned_long_long(1u - boost::ulong_long_type(v + 1)); // Avoid undefined behaviour in negation of minimum value for long long - negate(); - } - else - from_unsigned_long_long(v); - return *this; - } - - cpp_dec_float& operator=(boost::ulong_long_type v) - { + return val; + } + + static const cpp_dec_float &long_long_max() { + init.do_nothing(); + static cpp_dec_float val( + (std::numeric_limits::max)()); + return val; + } + + static const cpp_dec_float &long_long_min() { + init.do_nothing(); + static cpp_dec_float val( + (std::numeric_limits::min)()); + return val; + } + + static const cpp_dec_float &ulong_long_max() { + init.do_nothing(); + static cpp_dec_float val( + (std::numeric_limits::max)()); + return val; + } + + static const cpp_dec_float &eps() { + init.do_nothing(); + static cpp_dec_float val(1.0, 1 - static_cast(cpp_dec_float_digits10)); + return val; + } + + // Basic operations. + cpp_dec_float &operator=(const cpp_dec_float &v) + BOOST_MP_NOEXCEPT_IF(noexcept( + std::declval() = std::declval())) { + data = v.data; + exp = v.exp; + neg = v.neg; + fpclass = v.fpclass; + prec_elem = v.prec_elem; + return *this; + } + + template cpp_dec_float &operator=(const cpp_dec_float &f) { + exp = f.exp; + neg = f.neg; + fpclass = static_cast(static_cast(f.fpclass)); + unsigned elems = (std::min)(f.prec_elem, cpp_dec_float_elem_number); + std::copy(f.data.begin(), f.data.begin() + elems, data.begin()); + std::fill(data.begin() + elems, data.end(), 0); + prec_elem = cpp_dec_float_elem_number; + return *this; + } + + cpp_dec_float &operator=(boost::long_long_type v) { + if (v < 0) { + from_unsigned_long_long( + 1u - boost::ulong_long_type( + v + 1)); // Avoid undefined behaviour in negation of minimum + // value for long long + negate(); + } else from_unsigned_long_long(v); - return *this; - } - - cpp_dec_float& operator=(long double v); - - cpp_dec_float& operator=(const char* v) - { - rd_string(v); - return *this; - } - - cpp_dec_float& operator+=(const cpp_dec_float& v); - cpp_dec_float& operator-=(const cpp_dec_float& v); - cpp_dec_float& operator*=(const cpp_dec_float& v); - cpp_dec_float& operator/=(const cpp_dec_float& v); - - cpp_dec_float& add_unsigned_long_long(const boost::ulong_long_type n) - { - cpp_dec_float t; - t.from_unsigned_long_long(n); - return *this += t; - } - - cpp_dec_float& sub_unsigned_long_long(const boost::ulong_long_type n) - { - cpp_dec_float t; - t.from_unsigned_long_long(n); - return *this -= t; - } - - cpp_dec_float& mul_unsigned_long_long(const boost::ulong_long_type n); - cpp_dec_float& div_unsigned_long_long(const boost::ulong_long_type n); - - // Elementary primitives. - cpp_dec_float& calculate_inv (); - cpp_dec_float& calculate_sqrt(); - - void negate() - { - if(!iszero()) - neg = !neg; - } - - // Comparison functions - bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (fpclass == cpp_dec_float_NaN); } - bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (fpclass == cpp_dec_float_inf); } - bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (fpclass == cpp_dec_float_finite); } - - bool iszero () const - { - return ((fpclass == cpp_dec_float_finite) && (data[0u] == 0u)); - } - - bool isone () const; - bool isint () const; - bool isneg () const { return neg; } - - // Operators pre-increment and pre-decrement - cpp_dec_float& operator++() - { - return *this += one(); - } - - cpp_dec_float& operator--() - { - return *this -= one(); - } - - std::string str(boost::intmax_t digits, std::ios_base::fmtflags f)const; - - int compare(const cpp_dec_float& v)const; - - template - int compare(const V& v)const - { - cpp_dec_float t; - t = v; - return compare(t); - } - - void swap(cpp_dec_float& v) - { - data.swap(v.data); - std::swap(exp, v.exp); - std::swap(neg, v.neg); - std::swap(fpclass, v.fpclass); - std::swap(prec_elem, v.prec_elem); - } - - double extract_double() const; - long double extract_long_double() const; - boost::long_long_type extract_signed_long_long() const; - boost::ulong_long_type extract_unsigned_long_long() const; - void extract_parts(double& mantissa, ExponentType& exponent) const; - cpp_dec_float extract_integer_part() const; - - void precision(const boost::int32_t prec_digits) - { - if(prec_digits >= cpp_dec_float_total_digits10) - { - prec_elem = cpp_dec_float_elem_number; - } - else - { - const boost::int32_t elems = static_cast( static_cast( (prec_digits + (cpp_dec_float_elem_digits10 / 2)) / cpp_dec_float_elem_digits10) - + static_cast(((prec_digits % cpp_dec_float_elem_digits10) != 0) ? 1 : 0)); - - prec_elem = (std::min)(cpp_dec_float_elem_number, (std::max)(elems, static_cast(2))); - } - } - static cpp_dec_float pow2(boost::long_long_type i); - ExponentType order()const - { - const bool bo_order_is_zero = ((!(isfinite)()) || (data[0] == static_cast(0u))); - // - // Binary search to find the order of the leading term: - // - ExponentType prefix = 0; - - if(data[0] >= 100000UL) - { - if(data[0] >= 10000000UL) - { - if(data[0] >= 100000000UL) - { - if(data[0] >= 1000000000UL) - prefix = 9; - else - prefix = 8; - } - else - prefix = 7; - } - else - { - if(data[0] >= 1000000UL) - prefix = 6; - else - prefix = 5; - } + return *this; + } + + cpp_dec_float &operator=(boost::ulong_long_type v) { + from_unsigned_long_long(v); + return *this; + } + + cpp_dec_float &operator=(long double v); + + cpp_dec_float &operator=(const char *v) { + rd_string(v); + return *this; + } + + cpp_dec_float &operator+=(const cpp_dec_float &v); + cpp_dec_float &operator-=(const cpp_dec_float &v); + cpp_dec_float &operator*=(const cpp_dec_float &v); + cpp_dec_float &operator/=(const cpp_dec_float &v); + + cpp_dec_float &add_unsigned_long_long(const boost::ulong_long_type n) { + cpp_dec_float t; + t.from_unsigned_long_long(n); + return *this += t; + } + + cpp_dec_float &sub_unsigned_long_long(const boost::ulong_long_type n) { + cpp_dec_float t; + t.from_unsigned_long_long(n); + return *this -= t; + } + + cpp_dec_float &mul_unsigned_long_long(const boost::ulong_long_type n); + cpp_dec_float &div_unsigned_long_long(const boost::ulong_long_type n); + + // Elementary primitives. + cpp_dec_float &calculate_inv(); + cpp_dec_float &calculate_sqrt(); + + void negate() { + if (!iszero()) + neg = !neg; + } + + // Comparison functions + bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION() const { + return (fpclass == cpp_dec_float_NaN); + } + bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION() const { + return (fpclass == cpp_dec_float_inf); + } + bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION() const { + return (fpclass == cpp_dec_float_finite); + } + + bool iszero() const { + return ((fpclass == cpp_dec_float_finite) && (data[0u] == 0u)); + } + + bool isone() const; + bool isint() const; + bool isneg() const { return neg; } + + // Operators pre-increment and pre-decrement + cpp_dec_float &operator++() { return *this += one(); } + + cpp_dec_float &operator--() { return *this -= one(); } + + std::string str(boost::intmax_t digits, std::ios_base::fmtflags f) const; + + int compare(const cpp_dec_float &v) const; + + template int compare(const V &v) const { + cpp_dec_float t; + t = v; + return compare(t); + } + + void swap(cpp_dec_float &v) { + data.swap(v.data); + std::swap(exp, v.exp); + std::swap(neg, v.neg); + std::swap(fpclass, v.fpclass); + std::swap(prec_elem, v.prec_elem); + } + + double extract_double() const; + long double extract_long_double() const; + boost::long_long_type extract_signed_long_long() const; + boost::ulong_long_type extract_unsigned_long_long() const; + void extract_parts(double &mantissa, ExponentType &exponent) const; + cpp_dec_float extract_integer_part() const; + + void precision(const boost::int32_t prec_digits) { + if (prec_digits >= cpp_dec_float_total_digits10) { + prec_elem = cpp_dec_float_elem_number; + } else { + const boost::int32_t elems = static_cast( + static_cast( + (prec_digits + (cpp_dec_float_elem_digits10 / 2)) / + cpp_dec_float_elem_digits10) + + static_cast( + ((prec_digits % cpp_dec_float_elem_digits10) != 0) ? 1 : 0)); + + prec_elem = (std::min)(cpp_dec_float_elem_number, + (std::max)(elems, static_cast(2))); + } + } + static cpp_dec_float pow2(boost::long_long_type i); + ExponentType order() const { + const bool bo_order_is_zero = + ((!(isfinite)()) || (data[0] == static_cast(0u))); + // + // Binary search to find the order of the leading term: + // + ExponentType prefix = 0; + + if (data[0] >= 100000UL) { + if (data[0] >= 10000000UL) { + if (data[0] >= 100000000UL) { + if (data[0] >= 1000000000UL) + prefix = 9; + else + prefix = 8; + } else + prefix = 7; + } else { + if (data[0] >= 1000000UL) + prefix = 6; + else + prefix = 5; } - else - { - if(data[0] >= 1000UL) - { - if(data[0] >= 10000UL) - prefix = 4; - else - prefix = 3; - } - else - { - if(data[0] >= 100) - prefix = 2; - else if(data[0] >= 10) - prefix = 1; - } + } else { + if (data[0] >= 1000UL) { + if (data[0] >= 10000UL) + prefix = 4; + else + prefix = 3; + } else { + if (data[0] >= 100) + prefix = 2; + else if (data[0] >= 10) + prefix = 1; } - - return (bo_order_is_zero ? static_cast(0) : static_cast(exp + prefix)); - } - - template - void serialize(Archive & ar, const unsigned int /*version*/) - { - for(unsigned i = 0; i < data.size(); ++i) - ar & boost::serialization::make_nvp("digit", data[i]); - ar & boost::serialization::make_nvp("exponent", exp); - ar & boost::serialization::make_nvp("sign", neg); - ar & boost::serialization::make_nvp("class-type", fpclass); - ar & boost::serialization::make_nvp("precision", prec_elem); - } + } + + return (bo_order_is_zero ? static_cast(0) + : static_cast(exp + prefix)); + } + + template + void serialize(Archive &ar, const unsigned int /*version*/) { + for (unsigned i = 0; i < data.size(); ++i) + ar &boost::serialization::make_nvp("digit", data[i]); + ar &boost::serialization::make_nvp("exponent", exp); + ar &boost::serialization::make_nvp("sign", neg); + ar &boost::serialization::make_nvp("class-type", fpclass); + ar &boost::serialization::make_nvp("precision", prec_elem); + } private: - static bool data_elem_is_non_zero_predicate(const boost::uint32_t& d) { return (d != static_cast(0u)); } - static bool data_elem_is_non_nine_predicate(const boost::uint32_t& d) { return (d != static_cast(cpp_dec_float::cpp_dec_float_elem_mask - 1)); } - static bool char_is_nonzero_predicate(const char& c) { return (c != static_cast('0')); } - - void from_unsigned_long_long(const boost::ulong_long_type u); - - int cmp_data(const array_type& vd) const; - - - static boost::uint32_t mul_loop_uv(boost::uint32_t* const u, const boost::uint32_t* const v, const boost::int32_t p); - static boost::uint32_t mul_loop_n (boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p); - static boost::uint32_t div_loop_n (boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p); - - bool rd_string(const char* const s); - - template - friend class cpp_dec_float; + static bool data_elem_is_non_zero_predicate(const boost::uint32_t &d) { + return (d != static_cast(0u)); + } + static bool data_elem_is_non_nine_predicate(const boost::uint32_t &d) { + return (d != static_cast( + cpp_dec_float::cpp_dec_float_elem_mask - 1)); + } + static bool char_is_nonzero_predicate(const char &c) { + return (c != static_cast('0')); + } + + void from_unsigned_long_long(const boost::ulong_long_type u); + + int cmp_data(const array_type &vd) const; + + static boost::uint32_t mul_loop_uv(boost::uint32_t *const u, + const boost::uint32_t *const v, + const boost::int32_t p); + static boost::uint32_t mul_loop_n(boost::uint32_t *const u, boost::uint32_t n, + const boost::int32_t p); + static boost::uint32_t div_loop_n(boost::uint32_t *const u, boost::uint32_t n, + const boost::int32_t p); + + bool rd_string(const char *const s); + + template friend class cpp_dec_float; }; template -typename cpp_dec_float::initializer cpp_dec_float::init; +typename cpp_dec_float::initializer + cpp_dec_float::init; template -const boost::int32_t cpp_dec_float::cpp_dec_float_radix; +const boost::int32_t + cpp_dec_float::cpp_dec_float_radix; template -const boost::int32_t cpp_dec_float::cpp_dec_float_digits10_setting; +const boost::int32_t cpp_dec_float::cpp_dec_float_digits10_setting; template -const boost::int32_t cpp_dec_float::cpp_dec_float_digits10_limit_lo; +const boost::int32_t cpp_dec_float::cpp_dec_float_digits10_limit_lo; template -const boost::int32_t cpp_dec_float::cpp_dec_float_digits10_limit_hi; +const boost::int32_t cpp_dec_float::cpp_dec_float_digits10_limit_hi; template -const boost::int32_t cpp_dec_float::cpp_dec_float_digits10; +const boost::int32_t + cpp_dec_float::cpp_dec_float_digits10; template -const ExponentType cpp_dec_float::cpp_dec_float_max_exp; +const ExponentType + cpp_dec_float::cpp_dec_float_max_exp; template -const ExponentType cpp_dec_float::cpp_dec_float_min_exp; +const ExponentType + cpp_dec_float::cpp_dec_float_min_exp; template -const ExponentType cpp_dec_float::cpp_dec_float_max_exp10; +const ExponentType + cpp_dec_float::cpp_dec_float_max_exp10; template -const ExponentType cpp_dec_float::cpp_dec_float_min_exp10; +const ExponentType + cpp_dec_float::cpp_dec_float_min_exp10; template -const boost::int32_t cpp_dec_float::cpp_dec_float_elem_digits10; +const boost::int32_t cpp_dec_float::cpp_dec_float_elem_digits10; template -const boost::int32_t cpp_dec_float::cpp_dec_float_elem_number_request; +const boost::int32_t cpp_dec_float< + Digits10, ExponentType, Allocator>::cpp_dec_float_elem_number_request; template -const boost::int32_t cpp_dec_float::cpp_dec_float_elem_number; +const boost::int32_t + cpp_dec_float::cpp_dec_float_elem_number; template -const boost::int32_t cpp_dec_float::cpp_dec_float_elem_mask; +const boost::int32_t + cpp_dec_float::cpp_dec_float_elem_mask; template -cpp_dec_float& cpp_dec_float::operator+=(const cpp_dec_float& v) -{ - if((isnan)()) - { - return *this; - } - - if((isinf)()) - { - if((v.isinf)() && (isneg() != v.isneg())) - { - *this = nan(); - } - return *this; - } +cpp_dec_float & +cpp_dec_float:: +operator+=(const cpp_dec_float &v) { + if ((isnan)()) { + return *this; + } - if(iszero()) - { - return operator=(v); - } - - if((v.isnan)() || (v.isinf)()) - { - *this = v; - return *this; - } - - // Get the offset for the add/sub operation. - static const ExponentType max_delta_exp = static_cast((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10); - - const ExponentType ofs_exp = static_cast(exp - v.exp); - - // Check if the operation is out of range, requiring special handling. - if(v.iszero() || (ofs_exp > max_delta_exp)) - { - // Result is *this unchanged since v is negligible compared to *this. - return *this; - } - else if(ofs_exp < -max_delta_exp) - { - // Result is *this = v since *this is negligible compared to v. - return operator=(v); - } - - // Do the add/sub operation. - - typename array_type::iterator p_u = data.begin(); - typename array_type::const_iterator p_v = v.data.begin(); - bool b_copy = false; - const boost::int32_t ofs = static_cast(static_cast(ofs_exp) / cpp_dec_float_elem_digits10); - array_type n_data; - - if(neg == v.neg) - { - // Add v to *this, where the data array of either *this or v - // might have to be treated with a positive, negative or zero offset. - // The result is stored in *this. The data are added one element - // at a time, each element with carry. - if(ofs >= static_cast(0)) - { - std::copy(v.data.begin(), v.data.end() - static_cast(ofs), n_data.begin() + static_cast(ofs)); - std::fill(n_data.begin(), n_data.begin() + static_cast(ofs), static_cast(0u)); - p_v = n_data.begin(); - } - else - { - std::copy(data.begin(), data.end() - static_cast(-ofs), n_data.begin() + static_cast(-ofs)); - std::fill(n_data.begin(), n_data.begin() + static_cast(-ofs), static_cast(0u)); - p_u = n_data.begin(); - b_copy = true; - } - - // Addition algorithm - boost::uint32_t carry = static_cast(0u); - - for(boost::int32_t j = static_cast(cpp_dec_float_elem_number - static_cast(1)); j >= static_cast(0); j--) - { - boost::uint32_t t = static_cast(static_cast(p_u[j] + p_v[j]) + carry); - carry = t / static_cast(cpp_dec_float_elem_mask); - p_u[j] = static_cast(t - static_cast(carry * static_cast(cpp_dec_float_elem_mask))); - } - - if(b_copy) - { - data = n_data; - exp = v.exp; - } + if ((isinf)()) { + if ((v.isinf)() && (isneg() != v.isneg())) { + *this = nan(); + } + return *this; + } + + if (iszero()) { + return operator=(v); + } + + if ((v.isnan)() || (v.isinf)()) { + *this = v; + return *this; + } + + // Get the offset for the add/sub operation. + static const ExponentType max_delta_exp = static_cast( + (cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10); + + const ExponentType ofs_exp = static_cast(exp - v.exp); + + // Check if the operation is out of range, requiring special handling. + if (v.iszero() || (ofs_exp > max_delta_exp)) { + // Result is *this unchanged since v is negligible compared to *this. + return *this; + } else if (ofs_exp < -max_delta_exp) { + // Result is *this = v since *this is negligible compared to v. + return operator=(v); + } + + // Do the add/sub operation. + + typename array_type::iterator p_u = data.begin(); + typename array_type::const_iterator p_v = v.data.begin(); + bool b_copy = false; + const boost::int32_t ofs = static_cast( + static_cast(ofs_exp) / cpp_dec_float_elem_digits10); + array_type n_data; + + if (neg == v.neg) { + // Add v to *this, where the data array of either *this or v + // might have to be treated with a positive, negative or zero offset. + // The result is stored in *this. The data are added one element + // at a time, each element with carry. + if (ofs >= static_cast(0)) { + std::copy(v.data.begin(), v.data.end() - static_cast(ofs), + n_data.begin() + static_cast(ofs)); + std::fill(n_data.begin(), n_data.begin() + static_cast(ofs), + static_cast(0u)); + p_v = n_data.begin(); + } else { + std::copy(data.begin(), data.end() - static_cast(-ofs), + n_data.begin() + static_cast(-ofs)); + std::fill(n_data.begin(), n_data.begin() + static_cast(-ofs), + static_cast(0u)); + p_u = n_data.begin(); + b_copy = true; + } + + // Addition algorithm + boost::uint32_t carry = static_cast(0u); + + for (boost::int32_t j = static_cast( + cpp_dec_float_elem_number - static_cast(1)); + j >= static_cast(0); j--) { + boost::uint32_t t = static_cast( + static_cast(p_u[j] + p_v[j]) + carry); + carry = t / static_cast(cpp_dec_float_elem_mask); + p_u[j] = static_cast( + t - + static_cast( + carry * static_cast(cpp_dec_float_elem_mask))); + } + + if (b_copy) { + data = n_data; + exp = v.exp; + } - // There needs to be a carry into the element -1 of the array data - if(carry != static_cast(0u)) - { - std::copy_backward(data.begin(), data.end() - static_cast(1u), data.end()); - data[0] = carry; - exp += static_cast(cpp_dec_float_elem_digits10); - } - } - else - { - // Subtract v from *this, where the data array of either *this or v - // might have to be treated with a positive, negative or zero offset. - if((ofs > static_cast(0)) - || ( (ofs == static_cast(0)) - && (cmp_data(v.data) > static_cast(0))) - ) - { - // In this case, |u| > |v| and ofs is positive. - // Copy the data of v, shifted down to a lower value - // into the data array m_n. Set the operand pointer p_v - // to point to the copied, shifted data m_n. - std::copy(v.data.begin(), v.data.end() - static_cast(ofs), n_data.begin() + static_cast(ofs)); - std::fill(n_data.begin(), n_data.begin() + static_cast(ofs), static_cast(0u)); - p_v = n_data.begin(); - } - else - { - if(ofs != static_cast(0)) - { - // In this case, |u| < |v| and ofs is negative. - // Shift the data of u down to a lower value. - std::copy_backward(data.begin(), data.end() - static_cast(-ofs), data.end()); - std::fill(data.begin(), data.begin() + static_cast(-ofs), static_cast(0u)); - } - - // Copy the data of v into the data array n_data. - // Set the u-pointer p_u to point to m_n and the - // operand pointer p_v to point to the shifted - // data m_data. - n_data = v.data; - p_u = n_data.begin(); - p_v = data.begin(); - b_copy = true; + // There needs to be a carry into the element -1 of the array data + if (carry != static_cast(0u)) { + std::copy_backward(data.begin(), + data.end() - static_cast(1u), data.end()); + data[0] = carry; + exp += static_cast(cpp_dec_float_elem_digits10); + } + } else { + // Subtract v from *this, where the data array of either *this or v + // might have to be treated with a positive, negative or zero offset. + if ((ofs > static_cast(0)) || + ((ofs == static_cast(0)) && + (cmp_data(v.data) > static_cast(0)))) { + // In this case, |u| > |v| and ofs is positive. + // Copy the data of v, shifted down to a lower value + // into the data array m_n. Set the operand pointer p_v + // to point to the copied, shifted data m_n. + std::copy(v.data.begin(), v.data.end() - static_cast(ofs), + n_data.begin() + static_cast(ofs)); + std::fill(n_data.begin(), n_data.begin() + static_cast(ofs), + static_cast(0u)); + p_v = n_data.begin(); + } else { + if (ofs != static_cast(0)) { + // In this case, |u| < |v| and ofs is negative. + // Shift the data of u down to a lower value. + std::copy_backward(data.begin(), data.end() - static_cast(-ofs), + data.end()); + std::fill(data.begin(), data.begin() + static_cast(-ofs), + static_cast(0u)); } - boost::int32_t j; - - // Subtraction algorithm - boost::int32_t borrow = static_cast(0); - - for(j = static_cast(cpp_dec_float_elem_number - static_cast(1)); j >= static_cast(0); j--) - { - boost::int32_t t = static_cast(static_cast( static_cast(p_u[j]) - - static_cast(p_v[j])) - borrow); - - // Underflow? Borrow? - if(t < static_cast(0)) - { - // Yes, underflow and borrow - t += static_cast(cpp_dec_float_elem_mask); - borrow = static_cast(1); - } - else - { - borrow = static_cast(0); - } - - p_u[j] = static_cast(static_cast(t) % static_cast(cpp_dec_float_elem_mask)); + // Copy the data of v into the data array n_data. + // Set the u-pointer p_u to point to m_n and the + // operand pointer p_v to point to the shifted + // data m_data. + n_data = v.data; + p_u = n_data.begin(); + p_v = data.begin(); + b_copy = true; + } + + boost::int32_t j; + + // Subtraction algorithm + boost::int32_t borrow = static_cast(0); + + for (j = static_cast(cpp_dec_float_elem_number - + static_cast(1)); + j >= static_cast(0); j--) { + boost::int32_t t = static_cast( + static_cast(static_cast(p_u[j]) - + static_cast(p_v[j])) - + borrow); + + // Underflow? Borrow? + if (t < static_cast(0)) { + // Yes, underflow and borrow + t += static_cast(cpp_dec_float_elem_mask); + borrow = static_cast(1); + } else { + borrow = static_cast(0); } - if(b_copy) - { - data = n_data; - exp = v.exp; - neg = v.neg; - } + p_u[j] = static_cast( + static_cast(t) % + static_cast(cpp_dec_float_elem_mask)); + } - // Is it necessary to justify the data? - const typename array_type::const_iterator first_nonzero_elem = std::find_if(data.begin(), data.end(), data_elem_is_non_zero_predicate); - - if(first_nonzero_elem != data.begin()) - { - if(first_nonzero_elem == data.end()) - { - // This result of the subtraction is exactly zero. - // Reset the sign and the exponent. - neg = false; - exp = static_cast(0); - } - else - { - // Justify the data - const std::size_t sj = static_cast(std::distance(data.begin(), first_nonzero_elem)); - - std::copy(data.begin() + static_cast(sj), data.end(), data.begin()); - std::fill(data.end() - sj, data.end(), static_cast(0u)); - - exp -= static_cast(sj * static_cast(cpp_dec_float_elem_digits10)); - } + if (b_copy) { + data = n_data; + exp = v.exp; + neg = v.neg; + } + + // Is it necessary to justify the data? + const typename array_type::const_iterator first_nonzero_elem = + std::find_if(data.begin(), data.end(), data_elem_is_non_zero_predicate); + + if (first_nonzero_elem != data.begin()) { + if (first_nonzero_elem == data.end()) { + // This result of the subtraction is exactly zero. + // Reset the sign and the exponent. + neg = false; + exp = static_cast(0); + } else { + // Justify the data + const std::size_t sj = static_cast( + std::distance( + data.begin(), first_nonzero_elem)); + + std::copy(data.begin() + static_cast(sj), data.end(), + data.begin()); + std::fill(data.end() - sj, data.end(), + static_cast(0u)); + + exp -= static_cast( + sj * static_cast(cpp_dec_float_elem_digits10)); } - } + } + } - // Handle underflow. - if(iszero()) - return (*this = zero()); + // Handle underflow. + if (iszero()) + return (*this = zero()); - // Check for potential overflow. - const bool b_result_might_overflow = (exp >= static_cast(cpp_dec_float_max_exp10)); + // Check for potential overflow. + const bool b_result_might_overflow = + (exp >= static_cast(cpp_dec_float_max_exp10)); - // Handle overflow. - if(b_result_might_overflow) - { - const bool b_result_is_neg = neg; - neg = false; + // Handle overflow. + if (b_result_might_overflow) { + const bool b_result_is_neg = neg; + neg = false; - if(compare((cpp_dec_float::max)()) > 0) - *this = inf(); + if (compare((cpp_dec_float::max)()) > 0) + *this = inf(); - neg = b_result_is_neg; - } + neg = b_result_is_neg; + } - return *this; + return *this; } template -cpp_dec_float& cpp_dec_float::operator-=(const cpp_dec_float& v) -{ - // Use *this - v = -(-*this + v). - negate(); - *this += v; - negate(); - return *this; +cpp_dec_float & +cpp_dec_float:: +operator-=(const cpp_dec_float &v) { + // Use *this - v = -(-*this + v). + negate(); + *this += v; + negate(); + return *this; } template -cpp_dec_float& cpp_dec_float::operator*=(const cpp_dec_float& v) -{ - // Evaluate the sign of the result. - const bool b_result_is_neg = (neg != v.neg); +cpp_dec_float & +cpp_dec_float:: +operator*=(const cpp_dec_float &v) { + // Evaluate the sign of the result. + const bool b_result_is_neg = (neg != v.neg); - // Artificially set the sign of the result to be positive. - neg = false; + // Artificially set the sign of the result to be positive. + neg = false; - // Handle special cases like zero, inf and NaN. - const bool b_u_is_inf = (isinf)(); - const bool b_v_is_inf = (v.isinf)(); - const bool b_u_is_zero = iszero(); - const bool b_v_is_zero = v.iszero(); + // Handle special cases like zero, inf and NaN. + const bool b_u_is_inf = (isinf)(); + const bool b_v_is_inf = (v.isinf)(); + const bool b_u_is_zero = iszero(); + const bool b_v_is_zero = v.iszero(); - if( ((isnan)() || (v.isnan)()) - || (b_u_is_inf && b_v_is_zero) - || (b_v_is_inf && b_u_is_zero) - ) - { - *this = nan(); - return *this; - } + if (((isnan)() || (v.isnan)()) || (b_u_is_inf && b_v_is_zero) || + (b_v_is_inf && b_u_is_zero)) { + *this = nan(); + return *this; + } - if(b_u_is_inf || b_v_is_inf) - { - *this = inf(); - if(b_result_is_neg) - negate(); - return *this; - } + if (b_u_is_inf || b_v_is_inf) { + *this = inf(); + if (b_result_is_neg) + negate(); + return *this; + } - if(b_u_is_zero || b_v_is_zero) - { - return *this = zero(); - } + if (b_u_is_zero || b_v_is_zero) { + return *this = zero(); + } - // Check for potential overflow or underflow. - const bool b_result_might_overflow = ((exp + v.exp) >= static_cast(cpp_dec_float_max_exp10)); - const bool b_result_might_underflow = ((exp + v.exp) <= static_cast(cpp_dec_float_min_exp10)); + // Check for potential overflow or underflow. + const bool b_result_might_overflow = + ((exp + v.exp) >= static_cast(cpp_dec_float_max_exp10)); + const bool b_result_might_underflow = + ((exp + v.exp) <= static_cast(cpp_dec_float_min_exp10)); - // Set the exponent of the result. - exp += v.exp; + // Set the exponent of the result. + exp += v.exp; - const boost::int32_t prec_mul = (std::min)(prec_elem, v.prec_elem); + const boost::int32_t prec_mul = (std::min)(prec_elem, v.prec_elem); - const boost::uint32_t carry = mul_loop_uv(data.data(), v.data.data(), prec_mul); + const boost::uint32_t carry = + mul_loop_uv(data.data(), v.data.data(), prec_mul); - // Handle a potential carry. - if(carry != static_cast(0u)) - { - exp += cpp_dec_float_elem_digits10; + // Handle a potential carry. + if (carry != static_cast(0u)) { + exp += cpp_dec_float_elem_digits10; - // Shift the result of the multiplication one element to the right... - std::copy_backward(data.begin(), - data.begin() + static_cast(prec_elem - static_cast(1)), - data.begin() + static_cast(prec_elem)); + // Shift the result of the multiplication one element to the right... + std::copy_backward( + data.begin(), + data.begin() + static_cast(prec_elem - + static_cast(1)), + data.begin() + static_cast(prec_elem)); - // ... And insert the carry. - data.front() = carry; - } + // ... And insert the carry. + data.front() = carry; + } - // Handle overflow. - if(b_result_might_overflow && (compare((cpp_dec_float::max)()) > 0)) - { - *this = inf(); - } + // Handle overflow. + if (b_result_might_overflow && (compare((cpp_dec_float::max)()) > 0)) { + *this = inf(); + } - // Handle underflow. - if(b_result_might_underflow && (compare((cpp_dec_float::min)()) < 0)) - { - *this = zero(); + // Handle underflow. + if (b_result_might_underflow && (compare((cpp_dec_float::min)()) < 0)) { + *this = zero(); - return *this; - } + return *this; + } - // Set the sign of the result. - neg = b_result_is_neg; + // Set the sign of the result. + neg = b_result_is_neg; - return *this; + return *this; } template -cpp_dec_float& cpp_dec_float::operator/=(const cpp_dec_float& v) -{ - if(iszero()) - { - if((v.isnan)()) - { - return *this = v; - } - else if(v.iszero()) - { - return *this = nan(); - } - } - - const bool u_and_v_are_finite_and_identical = ( (isfinite)() - && (fpclass == v.fpclass) - && (exp == v.exp) - && (cmp_data(v.data) == static_cast(0))); - - if(u_and_v_are_finite_and_identical) - { - if(neg != v.neg) - { - *this = one(); - negate(); - } - else - *this = one(); - return *this; - } - else - { - cpp_dec_float t(v); - t.calculate_inv(); - return operator*=(t); - } +cpp_dec_float & +cpp_dec_float:: +operator/=(const cpp_dec_float &v) { + if (iszero()) { + if ((v.isnan)()) { + return *this = v; + } else if (v.iszero()) { + return *this = nan(); + } + } + + const bool u_and_v_are_finite_and_identical = + ((isfinite)() && (fpclass == v.fpclass) && (exp == v.exp) && + (cmp_data(v.data) == static_cast(0))); + + if (u_and_v_are_finite_and_identical) { + if (neg != v.neg) { + *this = one(); + negate(); + } else + *this = one(); + return *this; + } else { + cpp_dec_float t(v); + t.calculate_inv(); + return operator*=(t); + } } template -cpp_dec_float& cpp_dec_float::mul_unsigned_long_long(const boost::ulong_long_type n) -{ - // Multiply *this with a constant boost::ulong_long_type. - - // Evaluate the sign of the result. - const bool b_neg = neg; - - // Artificially set the sign of the result to be positive. - neg = false; - - // Handle special cases like zero, inf and NaN. - const bool b_u_is_inf = (isinf)(); - const bool b_n_is_zero = (n == static_cast(0)); - - if((isnan)() || (b_u_is_inf && b_n_is_zero)) - { - return (*this = nan()); - } - - if(b_u_is_inf) - { - *this = inf(); - if(b_neg) - negate(); - return *this; - } - - if(iszero() || b_n_is_zero) - { - // Multiplication by zero. - return *this = zero(); - } - - if(n >= static_cast(cpp_dec_float_elem_mask)) - { - neg = b_neg; - cpp_dec_float t; - t = n; - return operator*=(t); - } - - if(n == static_cast(1u)) - { - neg = b_neg; - return *this; - } - - // Set up the multiplication loop. - const boost::uint32_t nn = static_cast(n); - const boost::uint32_t carry = mul_loop_n(data.data(), nn, prec_elem); +cpp_dec_float & +cpp_dec_float::mul_unsigned_long_long( + const boost::ulong_long_type n) { + // Multiply *this with a constant boost::ulong_long_type. - // Handle the carry and adjust the exponent. - if(carry != static_cast(0u)) - { - exp += static_cast(cpp_dec_float_elem_digits10); + // Evaluate the sign of the result. + const bool b_neg = neg; - // Shift the result of the multiplication one element to the right. - std::copy_backward(data.begin(), - data.begin() + static_cast(prec_elem - static_cast(1)), - data.begin() + static_cast(prec_elem)); + // Artificially set the sign of the result to be positive. + neg = false; - data.front() = static_cast(carry); - } + // Handle special cases like zero, inf and NaN. + const bool b_u_is_inf = (isinf)(); + const bool b_n_is_zero = (n == static_cast(0)); - // Check for potential overflow. - const bool b_result_might_overflow = (exp >= cpp_dec_float_max_exp10); + if ((isnan)() || (b_u_is_inf && b_n_is_zero)) { + return (*this = nan()); + } - // Handle overflow. - if(b_result_might_overflow && (compare((cpp_dec_float::max)()) > 0)) - { - *this = inf(); - } + if (b_u_is_inf) { + *this = inf(); + if (b_neg) + negate(); + return *this; + } - // Set the sign. - neg = b_neg; + if (iszero() || b_n_is_zero) { + // Multiplication by zero. + return *this = zero(); + } - return *this; -} + if (n >= static_cast(cpp_dec_float_elem_mask)) { + neg = b_neg; + cpp_dec_float t; + t = n; + return operator*=(t); + } -template -cpp_dec_float& cpp_dec_float::div_unsigned_long_long(const boost::ulong_long_type n) -{ - // Divide *this by a constant boost::ulong_long_type. + if (n == static_cast(1u)) { + neg = b_neg; + return *this; + } - // Evaluate the sign of the result. - const bool b_neg = neg; + // Set up the multiplication loop. + const boost::uint32_t nn = static_cast(n); + const boost::uint32_t carry = mul_loop_n(data.data(), nn, prec_elem); - // Artificially set the sign of the result to be positive. - neg = false; + // Handle the carry and adjust the exponent. + if (carry != static_cast(0u)) { + exp += static_cast(cpp_dec_float_elem_digits10); - // Handle special cases like zero, inf and NaN. - if((isnan)()) - { - return *this; - } + // Shift the result of the multiplication one element to the right. + std::copy_backward( + data.begin(), + data.begin() + static_cast(prec_elem - + static_cast(1)), + data.begin() + static_cast(prec_elem)); - if((isinf)()) - { - *this = inf(); - if(b_neg) - negate(); - return *this; - } - - if(n == static_cast(0u)) - { - // Divide by 0. - if(iszero()) - { - *this = nan(); - return *this; - } - else - { - *this = inf(); - if(isneg()) - negate(); - return *this; - } - } - - if(iszero()) - { - return *this; - } - - if(n >= static_cast(cpp_dec_float_elem_mask)) - { - neg = b_neg; - cpp_dec_float t; - t = n; - return operator/=(t); - } - - const boost::uint32_t nn = static_cast(n); - - if(nn > static_cast(1u)) - { - // Do the division loop. - const boost::uint32_t prev = div_loop_n(data.data(), nn, prec_elem); - - // Determine if one leading zero is in the result data. - if(data[0] == static_cast(0u)) - { - // Adjust the exponent - exp -= static_cast(cpp_dec_float_elem_digits10); - - // Shift result of the division one element to the left. - std::copy(data.begin() + static_cast(1u), - data.begin() + static_cast(prec_elem - static_cast(1)), - data.begin()); - - data[prec_elem - static_cast(1)] = static_cast(static_cast(prev * static_cast(cpp_dec_float_elem_mask)) / nn); - } - } + data.front() = static_cast(carry); + } - // Check for potential underflow. - const bool b_result_might_underflow = (exp <= cpp_dec_float_min_exp10); + // Check for potential overflow. + const bool b_result_might_overflow = (exp >= cpp_dec_float_max_exp10); - // Handle underflow. - if(b_result_might_underflow && (compare((cpp_dec_float::min)()) < 0)) - return (*this = zero()); + // Handle overflow. + if (b_result_might_overflow && (compare((cpp_dec_float::max)()) > 0)) { + *this = inf(); + } - // Set the sign of the result. - neg = b_neg; + // Set the sign. + neg = b_neg; - return *this; + return *this; } template -cpp_dec_float& cpp_dec_float::calculate_inv() -{ - // Compute the inverse of *this. - const bool b_neg = neg; +cpp_dec_float & +cpp_dec_float::div_unsigned_long_long( + const boost::ulong_long_type n) { + // Divide *this by a constant boost::ulong_long_type. - neg = false; + // Evaluate the sign of the result. + const bool b_neg = neg; - // Handle special cases like zero, inf and NaN. - if(iszero()) - { - *this = inf(); - if(b_neg) - negate(); - return *this; - } + // Artificially set the sign of the result to be positive. + neg = false; - if((isnan)()) - { - return *this; - } + // Handle special cases like zero, inf and NaN. + if ((isnan)()) { + return *this; + } - if((isinf)()) - { - return *this = zero(); - } + if ((isinf)()) { + *this = inf(); + if (b_neg) + negate(); + return *this; + } - if(isone()) - { - if(b_neg) - negate(); + if (n == static_cast(0u)) { + // Divide by 0. + if (iszero()) { + *this = nan(); return *this; - } - - // Save the original *this. - cpp_dec_float x(*this); - - // Generate the initial estimate using division. - // Extract the mantissa and exponent for a "manual" - // computation of the estimate. - double dd; - ExponentType ne; - x.extract_parts(dd, ne); - - // Do the inverse estimate using double precision estimates of mantissa and exponent. - operator=(cpp_dec_float(1.0 / dd, -ne)); - - // Compute the inverse of *this. Quadratically convergent Newton-Raphson iteration - // is used. During the iterative steps, the precision of the calculation is limited - // to the minimum required in order to minimize the run-time. - - static const boost::int32_t double_digits10_minus_a_few = std::numeric_limits::digits10 - 3; - - for(boost::int32_t digits = double_digits10_minus_a_few; digits <= cpp_dec_float_total_digits10; digits *= static_cast(2)) - { - // Adjust precision of the terms. - precision(static_cast((digits + 10) * static_cast(2))); - x.precision(static_cast((digits + 10) * static_cast(2))); - - // Next iteration. - cpp_dec_float t(*this); - t *= x; - t -= two(); - t.negate(); - *this *= t; - } - - neg = b_neg; - - prec_elem = cpp_dec_float_elem_number; - - return *this; + } else { + *this = inf(); + if (isneg()) + negate(); + return *this; + } + } + + if (iszero()) { + return *this; + } + + if (n >= static_cast(cpp_dec_float_elem_mask)) { + neg = b_neg; + cpp_dec_float t; + t = n; + return operator/=(t); + } + + const boost::uint32_t nn = static_cast(n); + + if (nn > static_cast(1u)) { + // Do the division loop. + const boost::uint32_t prev = div_loop_n(data.data(), nn, prec_elem); + + // Determine if one leading zero is in the result data. + if (data[0] == static_cast(0u)) { + // Adjust the exponent + exp -= static_cast(cpp_dec_float_elem_digits10); + + // Shift result of the division one element to the left. + std::copy(data.begin() + static_cast(1u), + data.begin() + static_cast( + prec_elem - static_cast(1)), + data.begin()); + + data[prec_elem - static_cast(1)] = + static_cast( + static_cast( + prev * + static_cast(cpp_dec_float_elem_mask)) / + nn); + } + } + + // Check for potential underflow. + const bool b_result_might_underflow = (exp <= cpp_dec_float_min_exp10); + + // Handle underflow. + if (b_result_might_underflow && (compare((cpp_dec_float::min)()) < 0)) + return (*this = zero()); + + // Set the sign of the result. + neg = b_neg; + + return *this; } template -cpp_dec_float& cpp_dec_float::calculate_sqrt() -{ - // Compute the square root of *this. - - if((isinf)() && !isneg()) - { - return *this; - } - - if(isneg() || (!(isfinite)())) - { - *this = nan(); - errno = EDOM; - return *this; - } +cpp_dec_float & +cpp_dec_float::calculate_inv() { + // Compute the inverse of *this. + const bool b_neg = neg; + + neg = false; + + // Handle special cases like zero, inf and NaN. + if (iszero()) { + *this = inf(); + if (b_neg) + negate(); + return *this; + } + + if ((isnan)()) { + return *this; + } + + if ((isinf)()) { + return *this = zero(); + } + + if (isone()) { + if (b_neg) + negate(); + return *this; + } + + // Save the original *this. + cpp_dec_float x(*this); + + // Generate the initial estimate using division. + // Extract the mantissa and exponent for a "manual" + // computation of the estimate. + double dd; + ExponentType ne; + x.extract_parts(dd, ne); + + // Do the inverse estimate using double precision estimates of mantissa and + // exponent. + operator=(cpp_dec_float(1.0 / dd, -ne)); + + // Compute the inverse of *this. Quadratically convergent Newton-Raphson + // iteration is used. During the iterative steps, the precision of the + // calculation is limited to the minimum required in order to minimize the + // run-time. + + static const boost::int32_t double_digits10_minus_a_few = + std::numeric_limits::digits10 - 3; + + for (boost::int32_t digits = double_digits10_minus_a_few; + digits <= cpp_dec_float_total_digits10; + digits *= static_cast(2)) { + // Adjust precision of the terms. + precision(static_cast((digits + 10) * + static_cast(2))); + x.precision(static_cast((digits + 10) * + static_cast(2))); + + // Next iteration. + cpp_dec_float t(*this); + t *= x; + t -= two(); + t.negate(); + *this *= t; + } + + neg = b_neg; + + prec_elem = cpp_dec_float_elem_number; + + return *this; +} - if(iszero() || isone()) - { - return *this; - } - - // Save the original *this. - cpp_dec_float x(*this); - - // Generate the initial estimate using division. - // Extract the mantissa and exponent for a "manual" - // computation of the estimate. - double dd; - ExponentType ne; - extract_parts(dd, ne); - - // Force the exponent to be an even multiple of two. - if((ne % static_cast(2)) != static_cast(0)) - { - ++ne; - dd /= 10.0; - } - - // Setup the iteration. - // Estimate the square root using simple manipulations. - const double sqd = std::sqrt(dd); - - *this = cpp_dec_float(sqd, static_cast(ne / static_cast(2))); - - // Estimate 1.0 / (2.0 * x0) using simple manipulations. - cpp_dec_float vi(0.5 / sqd, static_cast(-ne / static_cast(2))); - - // Compute the square root of x. Coupled Newton iteration - // as described in "Pi Unleashed" is used. During the - // iterative steps, the precision of the calculation is - // limited to the minimum required in order to minimize - // the run-time. - // - // Book references: - // https://doi.org/10.1007/978-3-642-56735-3 - // http://www.amazon.com/exec/obidos/tg/detail/-/3540665722/qid=1035535482/sr=8-7/ref=sr_8_7/104-3357872-6059916?v=glance&n=507846 - - static const boost::uint32_t double_digits10_minus_a_few = std::numeric_limits::digits10 - 3; - - for(boost::int32_t digits = double_digits10_minus_a_few; digits <= cpp_dec_float_total_digits10; digits *= 2u) - { - // Adjust precision of the terms. - precision((digits + 10) * 2); - vi.precision((digits + 10) * 2); - - // Next iteration of vi - cpp_dec_float t(*this); - t *= vi; - t.negate(); - t.mul_unsigned_long_long(2u); - t += one(); - t *= vi; - vi += t; - - // Next iteration of *this - t = *this; - t *= *this; - t.negate(); - t += x; - t *= vi; - *this += t; - } - - prec_elem = cpp_dec_float_elem_number; - - return *this; +template +cpp_dec_float & +cpp_dec_float::calculate_sqrt() { + // Compute the square root of *this. + + if ((isinf)() && !isneg()) { + return *this; + } + + if (isneg() || (!(isfinite)())) { + *this = nan(); + errno = EDOM; + return *this; + } + + if (iszero() || isone()) { + return *this; + } + + // Save the original *this. + cpp_dec_float x(*this); + + // Generate the initial estimate using division. + // Extract the mantissa and exponent for a "manual" + // computation of the estimate. + double dd; + ExponentType ne; + extract_parts(dd, ne); + + // Force the exponent to be an even multiple of two. + if ((ne % static_cast(2)) != static_cast(0)) { + ++ne; + dd /= 10.0; + } + + // Setup the iteration. + // Estimate the square root using simple manipulations. + const double sqd = std::sqrt(dd); + + *this = cpp_dec_float( + sqd, static_cast(ne / static_cast(2))); + + // Estimate 1.0 / (2.0 * x0) using simple manipulations. + cpp_dec_float vi( + 0.5 / sqd, static_cast(-ne / static_cast(2))); + + // Compute the square root of x. Coupled Newton iteration + // as described in "Pi Unleashed" is used. During the + // iterative steps, the precision of the calculation is + // limited to the minimum required in order to minimize + // the run-time. + // + // Book references: + // https://doi.org/10.1007/978-3-642-56735-3 + // http://www.amazon.com/exec/obidos/tg/detail/-/3540665722/qid=1035535482/sr=8-7/ref=sr_8_7/104-3357872-6059916?v=glance&n=507846 + + static const boost::uint32_t double_digits10_minus_a_few = + std::numeric_limits::digits10 - 3; + + for (boost::int32_t digits = double_digits10_minus_a_few; + digits <= cpp_dec_float_total_digits10; digits *= 2u) { + // Adjust precision of the terms. + precision((digits + 10) * 2); + vi.precision((digits + 10) * 2); + + // Next iteration of vi + cpp_dec_float t(*this); + t *= vi; + t.negate(); + t.mul_unsigned_long_long(2u); + t += one(); + t *= vi; + vi += t; + + // Next iteration of *this + t = *this; + t *= *this; + t.negate(); + t += x; + t *= vi; + *this += t; + } + + prec_elem = cpp_dec_float_elem_number; + + return *this; } template -int cpp_dec_float::cmp_data(const array_type& vd) const -{ - // Compare the data of *this with those of v. - // Return +1 for *this > v - // 0 for *this = v - // -1 for *this < v +int cpp_dec_float::cmp_data( + const array_type &vd) const { + // Compare the data of *this with those of v. + // Return +1 for *this > v + // 0 for *this = v + // -1 for *this < v - const std::pair mismatch_pair = std::mismatch(data.begin(), data.end(), vd.begin()); + const std::pair + mismatch_pair = std::mismatch(data.begin(), data.end(), vd.begin()); - const bool is_equal = ((mismatch_pair.first == data.end()) && (mismatch_pair.second == vd.end())); + const bool is_equal = ((mismatch_pair.first == data.end()) && + (mismatch_pair.second == vd.end())); - if(is_equal) - { - return 0; - } - else - { - return ((*mismatch_pair.first > *mismatch_pair.second) ? 1 : -1); - } + if (is_equal) { + return 0; + } else { + return ((*mismatch_pair.first > *mismatch_pair.second) ? 1 : -1); + } } template -int cpp_dec_float::compare(const cpp_dec_float& v) const -{ - // Compare v with *this. - // Return +1 for *this > v - // 0 for *this = v - // -1 for *this < v - - // Handle all non-finite cases. - if((!(isfinite)()) || (!(v.isfinite)())) - { - // NaN can never equal NaN. Return an implementation-dependent - // signed result. Also note that comparison of NaN with NaN - // using operators greater-than or less-than is undefined. - if((isnan)() || (v.isnan)()) { return ((isnan)() ? 1 : -1); } - - if((isinf)() && (v.isinf)()) - { - // Both *this and v are infinite. They are equal if they have the same sign. - // Otherwise, *this is less than v if and only if *this is negative. - return ((neg == v.neg) ? 0 : (neg ? -1 : 1)); - } - - if((isinf)()) - { - // *this is infinite, but v is finite. - // So negative infinite *this is less than any finite v. - // Whereas positive infinite *this is greater than any finite v. - return (isneg() ? -1 : 1); - } - else - { - // *this is finite, and v is infinite. - // So any finite *this is greater than negative infinite v. - // Whereas any finite *this is less than positive infinite v. - return (v.neg ? 1 : -1); - } - } - - // And now handle all *finite* cases. - if(iszero()) - { - // The value of *this is zero and v is either zero or non-zero. - return (v.iszero() ? 0 - : (v.neg ? 1 : -1)); - } - else if(v.iszero()) - { - // The value of v is zero and *this is non-zero. +int cpp_dec_float::compare( + const cpp_dec_float &v) const { + // Compare v with *this. + // Return +1 for *this > v + // 0 for *this = v + // -1 for *this < v + + // Handle all non-finite cases. + if ((!(isfinite)()) || (!(v.isfinite)())) { + // NaN can never equal NaN. Return an implementation-dependent + // signed result. Also note that comparison of NaN with NaN + // using operators greater-than or less-than is undefined. + if ((isnan)() || (v.isnan)()) { + return ((isnan)() ? 1 : -1); + } + + if ((isinf)() && (v.isinf)()) { + // Both *this and v are infinite. They are equal if they have the same + // sign. Otherwise, *this is less than v if and only if *this is negative. + return ((neg == v.neg) ? 0 : (neg ? -1 : 1)); + } + + if ((isinf)()) { + // *this is infinite, but v is finite. + // So negative infinite *this is less than any finite v. + // Whereas positive infinite *this is greater than any finite v. + return (isneg() ? -1 : 1); + } else { + // *this is finite, and v is infinite. + // So any finite *this is greater than negative infinite v. + // Whereas any finite *this is less than positive infinite v. + return (v.neg ? 1 : -1); + } + } + + // And now handle all *finite* cases. + if (iszero()) { + // The value of *this is zero and v is either zero or non-zero. + return (v.iszero() ? 0 : (v.neg ? 1 : -1)); + } else if (v.iszero()) { + // The value of v is zero and *this is non-zero. + return (neg ? -1 : 1); + } else { + // Both *this and v are non-zero. + + if (neg != v.neg) { + // The signs are different. return (neg ? -1 : 1); - } - else - { - // Both *this and v are non-zero. - - if(neg != v.neg) - { - // The signs are different. - return (neg ? -1 : 1); - } - else if(exp != v.exp) - { - // The signs are the same and the exponents are different. - const int val_cexpression = ((exp < v.exp) ? 1 : -1); - - return (neg ? val_cexpression : -val_cexpression); - } - else - { - // The signs are the same and the exponents are the same. - // Compare the data. - const int val_cmp_data = cmp_data(v.data); - - return ((!neg) ? val_cmp_data : -val_cmp_data); - } - } + } else if (exp != v.exp) { + // The signs are the same and the exponents are different. + const int val_cexpression = ((exp < v.exp) ? 1 : -1); + + return (neg ? val_cexpression : -val_cexpression); + } else { + // The signs are the same and the exponents are the same. + // Compare the data. + const int val_cmp_data = cmp_data(v.data); + + return ((!neg) ? val_cmp_data : -val_cmp_data); + } + } } template -bool cpp_dec_float::isone() const -{ - // Check if the value of *this is identically 1 or very close to 1. - - const bool not_negative_and_is_finite = ((!neg) && (isfinite)()); - - if(not_negative_and_is_finite) - { - if((data[0u] == static_cast(1u)) && (exp == static_cast(0))) - { - const typename array_type::const_iterator it_non_zero = std::find_if(data.begin(), data.end(), data_elem_is_non_zero_predicate); - return (it_non_zero == data.end()); - } - else if((data[0u] == static_cast(cpp_dec_float_elem_mask - 1)) && (exp == static_cast(-cpp_dec_float_elem_digits10))) - { - const typename array_type::const_iterator it_non_nine = std::find_if(data.begin(), data.end(), data_elem_is_non_nine_predicate); - return (it_non_nine == data.end()); - } - } - - return false; +bool cpp_dec_float::isone() const { + // Check if the value of *this is identically 1 or very close to 1. + + const bool not_negative_and_is_finite = ((!neg) && (isfinite)()); + + if (not_negative_and_is_finite) { + if ((data[0u] == static_cast(1u)) && + (exp == static_cast(0))) { + const typename array_type::const_iterator it_non_zero = std::find_if( + data.begin(), data.end(), data_elem_is_non_zero_predicate); + return (it_non_zero == data.end()); + } else if ((data[0u] == + static_cast(cpp_dec_float_elem_mask - 1)) && + (exp == + static_cast(-cpp_dec_float_elem_digits10))) { + const typename array_type::const_iterator it_non_nine = std::find_if( + data.begin(), data.end(), data_elem_is_non_nine_predicate); + return (it_non_nine == data.end()); + } + } + + return false; } template -bool cpp_dec_float::isint() const -{ - if(fpclass != cpp_dec_float_finite) { return false; } +bool cpp_dec_float::isint() const { + if (fpclass != cpp_dec_float_finite) { + return false; + } - if(iszero()) { return true; } + if (iszero()) { + return true; + } - if(exp < static_cast(0)) { return false; } // |*this| < 1. + if (exp < static_cast(0)) { + return false; + } // |*this| < 1. - const typename array_type::size_type offset_decimal_part = static_cast(exp / cpp_dec_float_elem_digits10) + 1u; + const typename array_type::size_type offset_decimal_part = + static_cast(exp / + cpp_dec_float_elem_digits10) + + 1u; - if(offset_decimal_part >= static_cast(cpp_dec_float_elem_number)) - { - // The number is too large to resolve the integer part. - // It considered to be a pure integer. - return true; - } + if (offset_decimal_part >= + static_cast(cpp_dec_float_elem_number)) { + // The number is too large to resolve the integer part. + // It considered to be a pure integer. + return true; + } - typename array_type::const_iterator it_non_zero = std::find_if(data.begin() + offset_decimal_part, data.end(), data_elem_is_non_zero_predicate); + typename array_type::const_iterator it_non_zero = + std::find_if(data.begin() + offset_decimal_part, data.end(), + data_elem_is_non_zero_predicate); - return (it_non_zero == data.end()); + return (it_non_zero == data.end()); } template -void cpp_dec_float::extract_parts(double& mantissa, ExponentType& exponent) const -{ - // Extract the approximate parts mantissa and base-10 exponent from the input cpp_dec_float value x. - - // Extracts the mantissa and exponent. - exponent = exp; - - boost::uint32_t p10 = static_cast(1u); - boost::uint32_t test = data[0u]; - - for(;;) - { - test /= static_cast(10u); - - if(test == static_cast(0u)) - { - break; - } - - p10 *= static_cast(10u); - ++exponent; - } - - // Establish the upper bound of limbs for extracting the double. - const int max_elem_in_double_count = static_cast(static_cast(std::numeric_limits::digits10) / cpp_dec_float_elem_digits10) - + (static_cast(static_cast(std::numeric_limits::digits10) % cpp_dec_float_elem_digits10) != 0 ? 1 : 0) - + 1; - - // And make sure this upper bound stays within bounds of the elems. - const std::size_t max_elem_extract_count = static_cast((std::min)(static_cast(max_elem_in_double_count), cpp_dec_float_elem_number)); - - // Extract into the mantissa the first limb, extracted as a double. - mantissa = static_cast(data[0]); - double scale = 1.0; - - // Extract the rest of the mantissa piecewise from the limbs. - for(std::size_t i = 1u; i < max_elem_extract_count; i++) - { - scale /= static_cast(cpp_dec_float_elem_mask); - mantissa += (static_cast(data[i]) * scale); - } - - mantissa /= static_cast(p10); - - if(neg) { mantissa = -mantissa; } +void cpp_dec_float::extract_parts( + double &mantissa, ExponentType &exponent) const { + // Extract the approximate parts mantissa and base-10 exponent from the input + // cpp_dec_float value x. + + // Extracts the mantissa and exponent. + exponent = exp; + + boost::uint32_t p10 = static_cast(1u); + boost::uint32_t test = data[0u]; + + for (;;) { + test /= static_cast(10u); + + if (test == static_cast(0u)) { + break; + } + + p10 *= static_cast(10u); + ++exponent; + } + + // Establish the upper bound of limbs for extracting the double. + const int max_elem_in_double_count = + static_cast( + static_cast(std::numeric_limits::digits10) / + cpp_dec_float_elem_digits10) + + (static_cast( + static_cast(std::numeric_limits::digits10) % + cpp_dec_float_elem_digits10) != 0 + ? 1 + : 0) + + 1; + + // And make sure this upper bound stays within bounds of the elems. + const std::size_t max_elem_extract_count = static_cast( + (std::min)(static_cast(max_elem_in_double_count), + cpp_dec_float_elem_number)); + + // Extract into the mantissa the first limb, extracted as a double. + mantissa = static_cast(data[0]); + double scale = 1.0; + + // Extract the rest of the mantissa piecewise from the limbs. + for (std::size_t i = 1u; i < max_elem_extract_count; i++) { + scale /= static_cast(cpp_dec_float_elem_mask); + mantissa += (static_cast(data[i]) * scale); + } + + mantissa /= static_cast(p10); + + if (neg) { + mantissa = -mantissa; + } } template -double cpp_dec_float::extract_double() const -{ - // Returns the double conversion of a cpp_dec_float. +double +cpp_dec_float::extract_double() const { + // Returns the double conversion of a cpp_dec_float. - // Check for non-normal cpp_dec_float. - if(!(isfinite)()) - { - if((isnan)()) - { - return std::numeric_limits::quiet_NaN(); - } - else - { - return ((!neg) ? std::numeric_limits::infinity() - : -std::numeric_limits::infinity()); - } - } + // Check for non-normal cpp_dec_float. + if (!(isfinite)()) { + if ((isnan)()) { + return std::numeric_limits::quiet_NaN(); + } else { + return ((!neg) ? std::numeric_limits::infinity() + : -std::numeric_limits::infinity()); + } + } - cpp_dec_float xx(*this); - if(xx.isneg()) - xx.negate(); + cpp_dec_float xx(*this); + if (xx.isneg()) + xx.negate(); - // Check if *this cpp_dec_float is zero. - if(iszero() || (xx.compare(double_min()) < 0)) - { - return 0.0; - } + // Check if *this cpp_dec_float is zero. + if (iszero() || (xx.compare(double_min()) < 0)) { + return 0.0; + } - // Check if *this cpp_dec_float exceeds the maximum of double. - if(xx.compare(double_max()) > 0) - { - return ((!neg) ? std::numeric_limits::infinity() - : -std::numeric_limits::infinity()); - } + // Check if *this cpp_dec_float exceeds the + // maximum of double. + if (xx.compare(double_max()) > 0) { + return ((!neg) ? std::numeric_limits::infinity() + : -std::numeric_limits::infinity()); + } - std::stringstream ss; + std::stringstream ss; - ss << str(std::numeric_limits::digits10 + (2 + 1), std::ios_base::scientific); + ss << str(std::numeric_limits::digits10 + (2 + 1), + std::ios_base::scientific); - double d; - ss >> d; + double d; + ss >> d; - return d; + return d; } template -long double cpp_dec_float::extract_long_double() const -{ - // Returns the long double conversion of a cpp_dec_float. +long double +cpp_dec_float::extract_long_double() const { + // Returns the long double conversion of a cpp_dec_float. - // Check if *this cpp_dec_float is subnormal. - if(!(isfinite)()) - { - if((isnan)()) - { - return std::numeric_limits::quiet_NaN(); - } - else - { - return ((!neg) ? std::numeric_limits::infinity() - : -std::numeric_limits::infinity()); - } - } + // Check if *this cpp_dec_float is + // subnormal. + if (!(isfinite)()) { + if ((isnan)()) { + return std::numeric_limits::quiet_NaN(); + } else { + return ((!neg) ? std::numeric_limits::infinity() + : -std::numeric_limits::infinity()); + } + } - cpp_dec_float xx(*this); - if(xx.isneg()) - xx.negate(); + cpp_dec_float xx(*this); + if (xx.isneg()) + xx.negate(); - // Check if *this cpp_dec_float is zero. - if(iszero() || (xx.compare(long_double_min()) < 0)) - { - return static_cast(0.0); - } + // Check if *this cpp_dec_float is zero. + if (iszero() || (xx.compare(long_double_min()) < 0)) { + return static_cast(0.0); + } - // Check if *this cpp_dec_float exceeds the maximum of double. - if(xx.compare(long_double_max()) > 0) - { - return ((!neg) ? std::numeric_limits::infinity() - : -std::numeric_limits::infinity()); - } + // Check if *this cpp_dec_float exceeds the + // maximum of double. + if (xx.compare(long_double_max()) > 0) { + return ((!neg) ? std::numeric_limits::infinity() + : -std::numeric_limits::infinity()); + } - std::stringstream ss; + std::stringstream ss; - ss << str(std::numeric_limits::digits10 + (2 + 1), std::ios_base::scientific); + ss << str(std::numeric_limits::digits10 + (2 + 1), + std::ios_base::scientific); - long double ld; - ss >> ld; + long double ld; + ss >> ld; - return ld; + return ld; } template -boost::long_long_type cpp_dec_float::extract_signed_long_long() const -{ - // Extracts a signed long long from *this. - // If (x > maximum of long long) or (x < minimum of long long), - // then the maximum or minimum of long long is returned accordingly. - - if(exp < static_cast(0)) - { - return static_cast(0); - } - - const bool b_neg = isneg(); - - boost::ulong_long_type val; - - if((!b_neg) && (compare(long_long_max()) > 0)) - { - return (std::numeric_limits::max)(); - } - else if(b_neg && (compare(long_long_min()) < 0)) - { - return (std::numeric_limits::min)(); - } - else - { - // Extract the data into an boost::ulong_long_type value. - cpp_dec_float xn(extract_integer_part()); - if(xn.isneg()) - xn.negate(); - - val = static_cast(xn.data[0]); - - const boost::int32_t imax = (std::min)(static_cast(static_cast(xn.exp) / cpp_dec_float_elem_digits10), static_cast(cpp_dec_float_elem_number - static_cast(1))); - - for(boost::int32_t i = static_cast(1); i <= imax; i++) - { - val *= static_cast(cpp_dec_float_elem_mask); - val += static_cast(xn.data[i]); - } - } - - if (!b_neg) - { - return static_cast(val); - } - else - { - // This strange expression avoids a hardware trap in the corner case - // that val is the most negative value permitted in boost::long_long_type. - // See https://svn.boost.org/trac/boost/ticket/9740. - // - boost::long_long_type sval = static_cast(val - 1); - sval = -sval; - --sval; - return sval; - } +boost::long_long_type +cpp_dec_float::extract_signed_long_long() + const { + // Extracts a signed long long from *this. + // If (x > maximum of long long) or (x < minimum of long long), + // then the maximum or minimum of long long is returned accordingly. + + if (exp < static_cast(0)) { + return static_cast(0); + } + + const bool b_neg = isneg(); + + boost::ulong_long_type val; + + if ((!b_neg) && (compare(long_long_max()) > 0)) { + return (std::numeric_limits::max)(); + } else if (b_neg && (compare(long_long_min()) < 0)) { + return (std::numeric_limits::min)(); + } else { + // Extract the data into an boost::ulong_long_type value. + cpp_dec_float xn(extract_integer_part()); + if (xn.isneg()) + xn.negate(); + + val = static_cast(xn.data[0]); + + const boost::int32_t imax = (std::min)( + static_cast(static_cast(xn.exp) / + cpp_dec_float_elem_digits10), + static_cast(cpp_dec_float_elem_number - + static_cast(1))); + + for (boost::int32_t i = static_cast(1); i <= imax; i++) { + val *= static_cast(cpp_dec_float_elem_mask); + val += static_cast(xn.data[i]); + } + } + + if (!b_neg) { + return static_cast(val); + } else { + // This strange expression avoids a hardware trap in the corner case + // that val is the most negative value permitted in boost::long_long_type. + // See https://svn.boost.org/trac/boost/ticket/9740. + // + boost::long_long_type sval = static_cast(val - 1); + sval = -sval; + --sval; + return sval; + } } template -boost::ulong_long_type cpp_dec_float::extract_unsigned_long_long() const -{ - // Extracts an boost::ulong_long_type from *this. - // If x exceeds the maximum of boost::ulong_long_type, - // then the maximum of boost::ulong_long_type is returned. - // If x is negative, then the boost::ulong_long_type cast of - // the long long extracted value is returned. +boost::ulong_long_type +cpp_dec_float::extract_unsigned_long_long() + const { + // Extracts an boost::ulong_long_type from *this. + // If x exceeds the maximum of boost::ulong_long_type, + // then the maximum of boost::ulong_long_type is returned. + // If x is negative, then the boost::ulong_long_type cast of + // the long long extracted value is returned. - if(isneg()) - { - return static_cast(extract_signed_long_long()); - } + if (isneg()) { + return static_cast(extract_signed_long_long()); + } - if(exp < static_cast(0)) - { - return static_cast(0u); - } + if (exp < static_cast(0)) { + return static_cast(0u); + } - const cpp_dec_float xn(extract_integer_part()); + const cpp_dec_float xn( + extract_integer_part()); - boost::ulong_long_type val; + boost::ulong_long_type val; - if(xn.compare(ulong_long_max()) > 0) - { - return (std::numeric_limits::max)(); - } - else - { - // Extract the data into an boost::ulong_long_type value. - val = static_cast(xn.data[0]); + if (xn.compare(ulong_long_max()) > 0) { + return (std::numeric_limits::max)(); + } else { + // Extract the data into an boost::ulong_long_type value. + val = static_cast(xn.data[0]); - const boost::int32_t imax = (std::min)(static_cast(static_cast(xn.exp) / cpp_dec_float_elem_digits10), static_cast(cpp_dec_float_elem_number - static_cast(1))); + const boost::int32_t imax = (std::min)( + static_cast(static_cast(xn.exp) / + cpp_dec_float_elem_digits10), + static_cast(cpp_dec_float_elem_number - + static_cast(1))); - for(boost::int32_t i = static_cast(1); i <= imax; i++) - { - val *= static_cast(cpp_dec_float_elem_mask); - val += static_cast(xn.data[i]); - } - } + for (boost::int32_t i = static_cast(1); i <= imax; i++) { + val *= static_cast(cpp_dec_float_elem_mask); + val += static_cast(xn.data[i]); + } + } - return val; + return val; } template -cpp_dec_float cpp_dec_float::extract_integer_part() const -{ - // Compute the signed integer part of x. +cpp_dec_float +cpp_dec_float::extract_integer_part() const { + // Compute the signed integer part of x. - if(!(isfinite)()) - { - return *this; - } + if (!(isfinite)()) { + return *this; + } - if(exp < static_cast(0)) - { - // The absolute value of the number is smaller than 1. - // Thus the integer part is zero. - return zero(); - } + if (exp < static_cast(0)) { + // The absolute value of the number is smaller than 1. + // Thus the integer part is zero. + return zero(); + } - // Truncate the digits from the decimal part, including guard digits - // that do not belong to the integer part. + // Truncate the digits from the decimal part, including guard digits + // that do not belong to the integer part. - // Make a local copy. - cpp_dec_float x = *this; + // Make a local copy. + cpp_dec_float x = *this; - // Clear out the decimal portion - const size_t first_clear = (static_cast(x.exp) / static_cast(cpp_dec_float_elem_digits10)) + 1u; - const size_t last_clear = static_cast(cpp_dec_float_elem_number); + // Clear out the decimal portion + const size_t first_clear = + (static_cast(x.exp) / + static_cast(cpp_dec_float_elem_digits10)) + + 1u; + const size_t last_clear = static_cast(cpp_dec_float_elem_number); - if(first_clear < last_clear) - std::fill(x.data.begin() + first_clear, x.data.begin() + last_clear, static_cast(0u)); + if (first_clear < last_clear) + std::fill(x.data.begin() + first_clear, x.data.begin() + last_clear, + static_cast(0u)); - return x; + return x; } template -std::string cpp_dec_float::str(boost::intmax_t number_of_digits, std::ios_base::fmtflags f) const -{ - if((this->isinf)()) - { - if(this->isneg()) - return "-inf"; - else if(f & std::ios_base::showpos) - return "+inf"; - else - return "inf"; - } - else if((this->isnan)()) - { - return "nan"; - } - - std::string str; - boost::intmax_t org_digits(number_of_digits); - ExponentType my_exp = order(); - - if(number_of_digits == 0) - number_of_digits = cpp_dec_float_total_digits10; - - if(f & std::ios_base::fixed) - { - number_of_digits += my_exp + 1; - } - else if(f & std::ios_base::scientific) - ++number_of_digits; - // Determine the number of elements needed to provide the requested digits from cpp_dec_float. - const std::size_t number_of_elements = (std::min)(static_cast((number_of_digits / static_cast(cpp_dec_float_elem_digits10)) + 2u), - static_cast(cpp_dec_float_elem_number)); - - // Extract the remaining digits from cpp_dec_float after the decimal point. - str = boost::lexical_cast(data[0]); - - std::stringstream ss; - // Extract all of the digits from cpp_dec_float, beginning with the first data element. - for(std::size_t i = static_cast(1u); i < number_of_elements; i++) - { - ss << std::setw(static_cast(cpp_dec_float_elem_digits10)) - << std::setfill(static_cast('0')) - << data[i]; - - } - str += ss.str(); - - bool have_leading_zeros = false; - - if(number_of_digits == 0) - { - // We only get here if the output format is "fixed" and we just need to - // round the first non-zero digit. - number_of_digits -= my_exp + 1; // reset to original value - str.insert(static_cast(0), std::string::size_type(number_of_digits), '0'); - have_leading_zeros = true; - } - - if(number_of_digits < 0) - { - str = "0"; - if(isneg()) - str.insert(static_cast(0), 1, '-'); - boost::multiprecision::detail::format_float_string(str, 0, number_of_digits - my_exp - 1, f, this->iszero()); - return str; - } - else - { - // Cut the output to the size of the precision. - if(str.length() > static_cast(number_of_digits)) - { - // Get the digit after the last needed digit for rounding - const boost::uint32_t round = static_cast(static_cast(str[static_cast(number_of_digits)]) - static_cast('0')); - - bool need_round_up = round >= 5u; - - if(round == 5u) - { - const boost::uint32_t ix = static_cast(static_cast(str[static_cast(number_of_digits - 1)]) - static_cast('0')); - if((ix & 1u) == 0) - { - // We have an even digit followed by a 5, so we might not actually need to round up - // if all the remaining digits are zero: - if(str.find_first_not_of('0', static_cast(number_of_digits + 1)) == std::string::npos) - { - bool all_zeros = true; - // No none-zero trailing digits in the string, now check whatever parts we didn't convert to the string: - for(std::size_t i = number_of_elements; i < data.size(); i++) - { - if(data[i]) - { - all_zeros = false; - break; - } - } - if(all_zeros) - need_round_up = false; // tie break - round to even. - } - } - } - - // Truncate the string - str.erase(static_cast(number_of_digits)); - - if(need_round_up) - { - std::size_t ix = static_cast(str.length() - 1u); - - // Every trailing 9 must be rounded up - while(ix && (static_cast(str.at(ix)) - static_cast('0') == static_cast(9))) - { - str.at(ix) = static_cast('0'); - --ix; - } - - if(!ix) - { - // There were nothing but trailing nines. - if(static_cast(static_cast(str.at(ix)) - static_cast(0x30)) == static_cast(9)) - { - // Increment up to the next order and adjust exponent. - str.at(ix) = static_cast('1'); - ++my_exp; - } - else - { - // Round up this digit. - ++str.at(ix); - } - } - else - { - // Round up the last digit. - ++str[ix]; +std::string cpp_dec_float::str( + boost::intmax_t number_of_digits, std::ios_base::fmtflags f) const { + if ((this->isinf)()) { + if (this->isneg()) + return "-inf"; + else if (f & std::ios_base::showpos) + return "+inf"; + else + return "inf"; + } else if ((this->isnan)()) { + return "nan"; + } + + std::string str; + boost::intmax_t org_digits(number_of_digits); + ExponentType my_exp = order(); + + if (number_of_digits == 0) + number_of_digits = cpp_dec_float_total_digits10; + + if (f & std::ios_base::fixed) { + number_of_digits += my_exp + 1; + } else if (f & std::ios_base::scientific) + ++number_of_digits; + // Determine the number of elements needed to provide the requested digits + // from cpp_dec_float. + const std::size_t number_of_elements = + (std::min)(static_cast( + (number_of_digits / + static_cast(cpp_dec_float_elem_digits10)) + + 2u), + static_cast(cpp_dec_float_elem_number)); + + // Extract the remaining digits from cpp_dec_float after the decimal point. + str = boost::lexical_cast(data[0]); + + std::stringstream ss; + // Extract all of the digits from cpp_dec_float, beginning with the first data element. + for (std::size_t i = static_cast(1u); i < number_of_elements; + i++) { + ss << std::setw(static_cast(cpp_dec_float_elem_digits10)) + << std::setfill(static_cast('0')) << data[i]; + } + str += ss.str(); + + bool have_leading_zeros = false; + + if (number_of_digits == 0) { + // We only get here if the output format is "fixed" and we just need to + // round the first non-zero digit. + number_of_digits -= my_exp + 1; // reset to original value + str.insert(static_cast(0), + std::string::size_type(number_of_digits), '0'); + have_leading_zeros = true; + } + + if (number_of_digits < 0) { + str = "0"; + if (isneg()) + str.insert(static_cast(0), 1, '-'); + boost::multiprecision::detail::format_float_string( + str, 0, number_of_digits - my_exp - 1, f, this->iszero()); + return str; + } else { + // Cut the output to the size of the precision. + if (str.length() > static_cast(number_of_digits)) { + // Get the digit after the last needed digit for rounding + const boost::uint32_t round = static_cast( + static_cast( + str[static_cast(number_of_digits)]) - + static_cast('0')); + + bool need_round_up = round >= 5u; + + if (round == 5u) { + const boost::uint32_t ix = static_cast( + static_cast( + str[static_cast(number_of_digits - + 1)]) - + static_cast('0')); + if ((ix & 1u) == 0) { + // We have an even digit followed by a 5, so we might not actually + // need to round up if all the remaining digits are zero: + if (str.find_first_not_of('0', static_cast( + number_of_digits + 1)) == + std::string::npos) { + bool all_zeros = true; + // No none-zero trailing digits in the string, now check whatever + // parts we didn't convert to the string: + for (std::size_t i = number_of_elements; i < data.size(); i++) { + if (data[i]) { + all_zeros = false; + break; + } } - } - } - } - - if(have_leading_zeros) - { - // We need to take the zeros back out again, and correct the exponent - // if we rounded up: - if(str[std::string::size_type(number_of_digits - 1)] != '0') - { - ++my_exp; - str.erase(0, std::string::size_type(number_of_digits - 1)); + if (all_zeros) + need_round_up = false; // tie break - round to even. + } + } } - else - str.erase(0, std::string::size_type(number_of_digits)); - } - if(isneg()) - str.insert(static_cast(0), 1, '-'); - - boost::multiprecision::detail::format_float_string(str, my_exp, org_digits, f, this->iszero()); - return str; + // Truncate the string + str.erase(static_cast(number_of_digits)); + + if (need_round_up) { + std::size_t ix = static_cast(str.length() - 1u); + + // Every trailing 9 must be rounded up + while (ix && (static_cast(str.at(ix)) - + static_cast('0') == + static_cast(9))) { + str.at(ix) = static_cast('0'); + --ix; + } + + if (!ix) { + // There were nothing but trailing nines. + if (static_cast( + static_cast(str.at(ix)) - + static_cast(0x30)) == + static_cast(9)) { + // Increment up to the next order and adjust exponent. + str.at(ix) = static_cast('1'); + ++my_exp; + } else { + // Round up this digit. + ++str.at(ix); + } + } else { + // Round up the last digit. + ++str[ix]; + } + } + } + } + + if (have_leading_zeros) { + // We need to take the zeros back out again, and correct the exponent + // if we rounded up: + if (str[std::string::size_type(number_of_digits - 1)] != '0') { + ++my_exp; + str.erase(0, std::string::size_type(number_of_digits - 1)); + } else + str.erase(0, std::string::size_type(number_of_digits)); + } + + if (isneg()) + str.insert(static_cast(0), 1, '-'); + + boost::multiprecision::detail::format_float_string(str, my_exp, org_digits, f, + this->iszero()); + return str; } template -bool cpp_dec_float::rd_string(const char* const s) -{ +bool cpp_dec_float::rd_string( + const char *const s) { #ifndef BOOST_NO_EXCEPTIONS - try{ + try { #endif - std::string str(s); + std::string str(s); - // TBD: Using several regular expressions may significantly reduce - // the code complexity (and perhaps the run-time) of rd_string(). + // TBD: Using several regular expressions may significantly reduce + // the code complexity (and perhaps the run-time) of rd_string(). - // Get a possible exponent and remove it. - exp = static_cast(0); + // Get a possible exponent and remove it. + exp = static_cast(0); - std::size_t pos; + std::size_t pos; - if( ((pos = str.find('e')) != std::string::npos) - || ((pos = str.find('E')) != std::string::npos) - ) - { + if (((pos = str.find('e')) != std::string::npos) || + ((pos = str.find('E')) != std::string::npos)) { // Remove the exponent part from the string. - exp = boost::lexical_cast(static_cast(str.c_str() + (pos + 1u))); + exp = boost::lexical_cast( + static_cast(str.c_str() + (pos + 1u))); str = str.substr(static_cast(0u), pos); - } + } - // Get a possible +/- sign and remove it. - neg = false; + // Get a possible +/- sign and remove it. + neg = false; - if(str.size()) - { - if(str[0] == '-') - { - neg = true; - str.erase(0, 1); - } - else if(str[0] == '+') - { - str.erase(0, 1); - } - } - // - // Special cases for infinities and NaN's: - // - if((str == "inf") || (str == "INF") || (str == "infinity") || (str == "INFINITY")) - { - if(neg) - { - *this = this->inf(); - this->negate(); + if (str.size()) { + if (str[0] == '-') { + neg = true; + str.erase(0, 1); + } else if (str[0] == '+') { + str.erase(0, 1); } - else - *this = this->inf(); + } + // + // Special cases for infinities and NaN's: + // + if ((str == "inf") || (str == "INF") || (str == "infinity") || + (str == "INFINITY")) { + if (neg) { + *this = this->inf(); + this->negate(); + } else + *this = this->inf(); return true; - } - if((str.size() >= 3) && ((str.substr(0, 3) == "nan") || (str.substr(0, 3) == "NAN") || (str.substr(0, 3) == "NaN"))) - { + } + if ((str.size() >= 3) && + ((str.substr(0, 3) == "nan") || (str.substr(0, 3) == "NAN") || + (str.substr(0, 3) == "NaN"))) { *this = this->nan(); return true; - } - - // Remove the leading zeros for all input types. - const std::string::iterator fwd_it_leading_zero = std::find_if(str.begin(), str.end(), char_is_nonzero_predicate); - - if(fwd_it_leading_zero != str.begin()) - { - if(fwd_it_leading_zero == str.end()) - { - // The string contains nothing but leading zeros. - // This string represents zero. - operator=(zero()); - return true; + } + + // Remove the leading zeros for all input types. + const std::string::iterator fwd_it_leading_zero = + std::find_if(str.begin(), str.end(), char_is_nonzero_predicate); + + if (fwd_it_leading_zero != str.begin()) { + if (fwd_it_leading_zero == str.end()) { + // The string contains nothing but leading zeros. + // This string represents zero. + operator=(zero()); + return true; + } else { + str.erase(str.begin(), fwd_it_leading_zero); } - else - { - str.erase(str.begin(), fwd_it_leading_zero); - } - } + } - // Put the input string into the standard cpp_dec_float input form - // aaa.bbbbE+/-n, where aaa has 1...cpp_dec_float_elem_digits10, bbbb has an - // even multiple of cpp_dec_float_elem_digits10 which are possibly zero padded - // on the right-end, and n is a signed 64-bit integer which is an - // even multiple of cpp_dec_float_elem_digits10. + // Put the input string into the standard cpp_dec_float input form aaa.bbbbE+/-n, where aaa + // has 1...cpp_dec_float_elem_digits10, bbbb has an even multiple of + // cpp_dec_float_elem_digits10 which are possibly zero padded on the + // right-end, and n is a signed 64-bit integer which is an even multiple of + // cpp_dec_float_elem_digits10. - // Find a possible decimal point. - pos = str.find(static_cast('.')); + // Find a possible decimal point. + pos = str.find(static_cast('.')); - if(pos != std::string::npos) - { + if (pos != std::string::npos) { // Remove all trailing insignificant zeros. - const std::string::const_reverse_iterator rit_non_zero = std::find_if(str.rbegin(), str.rend(), char_is_nonzero_predicate); - - if(rit_non_zero != static_cast(str.rbegin())) - { - const std::string::size_type ofs = str.length() - std::distance(str.rbegin(), rit_non_zero); - str.erase(str.begin() + ofs, str.end()); + const std::string::const_reverse_iterator rit_non_zero = + std::find_if(str.rbegin(), str.rend(), char_is_nonzero_predicate); + + if (rit_non_zero != + static_cast(str.rbegin())) { + const std::string::size_type ofs = + str.length() - std::distance( + str.rbegin(), rit_non_zero); + str.erase(str.begin() + ofs, str.end()); } // Check if the input is identically zero. - if(str == std::string(".")) - { - operator=(zero()); - return true; + if (str == std::string(".")) { + operator=(zero()); + return true; } // Remove leading significant zeros just after the decimal point // and adjust the exponent accordingly. - // Note that the while-loop operates only on strings of the form ".000abcd..." - // and peels away the zeros just after the decimal point. - if(str.at(static_cast(0u)) == static_cast('.')) - { - const std::string::iterator it_non_zero = std::find_if(str.begin() + 1u, str.end(), char_is_nonzero_predicate); - - std::size_t delta_exp = static_cast(0u); - - if(str.at(static_cast(1u)) == static_cast('0')) - { - delta_exp = std::distance(str.begin() + 1u, it_non_zero); - } - - // Bring one single digit into the mantissa and adjust the exponent accordingly. - str.erase(str.begin(), it_non_zero); - str.insert(static_cast(1u), "."); - exp -= static_cast(delta_exp + 1u); + // Note that the while-loop operates only on strings of the form + // ".000abcd..." and peels away the zeros just after the decimal point. + if (str.at(static_cast(0u)) == static_cast('.')) { + const std::string::iterator it_non_zero = std::find_if( + str.begin() + 1u, str.end(), char_is_nonzero_predicate); + + std::size_t delta_exp = static_cast(0u); + + if (str.at(static_cast(1u)) == static_cast('0')) { + delta_exp = std::distance( + str.begin() + 1u, it_non_zero); + } + + // Bring one single digit into the mantissa and adjust the exponent + // accordingly. + str.erase(str.begin(), it_non_zero); + str.insert(static_cast(1u), "."); + exp -= static_cast(delta_exp + 1u); } - } - else - { + } else { // Input string has no decimal point: Append decimal point. str.append("."); - } + } - // Shift the decimal point such that the exponent is an even multiple of cpp_dec_float_elem_digits10. - std::size_t n_shift = static_cast(0u); - const std::size_t n_exp_rem = static_cast(exp % static_cast(cpp_dec_float_elem_digits10)); + // Shift the decimal point such that the exponent is an even multiple of + // cpp_dec_float_elem_digits10. + std::size_t n_shift = static_cast(0u); + const std::size_t n_exp_rem = static_cast( + exp % static_cast(cpp_dec_float_elem_digits10)); - if((exp % static_cast(cpp_dec_float_elem_digits10)) != static_cast(0)) - { + if ((exp % static_cast(cpp_dec_float_elem_digits10)) != + static_cast(0)) { n_shift = ((exp < static_cast(0)) - ? static_cast(n_exp_rem + static_cast(cpp_dec_float_elem_digits10)) - : static_cast(n_exp_rem)); - } + ? static_cast( + n_exp_rem + static_cast( + cpp_dec_float_elem_digits10)) + : static_cast(n_exp_rem)); + } - // Make sure that there are enough digits for the decimal point shift. - pos = str.find(static_cast('.')); + // Make sure that there are enough digits for the decimal point shift. + pos = str.find(static_cast('.')); - std::size_t pos_plus_one = static_cast(pos + 1u); + std::size_t pos_plus_one = static_cast(pos + 1u); - if((str.length() - pos_plus_one) < n_shift) - { - const std::size_t sz = static_cast(n_shift - (str.length() - pos_plus_one)); + if ((str.length() - pos_plus_one) < n_shift) { + const std::size_t sz = + static_cast(n_shift - (str.length() - pos_plus_one)); str.append(std::string(sz, static_cast('0'))); - } + } - // Do the decimal point shift. - if(n_shift != static_cast(0u)) - { - str.insert(static_cast(pos_plus_one + n_shift), "."); + // Do the decimal point shift. + if (n_shift != static_cast(0u)) { + str.insert(static_cast(pos_plus_one + n_shift), + "."); str.erase(pos, static_cast(1u)); exp -= static_cast(n_shift); - } + } - // Cut the size of the mantissa to <= cpp_dec_float_elem_digits10. - pos = str.find(static_cast('.')); - pos_plus_one = static_cast(pos + 1u); + // Cut the size of the mantissa to <= cpp_dec_float_elem_digits10. + pos = str.find(static_cast('.')); + pos_plus_one = static_cast(pos + 1u); - if(pos > static_cast(cpp_dec_float_elem_digits10)) - { + if (pos > static_cast(cpp_dec_float_elem_digits10)) { const boost::int32_t n_pos = static_cast(pos); - const boost::int32_t n_rem_is_zero = ((static_cast(n_pos % cpp_dec_float_elem_digits10) == static_cast(0)) ? static_cast(1) : static_cast(0)); - const boost::int32_t n = static_cast(static_cast(n_pos / cpp_dec_float_elem_digits10) - n_rem_is_zero); - - str.insert(static_cast(static_cast(n_pos - static_cast(n * cpp_dec_float_elem_digits10))), "."); + const boost::int32_t n_rem_is_zero = + ((static_cast(n_pos % cpp_dec_float_elem_digits10) == + static_cast(0)) + ? static_cast(1) + : static_cast(0)); + const boost::int32_t n = static_cast( + static_cast(n_pos / cpp_dec_float_elem_digits10) - + n_rem_is_zero); + + str.insert(static_cast(static_cast( + n_pos - static_cast( + n * cpp_dec_float_elem_digits10))), + "."); str.erase(pos_plus_one, static_cast(1u)); - exp += static_cast(static_cast(n) * static_cast(cpp_dec_float_elem_digits10)); - } + exp += static_cast( + static_cast(n) * + static_cast(cpp_dec_float_elem_digits10)); + } - // Pad the decimal part such that its value is an even - // multiple of cpp_dec_float_elem_digits10. - pos = str.find(static_cast('.')); - pos_plus_one = static_cast(pos + 1u); + // Pad the decimal part such that its value is an even + // multiple of cpp_dec_float_elem_digits10. + pos = str.find(static_cast('.')); + pos_plus_one = static_cast(pos + 1u); - const boost::int32_t n_dec = static_cast(static_cast(str.length() - 1u) - static_cast(pos)); - const boost::int32_t n_rem = static_cast(n_dec % cpp_dec_float_elem_digits10); + const boost::int32_t n_dec = static_cast( + static_cast(str.length() - 1u) - + static_cast(pos)); + const boost::int32_t n_rem = + static_cast(n_dec % cpp_dec_float_elem_digits10); - boost::int32_t n_cnt = ((n_rem != static_cast(0)) - ? static_cast(cpp_dec_float_elem_digits10 - n_rem) - : static_cast(0)); + boost::int32_t n_cnt = + ((n_rem != static_cast(0)) + ? static_cast(cpp_dec_float_elem_digits10 - n_rem) + : static_cast(0)); - if(n_cnt != static_cast(0)) - { + if (n_cnt != static_cast(0)) { str.append(static_cast(n_cnt), static_cast('0')); - } + } - // Truncate decimal part if it is too long. - const std::size_t max_dec = static_cast((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10); + // Truncate decimal part if it is too long. + const std::size_t max_dec = static_cast( + (cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10); - if(static_cast(str.length() - pos) > max_dec) - { + if (static_cast(str.length() - pos) > max_dec) { str = str.substr(static_cast(0u), - static_cast(pos_plus_one + max_dec)); - } + static_cast(pos_plus_one + max_dec)); + } - // Now the input string has the standard cpp_dec_float input form. - // (See the comment above.) + // Now the input string has the standard cpp_dec_float input form. (See the comment above.) - // Set all the data elements to 0. - std::fill(data.begin(), data.end(), static_cast(0u)); + // Set all the data elements to 0. + std::fill(data.begin(), data.end(), static_cast(0u)); - // Extract the data. + // Extract the data. - // First get the digits to the left of the decimal point... - data[0u] = boost::lexical_cast(str.substr(static_cast(0u), pos)); + // First get the digits to the left of the decimal point... + data[0u] = boost::lexical_cast( + str.substr(static_cast(0u), pos)); - // ...then get the remaining digits to the right of the decimal point. - const std::string::size_type i_end = ((str.length() - pos_plus_one) / static_cast(cpp_dec_float_elem_digits10)); + // ...then get the remaining digits to the right of the decimal point. + const std::string::size_type i_end = + ((str.length() - pos_plus_one) / + static_cast(cpp_dec_float_elem_digits10)); - for(std::string::size_type i = static_cast(0u); i < i_end; i++) - { - const std::string::const_iterator it = str.begin() - + pos_plus_one - + (i * static_cast(cpp_dec_float_elem_digits10)); + for (std::string::size_type i = static_cast(0u); + i < i_end; i++) { + const std::string::const_iterator it = + str.begin() + pos_plus_one + + (i * + static_cast(cpp_dec_float_elem_digits10)); - data[i + 1u] = boost::lexical_cast(std::string(it, it + static_cast(cpp_dec_float_elem_digits10))); - } + data[i + 1u] = boost::lexical_cast( + std::string(it, it + static_cast( + cpp_dec_float_elem_digits10))); + } - // Check for overflow... - if(exp > cpp_dec_float_max_exp10) - { + // Check for overflow... + if (exp > cpp_dec_float_max_exp10) { const bool b_result_is_neg = neg; *this = inf(); - if(b_result_is_neg) - negate(); - } - - // ...and check for underflow. - if(exp <= cpp_dec_float_min_exp10) - { - if(exp == cpp_dec_float_min_exp10) - { - // Check for identity with the minimum value. - cpp_dec_float test = *this; - - test.exp = static_cast(0); - - if(test.isone()) - { - *this = zero(); - } - } - else - { - *this = zero(); + if (b_result_is_neg) + negate(); + } + + // ...and check for underflow. + if (exp <= cpp_dec_float_min_exp10) { + if (exp == cpp_dec_float_min_exp10) { + // Check for identity with the minimum value. + cpp_dec_float test = *this; + + test.exp = static_cast(0); + + if (test.isone()) { + *this = zero(); + } + } else { + *this = zero(); } - } + } #ifndef BOOST_NO_EXCEPTIONS - } - catch(const bad_lexical_cast&) - { - // Rethrow with better error message: - std::string msg = "Unable to parse the string \""; - msg += s; - msg += "\" as a floating point value."; - throw std::runtime_error(msg); - } + } catch (const bad_lexical_cast &) { + // Rethrow with better error message: + std::string msg = "Unable to parse the string \""; + msg += s; + msg += "\" as a floating point value."; + throw std::runtime_error(msg); + } #endif - return true; + return true; } template -cpp_dec_float::cpp_dec_float(const double mantissa, const ExponentType exponent) - : data (), - exp (static_cast(0)), - neg (false), - fpclass (cpp_dec_float_finite), - prec_elem(cpp_dec_float_elem_number) -{ - // Create *this cpp_dec_float from a given mantissa and exponent. - // Note: This constructor does not maintain the full precision of double. - - const bool mantissa_is_iszero = (::fabs(mantissa) < ((std::numeric_limits::min)() * (1.0 + std::numeric_limits::epsilon()))); - - if(mantissa_is_iszero) - { - std::fill(data.begin(), data.end(), static_cast(0u)); - return; - } - - const bool b_neg = (mantissa < 0.0); - - double d = ((!b_neg) ? mantissa : -mantissa); - ExponentType e = exponent; - - while(d > 10.0) { d /= 10.0; ++e; } - while(d < 1.0) { d *= 10.0; --e; } - - boost::int32_t shift = static_cast(e % static_cast(cpp_dec_float_elem_digits10)); - - while(static_cast(shift-- % cpp_dec_float_elem_digits10) != static_cast(0)) - { - d *= 10.0; - --e; - } - - exp = e; - neg = b_neg; - - std::fill(data.begin(), data.end(), static_cast(0u)); - - static const boost::int32_t digit_ratio = static_cast(static_cast(std::numeric_limits::digits10) / static_cast(cpp_dec_float_elem_digits10)); - static const boost::int32_t digit_loops = static_cast(digit_ratio + static_cast(2)); - - for(boost::int32_t i = static_cast(0); i < digit_loops; i++) - { - boost::uint32_t n = static_cast(static_cast(d)); - data[i] = static_cast(n); - d -= static_cast(n); - d *= static_cast(cpp_dec_float_elem_mask); - } +cpp_dec_float::cpp_dec_float( + const double mantissa, const ExponentType exponent) + : data(), exp(static_cast(0)), neg(false), + fpclass(cpp_dec_float_finite), prec_elem(cpp_dec_float_elem_number) { + // Create *this cpp_dec_float from a given + // mantissa and exponent. Note: This constructor does not maintain the full + // precision of double. + + const bool mantissa_is_iszero = + (::fabs(mantissa) < ((std::numeric_limits::min)() * + (1.0 + std::numeric_limits::epsilon()))); + + if (mantissa_is_iszero) { + std::fill(data.begin(), data.end(), static_cast(0u)); + return; + } + + const bool b_neg = (mantissa < 0.0); + + double d = ((!b_neg) ? mantissa : -mantissa); + ExponentType e = exponent; + + while (d > 10.0) { + d /= 10.0; + ++e; + } + while (d < 1.0) { + d *= 10.0; + --e; + } + + boost::int32_t shift = static_cast( + e % static_cast(cpp_dec_float_elem_digits10)); + + while (static_cast(shift-- % cpp_dec_float_elem_digits10) != + static_cast(0)) { + d *= 10.0; + --e; + } + + exp = e; + neg = b_neg; + + std::fill(data.begin(), data.end(), static_cast(0u)); + + static const boost::int32_t digit_ratio = static_cast( + static_cast(std::numeric_limits::digits10) / + static_cast(cpp_dec_float_elem_digits10)); + static const boost::int32_t digit_loops = + static_cast(digit_ratio + static_cast(2)); + + for (boost::int32_t i = static_cast(0); i < digit_loops; + i++) { + boost::uint32_t n = + static_cast(static_cast(d)); + data[i] = static_cast(n); + d -= static_cast(n); + d *= static_cast(cpp_dec_float_elem_mask); + } } template -cpp_dec_float& cpp_dec_float::operator= (long double a) -{ - // Christopher Kormanyos's original code used a cast to boost::long_long_type here, but that fails - // when long double has more digits than a boost::long_long_type. - using std::frexp; - using std::ldexp; - using std::floor; - - if(a == 0) - return *this = zero(); - - if(a == 1) - return *this = one(); - - if((boost::math::isinf)(a)) - { - *this = inf(); - if(a < 0) - this->negate(); - return *this; - } - - if((boost::math::isnan)(a)) - return *this = nan(); - - int e; - long double f, term; - *this = zero(); - - f = frexp(a, &e); - // See https://svn.boost.org/trac/boost/ticket/10924 for an example of why this may go wrong: - BOOST_ASSERT((boost::math::isfinite)(f)); - - static const int shift = std::numeric_limits::digits - 1; - - while(f) - { - // extract int sized bits from f: - f = ldexp(f, shift); - BOOST_ASSERT((boost::math::isfinite)(f)); - term = floor(f); - e -= shift; - *this *= pow2(shift); - if(term > 0) - add_unsigned_long_long(static_cast(term)); - else - sub_unsigned_long_long(static_cast(-term)); - f -= term; - } - - if(e != 0) - *this *= pow2(e); - - return *this; +cpp_dec_float & +cpp_dec_float::operator=(long double a) { + // Christopher Kormanyos's original code used a cast to boost::long_long_type + // here, but that fails when long double has more digits than a + // boost::long_long_type. + using std::floor; + using std::frexp; + using std::ldexp; + + if (a == 0) + return *this = zero(); + + if (a == 1) + return *this = one(); + + if ((boost::math::isinf)(a)) { + *this = inf(); + if (a < 0) + this->negate(); + return *this; + } + + if ((boost::math::isnan)(a)) + return *this = nan(); + + int e; + long double f, term; + *this = zero(); + + f = frexp(a, &e); + // See https://svn.boost.org/trac/boost/ticket/10924 for an example of why + // this may go wrong: + BOOST_ASSERT((boost::math::isfinite)(f)); + + static const int shift = std::numeric_limits::digits - 1; + + while (f) { + // extract int sized bits from f: + f = ldexp(f, shift); + BOOST_ASSERT((boost::math::isfinite)(f)); + term = floor(f); + e -= shift; + *this *= pow2(shift); + if (term > 0) + add_unsigned_long_long(static_cast(term)); + else + sub_unsigned_long_long(static_cast(-term)); + f -= term; + } + + if (e != 0) + *this *= pow2(e); + + return *this; } template -void cpp_dec_float::from_unsigned_long_long(const boost::ulong_long_type u) -{ - std::fill(data.begin(), data.end(), static_cast(0u)); +void cpp_dec_float::from_unsigned_long_long( + const boost::ulong_long_type u) { + std::fill(data.begin(), data.end(), static_cast(0u)); - exp = static_cast(0); - neg = false; - fpclass = cpp_dec_float_finite; - prec_elem = cpp_dec_float_elem_number; + exp = static_cast(0); + neg = false; + fpclass = cpp_dec_float_finite; + prec_elem = cpp_dec_float_elem_number; - if(u == 0) - { - return; - } + if (u == 0) { + return; + } - std::size_t i =static_cast(0u); + std::size_t i = static_cast(0u); - boost::ulong_long_type uu = u; + boost::ulong_long_type uu = u; - boost::uint32_t temp[(std::numeric_limits::digits10 / static_cast(cpp_dec_float_elem_digits10)) + 3] = { static_cast(0u) }; + boost::uint32_t temp[(std::numeric_limits::digits10 / + static_cast(cpp_dec_float_elem_digits10)) + + 3] = {static_cast(0u)}; - while(uu != static_cast(0u)) - { - temp[i] = static_cast(uu % static_cast(cpp_dec_float_elem_mask)); - uu = static_cast(uu / static_cast(cpp_dec_float_elem_mask)); - ++i; - } + while (uu != static_cast(0u)) { + temp[i] = static_cast( + uu % static_cast(cpp_dec_float_elem_mask)); + uu = static_cast( + uu / static_cast(cpp_dec_float_elem_mask)); + ++i; + } - if(i > static_cast(1u)) - { - exp += static_cast((i - 1u) * static_cast(cpp_dec_float_elem_digits10)); - } + if (i > static_cast(1u)) { + exp += static_cast( + (i - 1u) * static_cast(cpp_dec_float_elem_digits10)); + } - std::reverse(temp, temp + i); - std::copy(temp, temp + (std::min)(i, static_cast(cpp_dec_float_elem_number)), data.begin()); + std::reverse(temp, temp + i); + std::copy( + temp, + temp + (std::min)(i, static_cast(cpp_dec_float_elem_number)), + data.begin()); } template -boost::uint32_t cpp_dec_float::mul_loop_uv(boost::uint32_t* const u, const boost::uint32_t* const v, const boost::int32_t p) -{ - // - // There is a limit on how many limbs this algorithm can handle without dropping digits - // due to overflow in the carry, it is: - // - // FLOOR( (2^64 - 1) / (10^8 * 10^8) ) == 1844 - // - BOOST_STATIC_ASSERT_MSG(cpp_dec_float_elem_number < 1800, "Too many limbs in the data type for the multiplication algorithm - unsupported precision in cpp_dec_float."); - - boost::uint64_t carry = static_cast(0u); - - for(boost::int32_t j = static_cast(p - 1u); j >= static_cast(0); j--) - { - boost::uint64_t sum = carry; - - for(boost::int32_t i = j; i >= static_cast(0); i--) - { - sum += static_cast(u[j - i] * static_cast(v[i])); - } - - u[j] = static_cast(sum % static_cast(cpp_dec_float_elem_mask)); - carry = static_cast(sum / static_cast(cpp_dec_float_elem_mask)); - } - - return static_cast(carry); +boost::uint32_t cpp_dec_float::mul_loop_uv( + boost::uint32_t *const u, const boost::uint32_t *const v, + const boost::int32_t p) { + // + // There is a limit on how many limbs this algorithm can handle without + // dropping digits due to overflow in the carry, it is: + // + // FLOOR( (2^64 - 1) / (10^8 * 10^8) ) == 1844 + // + BOOST_STATIC_ASSERT_MSG( + cpp_dec_float_elem_number < 1800, + "Too many limbs in the data type for the multiplication algorithm - " + "unsupported precision in cpp_dec_float."); + + boost::uint64_t carry = static_cast(0u); + + for (boost::int32_t j = static_cast(p - 1u); + j >= static_cast(0); j--) { + boost::uint64_t sum = carry; + + for (boost::int32_t i = j; i >= static_cast(0); i--) { + sum += static_cast(u[j - i] * + static_cast(v[i])); + } + + u[j] = static_cast( + sum % static_cast(cpp_dec_float_elem_mask)); + carry = static_cast( + sum / static_cast(cpp_dec_float_elem_mask)); + } + + return static_cast(carry); } template -boost::uint32_t cpp_dec_float::mul_loop_n(boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p) -{ - boost::uint64_t carry = static_cast(0u); - - // Multiplication loop. - for(boost::int32_t j = p - 1; j >= static_cast(0); j--) - { - const boost::uint64_t t = static_cast(carry + static_cast(u[j] * static_cast(n))); - carry = static_cast(t / static_cast(cpp_dec_float_elem_mask)); - u[j] = static_cast(t - static_cast(static_cast(cpp_dec_float_elem_mask) * static_cast(carry))); - } - - return static_cast(carry); +boost::uint32_t cpp_dec_float::mul_loop_n( + boost::uint32_t *const u, boost::uint32_t n, const boost::int32_t p) { + boost::uint64_t carry = static_cast(0u); + + // Multiplication loop. + for (boost::int32_t j = p - 1; j >= static_cast(0); j--) { + const boost::uint64_t t = static_cast( + carry + + static_cast(u[j] * static_cast(n))); + carry = static_cast( + t / static_cast(cpp_dec_float_elem_mask)); + u[j] = static_cast( + t - static_cast( + static_cast(cpp_dec_float_elem_mask) * + static_cast(carry))); + } + + return static_cast(carry); } template -boost::uint32_t cpp_dec_float::div_loop_n(boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p) -{ - boost::uint64_t prev = static_cast(0u); +boost::uint32_t cpp_dec_float::div_loop_n( + boost::uint32_t *const u, boost::uint32_t n, const boost::int32_t p) { + boost::uint64_t prev = static_cast(0u); - for(boost::int32_t j = static_cast(0); j < p; j++) - { - const boost::uint64_t t = static_cast(u[j] + static_cast(prev * static_cast(cpp_dec_float_elem_mask))); - u[j] = static_cast(t / n); - prev = static_cast(t - static_cast(n * static_cast(u[j]))); - } + for (boost::int32_t j = static_cast(0); j < p; j++) { + const boost::uint64_t t = static_cast( + u[j] + + static_cast( + prev * static_cast(cpp_dec_float_elem_mask))); + u[j] = static_cast(t / n); + prev = static_cast( + t - + static_cast(n * static_cast(u[j]))); + } - return static_cast(prev); + return static_cast(prev); } template -cpp_dec_float cpp_dec_float::pow2(const boost::long_long_type p) -{ - // Create a static const table of p^2 for -128 < p < +128. - // Note: The size of this table must be odd-numbered and - // symmetric about 0. - init.do_nothing(); - static const boost::array, 255u> p2_data = - {{ - cpp_dec_float("5.877471754111437539843682686111228389093327783860437607543758531392086297273635864257812500000000000e-39"), - cpp_dec_float("1.175494350822287507968736537222245677818665556772087521508751706278417259454727172851562500000000000e-38"), - cpp_dec_float("2.350988701644575015937473074444491355637331113544175043017503412556834518909454345703125000000000000e-38"), - cpp_dec_float("4.701977403289150031874946148888982711274662227088350086035006825113669037818908691406250000000000000e-38"), - cpp_dec_float("9.403954806578300063749892297777965422549324454176700172070013650227338075637817382812500000000000000e-38"), - cpp_dec_float("1.880790961315660012749978459555593084509864890835340034414002730045467615127563476562500000000000000e-37"), - cpp_dec_float("3.761581922631320025499956919111186169019729781670680068828005460090935230255126953125000000000000000e-37"), - cpp_dec_float("7.523163845262640050999913838222372338039459563341360137656010920181870460510253906250000000000000000e-37"), - cpp_dec_float("1.504632769052528010199982767644474467607891912668272027531202184036374092102050781250000000000000000e-36"), - cpp_dec_float("3.009265538105056020399965535288948935215783825336544055062404368072748184204101562500000000000000000e-36"), - cpp_dec_float("6.018531076210112040799931070577897870431567650673088110124808736145496368408203125000000000000000000e-36"), - cpp_dec_float("1.203706215242022408159986214115579574086313530134617622024961747229099273681640625000000000000000000e-35"), - cpp_dec_float("2.407412430484044816319972428231159148172627060269235244049923494458198547363281250000000000000000000e-35"), - cpp_dec_float("4.814824860968089632639944856462318296345254120538470488099846988916397094726562500000000000000000000e-35"), - cpp_dec_float("9.629649721936179265279889712924636592690508241076940976199693977832794189453125000000000000000000000e-35"), - cpp_dec_float("1.925929944387235853055977942584927318538101648215388195239938795566558837890625000000000000000000000e-34"), - cpp_dec_float("3.851859888774471706111955885169854637076203296430776390479877591133117675781250000000000000000000000e-34"), - cpp_dec_float("7.703719777548943412223911770339709274152406592861552780959755182266235351562500000000000000000000000e-34"), - cpp_dec_float("1.540743955509788682444782354067941854830481318572310556191951036453247070312500000000000000000000000e-33"), - cpp_dec_float("3.081487911019577364889564708135883709660962637144621112383902072906494140625000000000000000000000000e-33"), - cpp_dec_float("6.162975822039154729779129416271767419321925274289242224767804145812988281250000000000000000000000000e-33"), - cpp_dec_float("1.232595164407830945955825883254353483864385054857848444953560829162597656250000000000000000000000000e-32"), - cpp_dec_float("2.465190328815661891911651766508706967728770109715696889907121658325195312500000000000000000000000000e-32"), - cpp_dec_float("4.930380657631323783823303533017413935457540219431393779814243316650390625000000000000000000000000000e-32"), - cpp_dec_float("9.860761315262647567646607066034827870915080438862787559628486633300781250000000000000000000000000000e-32"), - cpp_dec_float("1.972152263052529513529321413206965574183016087772557511925697326660156250000000000000000000000000000e-31"), - cpp_dec_float("3.944304526105059027058642826413931148366032175545115023851394653320312500000000000000000000000000000e-31"), - cpp_dec_float("7.888609052210118054117285652827862296732064351090230047702789306640625000000000000000000000000000000e-31"), - cpp_dec_float("1.577721810442023610823457130565572459346412870218046009540557861328125000000000000000000000000000000e-30"), - cpp_dec_float("3.155443620884047221646914261131144918692825740436092019081115722656250000000000000000000000000000000e-30"), - cpp_dec_float("6.310887241768094443293828522262289837385651480872184038162231445312500000000000000000000000000000000e-30"), - cpp_dec_float("1.262177448353618888658765704452457967477130296174436807632446289062500000000000000000000000000000000e-29"), - cpp_dec_float("2.524354896707237777317531408904915934954260592348873615264892578125000000000000000000000000000000000e-29"), - cpp_dec_float("5.048709793414475554635062817809831869908521184697747230529785156250000000000000000000000000000000000e-29"), - cpp_dec_float("1.009741958682895110927012563561966373981704236939549446105957031250000000000000000000000000000000000e-28"), - cpp_dec_float("2.019483917365790221854025127123932747963408473879098892211914062500000000000000000000000000000000000e-28"), - cpp_dec_float("4.038967834731580443708050254247865495926816947758197784423828125000000000000000000000000000000000000e-28"), - cpp_dec_float("8.077935669463160887416100508495730991853633895516395568847656250000000000000000000000000000000000000e-28"), - cpp_dec_float("1.615587133892632177483220101699146198370726779103279113769531250000000000000000000000000000000000000e-27"), - cpp_dec_float("3.231174267785264354966440203398292396741453558206558227539062500000000000000000000000000000000000000e-27"), - cpp_dec_float("6.462348535570528709932880406796584793482907116413116455078125000000000000000000000000000000000000000e-27"), - cpp_dec_float("1.292469707114105741986576081359316958696581423282623291015625000000000000000000000000000000000000000e-26"), - cpp_dec_float("2.584939414228211483973152162718633917393162846565246582031250000000000000000000000000000000000000000e-26"), - cpp_dec_float("5.169878828456422967946304325437267834786325693130493164062500000000000000000000000000000000000000000e-26"), - cpp_dec_float("1.033975765691284593589260865087453566957265138626098632812500000000000000000000000000000000000000000e-25"), - cpp_dec_float("2.067951531382569187178521730174907133914530277252197265625000000000000000000000000000000000000000000e-25"), - cpp_dec_float("4.135903062765138374357043460349814267829060554504394531250000000000000000000000000000000000000000000e-25"), - cpp_dec_float("8.271806125530276748714086920699628535658121109008789062500000000000000000000000000000000000000000000e-25"), - cpp_dec_float("1.654361225106055349742817384139925707131624221801757812500000000000000000000000000000000000000000000e-24"), - cpp_dec_float("3.308722450212110699485634768279851414263248443603515625000000000000000000000000000000000000000000000e-24"), - cpp_dec_float("6.617444900424221398971269536559702828526496887207031250000000000000000000000000000000000000000000000e-24"), - cpp_dec_float("1.323488980084844279794253907311940565705299377441406250000000000000000000000000000000000000000000000e-23"), - cpp_dec_float("2.646977960169688559588507814623881131410598754882812500000000000000000000000000000000000000000000000e-23"), - cpp_dec_float("5.293955920339377119177015629247762262821197509765625000000000000000000000000000000000000000000000000e-23"), - cpp_dec_float("1.058791184067875423835403125849552452564239501953125000000000000000000000000000000000000000000000000e-22"), - cpp_dec_float("2.117582368135750847670806251699104905128479003906250000000000000000000000000000000000000000000000000e-22"), - cpp_dec_float("4.235164736271501695341612503398209810256958007812500000000000000000000000000000000000000000000000000e-22"), - cpp_dec_float("8.470329472543003390683225006796419620513916015625000000000000000000000000000000000000000000000000000e-22"), - cpp_dec_float("1.694065894508600678136645001359283924102783203125000000000000000000000000000000000000000000000000000e-21"), - cpp_dec_float("3.388131789017201356273290002718567848205566406250000000000000000000000000000000000000000000000000000e-21"), - cpp_dec_float("6.776263578034402712546580005437135696411132812500000000000000000000000000000000000000000000000000000e-21"), - cpp_dec_float("1.355252715606880542509316001087427139282226562500000000000000000000000000000000000000000000000000000e-20"), - cpp_dec_float("2.710505431213761085018632002174854278564453125000000000000000000000000000000000000000000000000000000e-20"), - cpp_dec_float("5.421010862427522170037264004349708557128906250000000000000000000000000000000000000000000000000000000e-20"), - cpp_dec_float("1.084202172485504434007452800869941711425781250000000000000000000000000000000000000000000000000000000e-19"), - cpp_dec_float("2.168404344971008868014905601739883422851562500000000000000000000000000000000000000000000000000000000e-19"), - cpp_dec_float("4.336808689942017736029811203479766845703125000000000000000000000000000000000000000000000000000000000e-19"), - cpp_dec_float("8.673617379884035472059622406959533691406250000000000000000000000000000000000000000000000000000000000e-19"), - cpp_dec_float("1.734723475976807094411924481391906738281250000000000000000000000000000000000000000000000000000000000e-18"), - cpp_dec_float("3.469446951953614188823848962783813476562500000000000000000000000000000000000000000000000000000000000e-18"), - cpp_dec_float("6.938893903907228377647697925567626953125000000000000000000000000000000000000000000000000000000000000e-18"), - cpp_dec_float("1.387778780781445675529539585113525390625000000000000000000000000000000000000000000000000000000000000e-17"), - cpp_dec_float("2.775557561562891351059079170227050781250000000000000000000000000000000000000000000000000000000000000e-17"), - cpp_dec_float("5.551115123125782702118158340454101562500000000000000000000000000000000000000000000000000000000000000e-17"), - cpp_dec_float("1.110223024625156540423631668090820312500000000000000000000000000000000000000000000000000000000000000e-16"), - cpp_dec_float("2.220446049250313080847263336181640625000000000000000000000000000000000000000000000000000000000000000e-16"), - cpp_dec_float("4.440892098500626161694526672363281250000000000000000000000000000000000000000000000000000000000000000e-16"), - cpp_dec_float("8.881784197001252323389053344726562500000000000000000000000000000000000000000000000000000000000000000e-16"), - cpp_dec_float("1.776356839400250464677810668945312500000000000000000000000000000000000000000000000000000000000000000e-15"), - cpp_dec_float("3.552713678800500929355621337890625000000000000000000000000000000000000000000000000000000000000000000e-15"), - cpp_dec_float("7.105427357601001858711242675781250000000000000000000000000000000000000000000000000000000000000000000e-15"), - cpp_dec_float("1.421085471520200371742248535156250000000000000000000000000000000000000000000000000000000000000000000e-14"), - cpp_dec_float("2.842170943040400743484497070312500000000000000000000000000000000000000000000000000000000000000000000e-14"), - cpp_dec_float("5.684341886080801486968994140625000000000000000000000000000000000000000000000000000000000000000000000e-14"), - cpp_dec_float("1.136868377216160297393798828125000000000000000000000000000000000000000000000000000000000000000000000e-13"), - cpp_dec_float("2.273736754432320594787597656250000000000000000000000000000000000000000000000000000000000000000000000e-13"), - cpp_dec_float("4.547473508864641189575195312500000000000000000000000000000000000000000000000000000000000000000000000e-13"), - cpp_dec_float("9.094947017729282379150390625000000000000000000000000000000000000000000000000000000000000000000000000e-13"), - cpp_dec_float("1.818989403545856475830078125000000000000000000000000000000000000000000000000000000000000000000000000e-12"), - cpp_dec_float("3.637978807091712951660156250000000000000000000000000000000000000000000000000000000000000000000000000e-12"), - cpp_dec_float("7.275957614183425903320312500000000000000000000000000000000000000000000000000000000000000000000000000e-12"), - cpp_dec_float("1.455191522836685180664062500000000000000000000000000000000000000000000000000000000000000000000000000e-11"), - cpp_dec_float("2.910383045673370361328125000000000000000000000000000000000000000000000000000000000000000000000000000e-11"), - cpp_dec_float("5.820766091346740722656250000000000000000000000000000000000000000000000000000000000000000000000000000e-11"), - cpp_dec_float("1.164153218269348144531250000000000000000000000000000000000000000000000000000000000000000000000000000e-10"), - cpp_dec_float("2.328306436538696289062500000000000000000000000000000000000000000000000000000000000000000000000000000e-10"), - cpp_dec_float("4.656612873077392578125000000000000000000000000000000000000000000000000000000000000000000000000000000e-10"), - cpp_dec_float("9.313225746154785156250000000000000000000000000000000000000000000000000000000000000000000000000000000e-10"), - cpp_dec_float("1.862645149230957031250000000000000000000000000000000000000000000000000000000000000000000000000000000e-9"), - cpp_dec_float("3.725290298461914062500000000000000000000000000000000000000000000000000000000000000000000000000000000e-9"), - cpp_dec_float("7.450580596923828125000000000000000000000000000000000000000000000000000000000000000000000000000000000e-9"), - cpp_dec_float("1.490116119384765625000000000000000000000000000000000000000000000000000000000000000000000000000000000e-8"), - cpp_dec_float("2.980232238769531250000000000000000000000000000000000000000000000000000000000000000000000000000000000e-8"), - cpp_dec_float("5.960464477539062500000000000000000000000000000000000000000000000000000000000000000000000000000000000e-8"), - cpp_dec_float("1.192092895507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"), - cpp_dec_float("2.384185791015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"), - cpp_dec_float("4.768371582031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"), - cpp_dec_float("9.536743164062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"), - cpp_dec_float("1.907348632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6"), - cpp_dec_float("3.814697265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6"), - cpp_dec_float("7.629394531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6"), - cpp_dec_float("0.000015258789062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.000030517578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.000061035156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.000122070312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.000244140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.000488281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.000976562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.001953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.003906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.007812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.01562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.03125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.06250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - cpp_dec_float("0.125"), - cpp_dec_float("0.25"), - cpp_dec_float("0.5"), - one(), - two(), - cpp_dec_float(static_cast(4)), - cpp_dec_float(static_cast(8)), - cpp_dec_float(static_cast(16)), - cpp_dec_float(static_cast(32)), - cpp_dec_float(static_cast(64)), - cpp_dec_float(static_cast(128)), - cpp_dec_float(static_cast(256)), - cpp_dec_float(static_cast(512)), - cpp_dec_float(static_cast(1024)), - cpp_dec_float(static_cast(2048)), - cpp_dec_float(static_cast(4096)), - cpp_dec_float(static_cast(8192)), - cpp_dec_float(static_cast(16384)), - cpp_dec_float(static_cast(32768)), - cpp_dec_float(static_cast(65536)), - cpp_dec_float(static_cast(131072)), - cpp_dec_float(static_cast(262144)), - cpp_dec_float(static_cast(524288)), - cpp_dec_float(static_cast(1uL << 20u)), - cpp_dec_float(static_cast(1uL << 21u)), - cpp_dec_float(static_cast(1uL << 22u)), - cpp_dec_float(static_cast(1uL << 23u)), - cpp_dec_float(static_cast(1uL << 24u)), - cpp_dec_float(static_cast(1uL << 25u)), - cpp_dec_float(static_cast(1uL << 26u)), - cpp_dec_float(static_cast(1uL << 27u)), - cpp_dec_float(static_cast(1uL << 28u)), - cpp_dec_float(static_cast(1uL << 29u)), - cpp_dec_float(static_cast(1uL << 30u)), - cpp_dec_float(static_cast(1uL << 31u)), - cpp_dec_float(static_cast(1uLL << 32u)), - cpp_dec_float(static_cast(1uLL << 33u)), - cpp_dec_float(static_cast(1uLL << 34u)), - cpp_dec_float(static_cast(1uLL << 35u)), - cpp_dec_float(static_cast(1uLL << 36u)), - cpp_dec_float(static_cast(1uLL << 37u)), - cpp_dec_float(static_cast(1uLL << 38u)), - cpp_dec_float(static_cast(1uLL << 39u)), - cpp_dec_float(static_cast(1uLL << 40u)), - cpp_dec_float(static_cast(1uLL << 41u)), - cpp_dec_float(static_cast(1uLL << 42u)), - cpp_dec_float(static_cast(1uLL << 43u)), - cpp_dec_float(static_cast(1uLL << 44u)), - cpp_dec_float(static_cast(1uLL << 45u)), - cpp_dec_float(static_cast(1uLL << 46u)), - cpp_dec_float(static_cast(1uLL << 47u)), - cpp_dec_float(static_cast(1uLL << 48u)), - cpp_dec_float(static_cast(1uLL << 49u)), - cpp_dec_float(static_cast(1uLL << 50u)), - cpp_dec_float(static_cast(1uLL << 51u)), - cpp_dec_float(static_cast(1uLL << 52u)), - cpp_dec_float(static_cast(1uLL << 53u)), - cpp_dec_float(static_cast(1uLL << 54u)), - cpp_dec_float(static_cast(1uLL << 55u)), - cpp_dec_float(static_cast(1uLL << 56u)), - cpp_dec_float(static_cast(1uLL << 57u)), - cpp_dec_float(static_cast(1uLL << 58u)), - cpp_dec_float(static_cast(1uLL << 59u)), - cpp_dec_float(static_cast(1uLL << 60u)), - cpp_dec_float(static_cast(1uLL << 61u)), - cpp_dec_float(static_cast(1uLL << 62u)), - cpp_dec_float(static_cast(1uLL << 63u)), - cpp_dec_float("1.844674407370955161600000000000000000000000000000000000000000000000000000000000000000000000000000000e19"), - cpp_dec_float("3.689348814741910323200000000000000000000000000000000000000000000000000000000000000000000000000000000e19"), - cpp_dec_float("7.378697629483820646400000000000000000000000000000000000000000000000000000000000000000000000000000000e19"), - cpp_dec_float("1.475739525896764129280000000000000000000000000000000000000000000000000000000000000000000000000000000e20"), - cpp_dec_float("2.951479051793528258560000000000000000000000000000000000000000000000000000000000000000000000000000000e20"), - cpp_dec_float("5.902958103587056517120000000000000000000000000000000000000000000000000000000000000000000000000000000e20"), - cpp_dec_float("1.180591620717411303424000000000000000000000000000000000000000000000000000000000000000000000000000000e21"), - cpp_dec_float("2.361183241434822606848000000000000000000000000000000000000000000000000000000000000000000000000000000e21"), - cpp_dec_float("4.722366482869645213696000000000000000000000000000000000000000000000000000000000000000000000000000000e21"), - cpp_dec_float("9.444732965739290427392000000000000000000000000000000000000000000000000000000000000000000000000000000e21"), - cpp_dec_float("1.888946593147858085478400000000000000000000000000000000000000000000000000000000000000000000000000000e22"), - cpp_dec_float("3.777893186295716170956800000000000000000000000000000000000000000000000000000000000000000000000000000e22"), - cpp_dec_float("7.555786372591432341913600000000000000000000000000000000000000000000000000000000000000000000000000000e22"), - cpp_dec_float("1.511157274518286468382720000000000000000000000000000000000000000000000000000000000000000000000000000e23"), - cpp_dec_float("3.022314549036572936765440000000000000000000000000000000000000000000000000000000000000000000000000000e23"), - cpp_dec_float("6.044629098073145873530880000000000000000000000000000000000000000000000000000000000000000000000000000e23"), - cpp_dec_float("1.208925819614629174706176000000000000000000000000000000000000000000000000000000000000000000000000000e24"), - cpp_dec_float("2.417851639229258349412352000000000000000000000000000000000000000000000000000000000000000000000000000e24"), - cpp_dec_float("4.835703278458516698824704000000000000000000000000000000000000000000000000000000000000000000000000000e24"), - cpp_dec_float("9.671406556917033397649408000000000000000000000000000000000000000000000000000000000000000000000000000e24"), - cpp_dec_float("1.934281311383406679529881600000000000000000000000000000000000000000000000000000000000000000000000000e25"), - cpp_dec_float("3.868562622766813359059763200000000000000000000000000000000000000000000000000000000000000000000000000e25"), - cpp_dec_float("7.737125245533626718119526400000000000000000000000000000000000000000000000000000000000000000000000000e25"), - cpp_dec_float("1.547425049106725343623905280000000000000000000000000000000000000000000000000000000000000000000000000e26"), - cpp_dec_float("3.094850098213450687247810560000000000000000000000000000000000000000000000000000000000000000000000000e26"), - cpp_dec_float("6.189700196426901374495621120000000000000000000000000000000000000000000000000000000000000000000000000e26"), - cpp_dec_float("1.237940039285380274899124224000000000000000000000000000000000000000000000000000000000000000000000000e27"), - cpp_dec_float("2.475880078570760549798248448000000000000000000000000000000000000000000000000000000000000000000000000e27"), - cpp_dec_float("4.951760157141521099596496896000000000000000000000000000000000000000000000000000000000000000000000000e27"), - cpp_dec_float("9.903520314283042199192993792000000000000000000000000000000000000000000000000000000000000000000000000e27"), - cpp_dec_float("1.980704062856608439838598758400000000000000000000000000000000000000000000000000000000000000000000000e28"), - cpp_dec_float("3.961408125713216879677197516800000000000000000000000000000000000000000000000000000000000000000000000e28"), - cpp_dec_float("7.922816251426433759354395033600000000000000000000000000000000000000000000000000000000000000000000000e28"), - cpp_dec_float("1.584563250285286751870879006720000000000000000000000000000000000000000000000000000000000000000000000e29"), - cpp_dec_float("3.169126500570573503741758013440000000000000000000000000000000000000000000000000000000000000000000000e29"), - cpp_dec_float("6.338253001141147007483516026880000000000000000000000000000000000000000000000000000000000000000000000e29"), - cpp_dec_float("1.267650600228229401496703205376000000000000000000000000000000000000000000000000000000000000000000000e30"), - cpp_dec_float("2.535301200456458802993406410752000000000000000000000000000000000000000000000000000000000000000000000e30"), - cpp_dec_float("5.070602400912917605986812821504000000000000000000000000000000000000000000000000000000000000000000000e30"), - cpp_dec_float("1.014120480182583521197362564300800000000000000000000000000000000000000000000000000000000000000000000e31"), - cpp_dec_float("2.028240960365167042394725128601600000000000000000000000000000000000000000000000000000000000000000000e31"), - cpp_dec_float("4.056481920730334084789450257203200000000000000000000000000000000000000000000000000000000000000000000e31"), - cpp_dec_float("8.112963841460668169578900514406400000000000000000000000000000000000000000000000000000000000000000000e31"), - cpp_dec_float("1.622592768292133633915780102881280000000000000000000000000000000000000000000000000000000000000000000e32"), - cpp_dec_float("3.245185536584267267831560205762560000000000000000000000000000000000000000000000000000000000000000000e32"), - cpp_dec_float("6.490371073168534535663120411525120000000000000000000000000000000000000000000000000000000000000000000e32"), - cpp_dec_float("1.298074214633706907132624082305024000000000000000000000000000000000000000000000000000000000000000000e33"), - cpp_dec_float("2.596148429267413814265248164610048000000000000000000000000000000000000000000000000000000000000000000e33"), - cpp_dec_float("5.192296858534827628530496329220096000000000000000000000000000000000000000000000000000000000000000000e33"), - cpp_dec_float("1.038459371706965525706099265844019200000000000000000000000000000000000000000000000000000000000000000e34"), - cpp_dec_float("2.076918743413931051412198531688038400000000000000000000000000000000000000000000000000000000000000000e34"), - cpp_dec_float("4.153837486827862102824397063376076800000000000000000000000000000000000000000000000000000000000000000e34"), - cpp_dec_float("8.307674973655724205648794126752153600000000000000000000000000000000000000000000000000000000000000000e34"), - cpp_dec_float("1.661534994731144841129758825350430720000000000000000000000000000000000000000000000000000000000000000e35"), - cpp_dec_float("3.323069989462289682259517650700861440000000000000000000000000000000000000000000000000000000000000000e35"), - cpp_dec_float("6.646139978924579364519035301401722880000000000000000000000000000000000000000000000000000000000000000e35"), - cpp_dec_float("1.329227995784915872903807060280344576000000000000000000000000000000000000000000000000000000000000000e36"), - cpp_dec_float("2.658455991569831745807614120560689152000000000000000000000000000000000000000000000000000000000000000e36"), - cpp_dec_float("5.316911983139663491615228241121378304000000000000000000000000000000000000000000000000000000000000000e36"), - cpp_dec_float("1.063382396627932698323045648224275660800000000000000000000000000000000000000000000000000000000000000e37"), - cpp_dec_float("2.126764793255865396646091296448551321600000000000000000000000000000000000000000000000000000000000000e37"), - cpp_dec_float("4.253529586511730793292182592897102643200000000000000000000000000000000000000000000000000000000000000e37"), - cpp_dec_float("8.507059173023461586584365185794205286400000000000000000000000000000000000000000000000000000000000000e37"), - cpp_dec_float("1.701411834604692317316873037158841057280000000000000000000000000000000000000000000000000000000000000e38") - }}; - - if((p > static_cast(-128)) && (p < static_cast(+128))) - { - return p2_data[static_cast(p + ((p2_data.size() - 1u) / 2u))]; - } - else - { - // Compute and return 2^p. - if(p < static_cast(0)) - { - return pow2(static_cast(-p)).calculate_inv(); - } - else - { - cpp_dec_float t; - default_ops::detail::pow_imp(t, two(), p, mpl::true_()); - return t; - } - } +cpp_dec_float +cpp_dec_float::pow2( + const boost::long_long_type p) { + // Create a static const table of p^2 for -128 < p < +128. + // Note: The size of this table must be odd-numbered and + // symmetric about 0. + init.do_nothing(); + static const boost::array, + 255u> + p2_data = { + {cpp_dec_float("5." + "87747175411143753984368268611122838909332778386043760" + "7543758531392086297273635864257812500000000000e-39"), + cpp_dec_float("1." + "17549435082228750796873653722224567781866555677208752" + "1508751706278417259454727172851562500000000000e-38"), + cpp_dec_float("2." + "35098870164457501593747307444449135563733111354417504" + "3017503412556834518909454345703125000000000000e-38"), + cpp_dec_float("4." + "70197740328915003187494614888898271127466222708835008" + "6035006825113669037818908691406250000000000000e-38"), + cpp_dec_float("9." + "40395480657830006374989229777796542254932445417670017" + "2070013650227338075637817382812500000000000000e-38"), + cpp_dec_float("1." + "88079096131566001274997845955559308450986489083534003" + "4414002730045467615127563476562500000000000000e-37"), + cpp_dec_float("3." + "76158192263132002549995691911118616901972978167068006" + "8828005460090935230255126953125000000000000000e-37"), + cpp_dec_float("7." + "52316384526264005099991383822237233803945956334136013" + "7656010920181870460510253906250000000000000000e-37"), + cpp_dec_float("1." + "50463276905252801019998276764447446760789191266827202" + "7531202184036374092102050781250000000000000000e-36"), + cpp_dec_float("3." + "00926553810505602039996553528894893521578382533654405" + "5062404368072748184204101562500000000000000000e-36"), + cpp_dec_float("6." + "01853107621011204079993107057789787043156765067308811" + "0124808736145496368408203125000000000000000000e-36"), + cpp_dec_float("1." + "20370621524202240815998621411557957408631353013461762" + "2024961747229099273681640625000000000000000000e-35"), + cpp_dec_float("2." + "40741243048404481631997242823115914817262706026923524" + "4049923494458198547363281250000000000000000000e-35"), + cpp_dec_float("4." + "81482486096808963263994485646231829634525412053847048" + "8099846988916397094726562500000000000000000000e-35"), + cpp_dec_float("9." + "62964972193617926527988971292463659269050824107694097" + "6199693977832794189453125000000000000000000000e-35"), + cpp_dec_float("1." + "92592994438723585305597794258492731853810164821538819" + "5239938795566558837890625000000000000000000000e-34"), + cpp_dec_float("3." + "85185988877447170611195588516985463707620329643077639" + "0479877591133117675781250000000000000000000000e-34"), + cpp_dec_float("7." + "70371977754894341222391177033970927415240659286155278" + "0959755182266235351562500000000000000000000000e-34"), + cpp_dec_float("1." + "54074395550978868244478235406794185483048131857231055" + "6191951036453247070312500000000000000000000000e-33"), + cpp_dec_float("3." + "08148791101957736488956470813588370966096263714462111" + "2383902072906494140625000000000000000000000000e-33"), + cpp_dec_float("6." + "16297582203915472977912941627176741932192527428924222" + "4767804145812988281250000000000000000000000000e-33"), + cpp_dec_float("1." + "23259516440783094595582588325435348386438505485784844" + "4953560829162597656250000000000000000000000000e-32"), + cpp_dec_float("2." + "46519032881566189191165176650870696772877010971569688" + "9907121658325195312500000000000000000000000000e-32"), + cpp_dec_float("4." + "93038065763132378382330353301741393545754021943139377" + "9814243316650390625000000000000000000000000000e-32"), + cpp_dec_float("9." + "86076131526264756764660706603482787091508043886278755" + "9628486633300781250000000000000000000000000000e-32"), + cpp_dec_float("1." + "97215226305252951352932141320696557418301608777255751" + "1925697326660156250000000000000000000000000000e-31"), + cpp_dec_float("3." + "94430452610505902705864282641393114836603217554511502" + "3851394653320312500000000000000000000000000000e-31"), + cpp_dec_float("7." + "88860905221011805411728565282786229673206435109023004" + "7702789306640625000000000000000000000000000000e-31"), + cpp_dec_float("1." + "57772181044202361082345713056557245934641287021804600" + "9540557861328125000000000000000000000000000000e-30"), + cpp_dec_float("3." + "15544362088404722164691426113114491869282574043609201" + "9081115722656250000000000000000000000000000000e-30"), + cpp_dec_float("6." + "31088724176809444329382852226228983738565148087218403" + "8162231445312500000000000000000000000000000000e-30"), + cpp_dec_float("1." + "26217744835361888865876570445245796747713029617443680" + "7632446289062500000000000000000000000000000000e-29"), + cpp_dec_float("2." + "52435489670723777731753140890491593495426059234887361" + "5264892578125000000000000000000000000000000000e-29"), + cpp_dec_float("5." + "04870979341447555463506281780983186990852118469774723" + "0529785156250000000000000000000000000000000000e-29"), + cpp_dec_float("1." + "00974195868289511092701256356196637398170423693954944" + "6105957031250000000000000000000000000000000000e-28"), + cpp_dec_float("2." + "01948391736579022185402512712393274796340847387909889" + "2211914062500000000000000000000000000000000000e-28"), + cpp_dec_float("4." + "03896783473158044370805025424786549592681694775819778" + "4423828125000000000000000000000000000000000000e-28"), + cpp_dec_float("8." + "07793566946316088741610050849573099185363389551639556" + "8847656250000000000000000000000000000000000000e-28"), + cpp_dec_float("1." + "61558713389263217748322010169914619837072677910327911" + "3769531250000000000000000000000000000000000000e-27"), + cpp_dec_float("3." + "23117426778526435496644020339829239674145355820655822" + "7539062500000000000000000000000000000000000000e-27"), + cpp_dec_float("6." + "46234853557052870993288040679658479348290711641311645" + "5078125000000000000000000000000000000000000000e-27"), + cpp_dec_float("1." + "29246970711410574198657608135931695869658142328262329" + "1015625000000000000000000000000000000000000000e-26"), + cpp_dec_float("2." + "58493941422821148397315216271863391739316284656524658" + "2031250000000000000000000000000000000000000000e-26"), + cpp_dec_float("5." + "16987882845642296794630432543726783478632569313049316" + "4062500000000000000000000000000000000000000000e-26"), + cpp_dec_float("1." + "03397576569128459358926086508745356695726513862609863" + "2812500000000000000000000000000000000000000000e-25"), + cpp_dec_float("2." + "06795153138256918717852173017490713391453027725219726" + "5625000000000000000000000000000000000000000000e-25"), + cpp_dec_float("4." + "13590306276513837435704346034981426782906055450439453" + "1250000000000000000000000000000000000000000000e-25"), + cpp_dec_float("8." + "27180612553027674871408692069962853565812110900878906" + "2500000000000000000000000000000000000000000000e-25"), + cpp_dec_float("1." + "65436122510605534974281738413992570713162422180175781" + "2500000000000000000000000000000000000000000000e-24"), + cpp_dec_float("3." + "30872245021211069948563476827985141426324844360351562" + "5000000000000000000000000000000000000000000000e-24"), + cpp_dec_float("6." + "61744490042422139897126953655970282852649688720703125" + "0000000000000000000000000000000000000000000000e-24"), + cpp_dec_float("1." + "32348898008484427979425390731194056570529937744140625" + "0000000000000000000000000000000000000000000000e-23"), + cpp_dec_float("2." + "64697796016968855958850781462388113141059875488281250" + "0000000000000000000000000000000000000000000000e-23"), + cpp_dec_float("5." + "29395592033937711917701562924776226282119750976562500" + "0000000000000000000000000000000000000000000000e-23"), + cpp_dec_float("1." + "05879118406787542383540312584955245256423950195312500" + "0000000000000000000000000000000000000000000000e-22"), + cpp_dec_float("2." + "11758236813575084767080625169910490512847900390625000" + "0000000000000000000000000000000000000000000000e-22"), + cpp_dec_float("4." + "23516473627150169534161250339820981025695800781250000" + "0000000000000000000000000000000000000000000000e-22"), + cpp_dec_float("8." + "47032947254300339068322500679641962051391601562500000" + "0000000000000000000000000000000000000000000000e-22"), + cpp_dec_float("1." + "69406589450860067813664500135928392410278320312500000" + "0000000000000000000000000000000000000000000000e-21"), + cpp_dec_float("3." + "38813178901720135627329000271856784820556640625000000" + "0000000000000000000000000000000000000000000000e-21"), + cpp_dec_float("6." + "77626357803440271254658000543713569641113281250000000" + "0000000000000000000000000000000000000000000000e-21"), + cpp_dec_float("1." + "35525271560688054250931600108742713928222656250000000" + "0000000000000000000000000000000000000000000000e-20"), + cpp_dec_float("2." + "71050543121376108501863200217485427856445312500000000" + "0000000000000000000000000000000000000000000000e-20"), + cpp_dec_float("5." + "42101086242752217003726400434970855712890625000000000" + "0000000000000000000000000000000000000000000000e-20"), + cpp_dec_float("1." + "08420217248550443400745280086994171142578125000000000" + "0000000000000000000000000000000000000000000000e-19"), + cpp_dec_float("2." + "16840434497100886801490560173988342285156250000000000" + "0000000000000000000000000000000000000000000000e-19"), + cpp_dec_float("4." + "33680868994201773602981120347976684570312500000000000" + "0000000000000000000000000000000000000000000000e-19"), + cpp_dec_float("8." + "67361737988403547205962240695953369140625000000000000" + "0000000000000000000000000000000000000000000000e-19"), + cpp_dec_float("1." + "73472347597680709441192448139190673828125000000000000" + "0000000000000000000000000000000000000000000000e-18"), + cpp_dec_float("3." + "46944695195361418882384896278381347656250000000000000" + "0000000000000000000000000000000000000000000000e-18"), + cpp_dec_float("6." + "93889390390722837764769792556762695312500000000000000" + "0000000000000000000000000000000000000000000000e-18"), + cpp_dec_float("1." + "38777878078144567552953958511352539062500000000000000" + "0000000000000000000000000000000000000000000000e-17"), + cpp_dec_float("2." + "77555756156289135105907917022705078125000000000000000" + "0000000000000000000000000000000000000000000000e-17"), + cpp_dec_float("5." + "55111512312578270211815834045410156250000000000000000" + "0000000000000000000000000000000000000000000000e-17"), + cpp_dec_float("1." + "11022302462515654042363166809082031250000000000000000" + "0000000000000000000000000000000000000000000000e-16"), + cpp_dec_float("2." + "22044604925031308084726333618164062500000000000000000" + "0000000000000000000000000000000000000000000000e-16"), + cpp_dec_float("4." + "44089209850062616169452667236328125000000000000000000" + "0000000000000000000000000000000000000000000000e-16"), + cpp_dec_float("8." + "88178419700125232338905334472656250000000000000000000" + "0000000000000000000000000000000000000000000000e-16"), + cpp_dec_float("1." + "77635683940025046467781066894531250000000000000000000" + "0000000000000000000000000000000000000000000000e-15"), + cpp_dec_float("3." + "55271367880050092935562133789062500000000000000000000" + "0000000000000000000000000000000000000000000000e-15"), + cpp_dec_float("7." + "10542735760100185871124267578125000000000000000000000" + "0000000000000000000000000000000000000000000000e-15"), + cpp_dec_float("1." + "42108547152020037174224853515625000000000000000000000" + "0000000000000000000000000000000000000000000000e-14"), + cpp_dec_float("2." + "84217094304040074348449707031250000000000000000000000" + "0000000000000000000000000000000000000000000000e-14"), + cpp_dec_float("5." + "68434188608080148696899414062500000000000000000000000" + "0000000000000000000000000000000000000000000000e-14"), + cpp_dec_float("1." + "13686837721616029739379882812500000000000000000000000" + "0000000000000000000000000000000000000000000000e-13"), + cpp_dec_float("2." + "27373675443232059478759765625000000000000000000000000" + "0000000000000000000000000000000000000000000000e-13"), + cpp_dec_float("4." + "54747350886464118957519531250000000000000000000000000" + "0000000000000000000000000000000000000000000000e-13"), + cpp_dec_float("9." + "09494701772928237915039062500000000000000000000000000" + "0000000000000000000000000000000000000000000000e-13"), + cpp_dec_float("1." + "81898940354585647583007812500000000000000000000000000" + "0000000000000000000000000000000000000000000000e-12"), + cpp_dec_float("3." + "63797880709171295166015625000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-12"), + cpp_dec_float("7." + "27595761418342590332031250000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-12"), + cpp_dec_float("1." + "45519152283668518066406250000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-11"), + cpp_dec_float("2." + "91038304567337036132812500000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-11"), + cpp_dec_float("5." + "82076609134674072265625000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-11"), + cpp_dec_float("1." + "16415321826934814453125000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-10"), + cpp_dec_float("2." + "32830643653869628906250000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-10"), + cpp_dec_float("4." + "65661287307739257812500000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-10"), + cpp_dec_float("9." + "31322574615478515625000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-10"), + cpp_dec_float("1." + "86264514923095703125000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-9"), + cpp_dec_float("3." + "72529029846191406250000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-9"), + cpp_dec_float("7." + "45058059692382812500000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-9"), + cpp_dec_float("1." + "49011611938476562500000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-8"), + cpp_dec_float("2." + "98023223876953125000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-8"), + cpp_dec_float("5." + "96046447753906250000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-8"), + cpp_dec_float("1." + "19209289550781250000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-7"), + cpp_dec_float("2." + "38418579101562500000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-7"), + cpp_dec_float("4." + "76837158203125000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-7"), + cpp_dec_float("9." + "53674316406250000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-7"), + cpp_dec_float("1." + "90734863281250000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-6"), + cpp_dec_float("3." + "81469726562500000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-6"), + cpp_dec_float("7." + "62939453125000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e-6"), + cpp_dec_float("0." + "00001525878906250000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "00003051757812500000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "00006103515625000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "00012207031250000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "00024414062500000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "00048828125000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "00097656250000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "00195312500000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "00390625000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "00781250000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "01562500000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "03125000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000"), + cpp_dec_float("0." + "06250000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.125"), + cpp_dec_float("0.25"), + cpp_dec_float("0.5"), + one(), + two(), + cpp_dec_float(static_cast(4)), + cpp_dec_float(static_cast(8)), + cpp_dec_float(static_cast(16)), + cpp_dec_float(static_cast(32)), + cpp_dec_float(static_cast(64)), + cpp_dec_float(static_cast(128)), + cpp_dec_float(static_cast(256)), + cpp_dec_float(static_cast(512)), + cpp_dec_float(static_cast(1024)), + cpp_dec_float(static_cast(2048)), + cpp_dec_float(static_cast(4096)), + cpp_dec_float(static_cast(8192)), + cpp_dec_float(static_cast(16384)), + cpp_dec_float(static_cast(32768)), + cpp_dec_float(static_cast(65536)), + cpp_dec_float(static_cast(131072)), + cpp_dec_float(static_cast(262144)), + cpp_dec_float(static_cast(524288)), + cpp_dec_float(static_cast(1uL << 20u)), + cpp_dec_float(static_cast(1uL << 21u)), + cpp_dec_float(static_cast(1uL << 22u)), + cpp_dec_float(static_cast(1uL << 23u)), + cpp_dec_float(static_cast(1uL << 24u)), + cpp_dec_float(static_cast(1uL << 25u)), + cpp_dec_float(static_cast(1uL << 26u)), + cpp_dec_float(static_cast(1uL << 27u)), + cpp_dec_float(static_cast(1uL << 28u)), + cpp_dec_float(static_cast(1uL << 29u)), + cpp_dec_float(static_cast(1uL << 30u)), + cpp_dec_float(static_cast(1uL << 31u)), + cpp_dec_float(static_cast(1uLL << 32u)), + cpp_dec_float(static_cast(1uLL << 33u)), + cpp_dec_float(static_cast(1uLL << 34u)), + cpp_dec_float(static_cast(1uLL << 35u)), + cpp_dec_float(static_cast(1uLL << 36u)), + cpp_dec_float(static_cast(1uLL << 37u)), + cpp_dec_float(static_cast(1uLL << 38u)), + cpp_dec_float(static_cast(1uLL << 39u)), + cpp_dec_float(static_cast(1uLL << 40u)), + cpp_dec_float(static_cast(1uLL << 41u)), + cpp_dec_float(static_cast(1uLL << 42u)), + cpp_dec_float(static_cast(1uLL << 43u)), + cpp_dec_float(static_cast(1uLL << 44u)), + cpp_dec_float(static_cast(1uLL << 45u)), + cpp_dec_float(static_cast(1uLL << 46u)), + cpp_dec_float(static_cast(1uLL << 47u)), + cpp_dec_float(static_cast(1uLL << 48u)), + cpp_dec_float(static_cast(1uLL << 49u)), + cpp_dec_float(static_cast(1uLL << 50u)), + cpp_dec_float(static_cast(1uLL << 51u)), + cpp_dec_float(static_cast(1uLL << 52u)), + cpp_dec_float(static_cast(1uLL << 53u)), + cpp_dec_float(static_cast(1uLL << 54u)), + cpp_dec_float(static_cast(1uLL << 55u)), + cpp_dec_float(static_cast(1uLL << 56u)), + cpp_dec_float(static_cast(1uLL << 57u)), + cpp_dec_float(static_cast(1uLL << 58u)), + cpp_dec_float(static_cast(1uLL << 59u)), + cpp_dec_float(static_cast(1uLL << 60u)), + cpp_dec_float(static_cast(1uLL << 61u)), + cpp_dec_float(static_cast(1uLL << 62u)), + cpp_dec_float(static_cast(1uLL << 63u)), + cpp_dec_float("1." + "84467440737095516160000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e19"), + cpp_dec_float("3." + "68934881474191032320000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e19"), + cpp_dec_float("7." + "37869762948382064640000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e19"), + cpp_dec_float("1." + "47573952589676412928000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e20"), + cpp_dec_float("2." + "95147905179352825856000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e20"), + cpp_dec_float("5." + "90295810358705651712000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e20"), + cpp_dec_float("1." + "18059162071741130342400000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e21"), + cpp_dec_float("2." + "36118324143482260684800000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e21"), + cpp_dec_float("4." + "72236648286964521369600000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e21"), + cpp_dec_float("9." + "44473296573929042739200000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e21"), + cpp_dec_float("1." + "88894659314785808547840000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e22"), + cpp_dec_float("3." + "77789318629571617095680000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e22"), + cpp_dec_float("7." + "55578637259143234191360000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e22"), + cpp_dec_float("1." + "51115727451828646838272000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e23"), + cpp_dec_float("3." + "02231454903657293676544000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e23"), + cpp_dec_float("6." + "04462909807314587353088000000000000000000000000000000" + "0000000000000000000000000000000000000000000000e23"), + cpp_dec_float("1." + "20892581961462917470617600000000000000000000000000000" + "0000000000000000000000000000000000000000000000e24"), + cpp_dec_float("2." + "41785163922925834941235200000000000000000000000000000" + "0000000000000000000000000000000000000000000000e24"), + cpp_dec_float("4." + "83570327845851669882470400000000000000000000000000000" + "0000000000000000000000000000000000000000000000e24"), + cpp_dec_float("9." + "67140655691703339764940800000000000000000000000000000" + "0000000000000000000000000000000000000000000000e24"), + cpp_dec_float("1." + "93428131138340667952988160000000000000000000000000000" + "0000000000000000000000000000000000000000000000e25"), + cpp_dec_float("3." + "86856262276681335905976320000000000000000000000000000" + "0000000000000000000000000000000000000000000000e25"), + cpp_dec_float("7." + "73712524553362671811952640000000000000000000000000000" + "0000000000000000000000000000000000000000000000e25"), + cpp_dec_float("1." + "54742504910672534362390528000000000000000000000000000" + "0000000000000000000000000000000000000000000000e26"), + cpp_dec_float("3." + "09485009821345068724781056000000000000000000000000000" + "0000000000000000000000000000000000000000000000e26"), + cpp_dec_float("6." + "18970019642690137449562112000000000000000000000000000" + "0000000000000000000000000000000000000000000000e26"), + cpp_dec_float("1." + "23794003928538027489912422400000000000000000000000000" + "0000000000000000000000000000000000000000000000e27"), + cpp_dec_float("2." + "47588007857076054979824844800000000000000000000000000" + "0000000000000000000000000000000000000000000000e27"), + cpp_dec_float("4." + "95176015714152109959649689600000000000000000000000000" + "0000000000000000000000000000000000000000000000e27"), + cpp_dec_float("9." + "90352031428304219919299379200000000000000000000000000" + "0000000000000000000000000000000000000000000000e27"), + cpp_dec_float("1." + "98070406285660843983859875840000000000000000000000000" + "0000000000000000000000000000000000000000000000e28"), + cpp_dec_float("3." + "96140812571321687967719751680000000000000000000000000" + "0000000000000000000000000000000000000000000000e28"), + cpp_dec_float("7." + "92281625142643375935439503360000000000000000000000000" + "0000000000000000000000000000000000000000000000e28"), + cpp_dec_float("1." + "58456325028528675187087900672000000000000000000000000" + "0000000000000000000000000000000000000000000000e29"), + cpp_dec_float("3." + "16912650057057350374175801344000000000000000000000000" + "0000000000000000000000000000000000000000000000e29"), + cpp_dec_float("6." + "33825300114114700748351602688000000000000000000000000" + "0000000000000000000000000000000000000000000000e29"), + cpp_dec_float("1." + "26765060022822940149670320537600000000000000000000000" + "0000000000000000000000000000000000000000000000e30"), + cpp_dec_float("2." + "53530120045645880299340641075200000000000000000000000" + "0000000000000000000000000000000000000000000000e30"), + cpp_dec_float("5." + "07060240091291760598681282150400000000000000000000000" + "0000000000000000000000000000000000000000000000e30"), + cpp_dec_float("1." + "01412048018258352119736256430080000000000000000000000" + "0000000000000000000000000000000000000000000000e31"), + cpp_dec_float("2." + "02824096036516704239472512860160000000000000000000000" + "0000000000000000000000000000000000000000000000e31"), + cpp_dec_float("4." + "05648192073033408478945025720320000000000000000000000" + "0000000000000000000000000000000000000000000000e31"), + cpp_dec_float("8." + "11296384146066816957890051440640000000000000000000000" + "0000000000000000000000000000000000000000000000e31"), + cpp_dec_float("1." + "62259276829213363391578010288128000000000000000000000" + "0000000000000000000000000000000000000000000000e32"), + cpp_dec_float("3." + "24518553658426726783156020576256000000000000000000000" + "0000000000000000000000000000000000000000000000e32"), + cpp_dec_float("6." + "49037107316853453566312041152512000000000000000000000" + "0000000000000000000000000000000000000000000000e32"), + cpp_dec_float("1." + "29807421463370690713262408230502400000000000000000000" + "0000000000000000000000000000000000000000000000e33"), + cpp_dec_float("2." + "59614842926741381426524816461004800000000000000000000" + "0000000000000000000000000000000000000000000000e33"), + cpp_dec_float("5." + "19229685853482762853049632922009600000000000000000000" + "0000000000000000000000000000000000000000000000e33"), + cpp_dec_float("1." + "03845937170696552570609926584401920000000000000000000" + "0000000000000000000000000000000000000000000000e34"), + cpp_dec_float("2." + "07691874341393105141219853168803840000000000000000000" + "0000000000000000000000000000000000000000000000e34"), + cpp_dec_float("4." + "15383748682786210282439706337607680000000000000000000" + "0000000000000000000000000000000000000000000000e34"), + cpp_dec_float("8." + "30767497365572420564879412675215360000000000000000000" + "0000000000000000000000000000000000000000000000e34"), + cpp_dec_float("1." + "66153499473114484112975882535043072000000000000000000" + "0000000000000000000000000000000000000000000000e35"), + cpp_dec_float("3." + "32306998946228968225951765070086144000000000000000000" + "0000000000000000000000000000000000000000000000e35"), + cpp_dec_float("6." + "64613997892457936451903530140172288000000000000000000" + "0000000000000000000000000000000000000000000000e35"), + cpp_dec_float("1." + "32922799578491587290380706028034457600000000000000000" + "0000000000000000000000000000000000000000000000e36"), + cpp_dec_float("2." + "65845599156983174580761412056068915200000000000000000" + "0000000000000000000000000000000000000000000000e36"), + cpp_dec_float("5." + "31691198313966349161522824112137830400000000000000000" + "0000000000000000000000000000000000000000000000e36"), + cpp_dec_float("1." + "06338239662793269832304564822427566080000000000000000" + "0000000000000000000000000000000000000000000000e37"), + cpp_dec_float("2." + "12676479325586539664609129644855132160000000000000000" + "0000000000000000000000000000000000000000000000e37"), + cpp_dec_float("4." + "25352958651173079329218259289710264320000000000000000" + "0000000000000000000000000000000000000000000000e37"), + cpp_dec_float("8." + "50705917302346158658436518579420528640000000000000000" + "0000000000000000000000000000000000000000000000e37"), + cpp_dec_float("1." + "70141183460469231731687303715884105728000000000000000" + "0000000000000000000000000000000000000000000000e38")}}; + + if ((p > static_cast(-128)) && + (p < static_cast(+128))) { + return p2_data[static_cast(p + ((p2_data.size() - 1u) / 2u))]; + } else { + // Compute and return 2^p. + if (p < static_cast(0)) { + return pow2(static_cast(-p)).calculate_inv(); + } else { + cpp_dec_float t; + default_ops::detail::pow_imp(t, two(), p, mpl::true_()); + return t; + } + } } - template -inline void eval_add(cpp_dec_float& result, const cpp_dec_float& o) -{ - result += o; +inline void +eval_add(cpp_dec_float &result, + const cpp_dec_float &o) { + result += o; } template -inline void eval_subtract(cpp_dec_float& result, const cpp_dec_float& o) -{ - result -= o; +inline void +eval_subtract(cpp_dec_float &result, + const cpp_dec_float &o) { + result -= o; } template -inline void eval_multiply(cpp_dec_float& result, const cpp_dec_float& o) -{ - result *= o; +inline void +eval_multiply(cpp_dec_float &result, + const cpp_dec_float &o) { + result *= o; } template -inline void eval_divide(cpp_dec_float& result, const cpp_dec_float& o) -{ - result /= o; +inline void +eval_divide(cpp_dec_float &result, + const cpp_dec_float &o) { + result /= o; } template -inline void eval_add(cpp_dec_float& result, const boost::ulong_long_type& o) -{ - result.add_unsigned_long_long(o); +inline void eval_add(cpp_dec_float &result, + const boost::ulong_long_type &o) { + result.add_unsigned_long_long(o); } template -inline void eval_subtract(cpp_dec_float& result, const boost::ulong_long_type& o) -{ - result.sub_unsigned_long_long(o); +inline void +eval_subtract(cpp_dec_float &result, + const boost::ulong_long_type &o) { + result.sub_unsigned_long_long(o); } template -inline void eval_multiply(cpp_dec_float& result, const boost::ulong_long_type& o) -{ - result.mul_unsigned_long_long(o); +inline void +eval_multiply(cpp_dec_float &result, + const boost::ulong_long_type &o) { + result.mul_unsigned_long_long(o); } template -inline void eval_divide(cpp_dec_float& result, const boost::ulong_long_type& o) -{ - result.div_unsigned_long_long(o); +inline void +eval_divide(cpp_dec_float &result, + const boost::ulong_long_type &o) { + result.div_unsigned_long_long(o); } template -inline void eval_add(cpp_dec_float& result, boost::long_long_type o) -{ - if(o < 0) - result.sub_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o)); - else - result.add_unsigned_long_long(o); +inline void eval_add(cpp_dec_float &result, + boost::long_long_type o) { + if (o < 0) + result.sub_unsigned_long_long( + boost::multiprecision::detail::unsigned_abs(o)); + else + result.add_unsigned_long_long(o); } template -inline void eval_subtract(cpp_dec_float& result, boost::long_long_type o) -{ - if(o < 0) - result.add_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o)); - else - result.sub_unsigned_long_long(o); +inline void +eval_subtract(cpp_dec_float &result, + boost::long_long_type o) { + if (o < 0) + result.add_unsigned_long_long( + boost::multiprecision::detail::unsigned_abs(o)); + else + result.sub_unsigned_long_long(o); } template -inline void eval_multiply(cpp_dec_float& result, boost::long_long_type o) -{ - if(o < 0) - { - result.mul_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o)); - result.negate(); - } - else - result.mul_unsigned_long_long(o); +inline void +eval_multiply(cpp_dec_float &result, + boost::long_long_type o) { + if (o < 0) { + result.mul_unsigned_long_long( + boost::multiprecision::detail::unsigned_abs(o)); + result.negate(); + } else + result.mul_unsigned_long_long(o); } template -inline void eval_divide(cpp_dec_float& result, boost::long_long_type o) -{ - if(o < 0) - { - result.div_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o)); - result.negate(); - } - else - result.div_unsigned_long_long(o); +inline void +eval_divide(cpp_dec_float &result, + boost::long_long_type o) { + if (o < 0) { + result.div_unsigned_long_long( + boost::multiprecision::detail::unsigned_abs(o)); + result.negate(); + } else + result.div_unsigned_long_long(o); } template -inline void eval_convert_to(boost::ulong_long_type* result, const cpp_dec_float& val) -{ - *result = val.extract_unsigned_long_long(); +inline void +eval_convert_to(boost::ulong_long_type *result, + const cpp_dec_float &val) { + *result = val.extract_unsigned_long_long(); } template -inline void eval_convert_to(boost::long_long_type* result, const cpp_dec_float& val) -{ - *result = val.extract_signed_long_long(); +inline void +eval_convert_to(boost::long_long_type *result, + const cpp_dec_float &val) { + *result = val.extract_signed_long_long(); } template -inline void eval_convert_to(long double* result, cpp_dec_float& val) -{ - *result = val.extract_long_double(); +inline void +eval_convert_to(long double *result, + cpp_dec_float &val) { + *result = val.extract_long_double(); } // // Non member function support: // template -inline int eval_fpclassify(const cpp_dec_float& x) -{ - if((x.isinf)()) - return FP_INFINITE; - if((x.isnan)()) - return FP_NAN; - if(x.iszero()) - return FP_ZERO; - return FP_NORMAL; +inline int +eval_fpclassify(const cpp_dec_float &x) { + if ((x.isinf)()) + return FP_INFINITE; + if ((x.isnan)()) + return FP_NAN; + if (x.iszero()) + return FP_ZERO; + return FP_NORMAL; } template -inline void eval_abs(cpp_dec_float& result, const cpp_dec_float& x) -{ - result = x; - if(x.isneg()) - result.negate(); +inline void +eval_abs(cpp_dec_float &result, + const cpp_dec_float &x) { + result = x; + if (x.isneg()) + result.negate(); } template -inline void eval_fabs(cpp_dec_float& result, const cpp_dec_float& x) -{ - result = x; - if(x.isneg()) - result.negate(); +inline void +eval_fabs(cpp_dec_float &result, + const cpp_dec_float &x) { + result = x; + if (x.isneg()) + result.negate(); } template -inline void eval_sqrt(cpp_dec_float& result, const cpp_dec_float& x) -{ - result = x; - result.calculate_sqrt(); +inline void +eval_sqrt(cpp_dec_float &result, + const cpp_dec_float &x) { + result = x; + result.calculate_sqrt(); } template -inline void eval_floor(cpp_dec_float& result, const cpp_dec_float& x) -{ - result = x; - if(!(x.isfinite)() || x.isint()) - { - if((x.isnan)()) - errno = EDOM; - return; - } +inline void +eval_floor(cpp_dec_float &result, + const cpp_dec_float &x) { + result = x; + if (!(x.isfinite)() || x.isint()) { + if ((x.isnan)()) + errno = EDOM; + return; + } - if(x.isneg()) - result -= cpp_dec_float::one(); - result = result.extract_integer_part(); + if (x.isneg()) + result -= cpp_dec_float::one(); + result = result.extract_integer_part(); } template -inline void eval_ceil(cpp_dec_float& result, const cpp_dec_float& x) -{ - result = x; - if(!(x.isfinite)() || x.isint()) - { - if((x.isnan)()) - errno = EDOM; - return; - } +inline void +eval_ceil(cpp_dec_float &result, + const cpp_dec_float &x) { + result = x; + if (!(x.isfinite)() || x.isint()) { + if ((x.isnan)()) + errno = EDOM; + return; + } - if(!x.isneg()) - result += cpp_dec_float::one(); - result = result.extract_integer_part(); + if (!x.isneg()) + result += cpp_dec_float::one(); + result = result.extract_integer_part(); } template -inline void eval_trunc(cpp_dec_float& result, const cpp_dec_float& x) -{ - if(x.isint() || !(x.isfinite)()) - { - result = x; - if((x.isnan)()) - errno = EDOM; - return; - } - result = x.extract_integer_part(); +inline void +eval_trunc(cpp_dec_float &result, + const cpp_dec_float &x) { + if (x.isint() || !(x.isfinite)()) { + result = x; + if ((x.isnan)()) + errno = EDOM; + return; + } + result = x.extract_integer_part(); } template -inline ExponentType eval_ilogb(const cpp_dec_float& val) -{ - if(val.iszero()) - return (std::numeric_limits::min)(); - if((val.isinf)()) - return INT_MAX; - if((val.isnan)()) +inline ExponentType +eval_ilogb(const cpp_dec_float &val) { + if (val.iszero()) + return (std::numeric_limits::min)(); + if ((val.isinf)()) + return INT_MAX; + if ((val.isnan)()) #ifdef FP_ILOGBNAN - return FP_ILOGBNAN; + return FP_ILOGBNAN; #else - return INT_MAX; + return INT_MAX; #endif - // Set result, to the exponent of val: - return val.order(); + // Set result, to the exponent of val: + return val.order(); } template -inline void eval_scalbn(cpp_dec_float& result, const cpp_dec_float& val, ArgType e_) -{ - using default_ops::eval_multiply; - const ExponentType e = static_cast(e_); - cpp_dec_float t(1.0, e); - eval_multiply(result, val, t); +inline void +eval_scalbn(cpp_dec_float &result, + const cpp_dec_float &val, + ArgType e_) { + using default_ops::eval_multiply; + const ExponentType e = static_cast(e_); + cpp_dec_float t(1.0, e); + eval_multiply(result, val, t); } template -inline void eval_ldexp(cpp_dec_float& result, const cpp_dec_float& x, ArgType e) -{ - const boost::long_long_type the_exp = static_cast(e); - - if((the_exp > (std::numeric_limits::max)()) || (the_exp < (std::numeric_limits::min)())) - BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Exponent value is out of range."))); - - result = x; - - if ((the_exp > static_cast(-std::numeric_limits::digits)) && (the_exp < static_cast(0))) - result.div_unsigned_long_long(1ULL << static_cast(-the_exp)); - else if((the_exp < static_cast( std::numeric_limits::digits)) && (the_exp > static_cast(0))) - result.mul_unsigned_long_long(1ULL << the_exp); - else if(the_exp != static_cast(0)) - result *= cpp_dec_float::pow2(e); +inline void +eval_ldexp(cpp_dec_float &result, + const cpp_dec_float &x, + ArgType e) { + const boost::long_long_type the_exp = static_cast(e); + + if ((the_exp > (std::numeric_limits::max)()) || + (the_exp < (std::numeric_limits::min)())) + BOOST_THROW_EXCEPTION( + std::runtime_error(std::string("Exponent value is out of range."))); + + result = x; + + if ((the_exp > static_cast( + -std::numeric_limits::digits)) && + (the_exp < static_cast(0))) + result.div_unsigned_long_long( + 1ULL << static_cast(-the_exp)); + else if ((the_exp < + static_cast( + std::numeric_limits::digits)) && + (the_exp > static_cast(0))) + result.mul_unsigned_long_long(1ULL << the_exp); + else if (the_exp != static_cast(0)) + result *= cpp_dec_float::pow2(e); } template -inline void eval_frexp(cpp_dec_float& result, const cpp_dec_float& x, ExponentType* e) -{ - result = x; - - if(result.iszero() || (result.isinf)() || (result.isnan)()) - { - *e = 0; - return; - } - - if(result.isneg()) - result.negate(); - - ExponentType t = result.order(); - BOOST_MP_USING_ABS - if(abs(t) < ((std::numeric_limits::max)() / 1000)) - { - t *= 1000; - t /= 301; - } - else - { - t /= 301; - t *= 1000; - } - - result *= cpp_dec_float::pow2(-t); - - if(result.iszero() || (result.isinf)() || (result.isnan)()) - { - // pow2 overflowed, slip the calculation up: - result = x; - if(result.isneg()) - result.negate(); - t /= 2; - result *= cpp_dec_float::pow2(-t); - } - BOOST_MP_USING_ABS - if(abs(result.order()) > 5) - { - // If our first estimate doesn't get close enough then try recursion until we do: - ExponentType e2; - cpp_dec_float r2; - eval_frexp(r2, result, &e2); - // overflow protection: - if((t > 0) && (e2 > 0) && (t > (std::numeric_limits::max)() - e2)) - BOOST_THROW_EXCEPTION(std::runtime_error("Exponent is too large to be represented as a power of 2.")); - if((t < 0) && (e2 < 0) && (t < (std::numeric_limits::min)() - e2)) - BOOST_THROW_EXCEPTION(std::runtime_error("Exponent is too large to be represented as a power of 2.")); - t += e2; - result = r2; - } - - while(result.compare(cpp_dec_float::one()) >= 0) - { - result /= cpp_dec_float::two(); - ++t; - } - while(result.compare(cpp_dec_float::half()) < 0) - { - result *= cpp_dec_float::two(); - --t; - } - *e = t; - if(x.isneg()) +inline void +eval_frexp(cpp_dec_float &result, + const cpp_dec_float &x, + ExponentType *e) { + result = x; + + if (result.iszero() || (result.isinf)() || (result.isnan)()) { + *e = 0; + return; + } + + if (result.isneg()) + result.negate(); + + ExponentType t = result.order(); + BOOST_MP_USING_ABS + if (abs(t) < ((std::numeric_limits::max)() / 1000)) { + t *= 1000; + t /= 301; + } else { + t /= 301; + t *= 1000; + } + + result *= cpp_dec_float::pow2(-t); + + if (result.iszero() || (result.isinf)() || (result.isnan)()) { + // pow2 overflowed, slip the calculation up: + result = x; + if (result.isneg()) result.negate(); + t /= 2; + result *= cpp_dec_float::pow2(-t); + } + BOOST_MP_USING_ABS + if (abs(result.order()) > 5) { + // If our first estimate doesn't get close enough then try recursion until + // we do: + ExponentType e2; + cpp_dec_float r2; + eval_frexp(r2, result, &e2); + // overflow protection: + if ((t > 0) && (e2 > 0) && + (t > (std::numeric_limits::max)() - e2)) + BOOST_THROW_EXCEPTION(std::runtime_error( + "Exponent is too large to be represented as a power of 2.")); + if ((t < 0) && (e2 < 0) && + (t < (std::numeric_limits::min)() - e2)) + BOOST_THROW_EXCEPTION(std::runtime_error( + "Exponent is too large to be represented as a power of 2.")); + t += e2; + result = r2; + } + + while (result.compare( + cpp_dec_float::one()) >= 0) { + result /= cpp_dec_float::two(); + ++t; + } + while (result.compare( + cpp_dec_float::half()) < 0) { + result *= cpp_dec_float::two(); + --t; + } + *e = t; + if (x.isneg()) + result.negate(); } template -inline typename disable_if >::type eval_frexp(cpp_dec_float& result, const cpp_dec_float& x, int* e) -{ - ExponentType t; - eval_frexp(result, x, &t); - if((t > (std::numeric_limits::max)()) || (t < (std::numeric_limits::min)())) - BOOST_THROW_EXCEPTION(std::runtime_error("Exponent is outside the range of an int")); - *e = static_cast(t); +inline typename disable_if>::type +eval_frexp(cpp_dec_float &result, + const cpp_dec_float &x, int *e) { + ExponentType t; + eval_frexp(result, x, &t); + if ((t > (std::numeric_limits::max)()) || + (t < (std::numeric_limits::min)())) + BOOST_THROW_EXCEPTION( + std::runtime_error("Exponent is outside the range of an int")); + *e = static_cast(t); } template -inline bool eval_is_zero(const cpp_dec_float& val) -{ - return val.iszero(); +inline bool +eval_is_zero(const cpp_dec_float &val) { + return val.iszero(); } template -inline int eval_get_sign(const cpp_dec_float& val) -{ - return val.iszero() ? 0 : val.isneg() ? -1 : 1; +inline int +eval_get_sign(const cpp_dec_float &val) { + return val.iszero() ? 0 : val.isneg() ? -1 : 1; } template -inline std::size_t hash_value(const cpp_dec_float& val) -{ - return val.hash(); +inline std::size_t +hash_value(const cpp_dec_float &val) { + return val.hash(); } } // namespace backends using boost::multiprecision::backends::cpp_dec_float; - -typedef number > cpp_dec_float_50; -typedef number > cpp_dec_float_100; +typedef number> cpp_dec_float_50; +typedef number> cpp_dec_float_100; #ifdef BOOST_NO_SFINAE_EXPR -namespace detail{ +namespace detail { -template -struct is_explicitly_convertible, cpp_dec_float > : public mpl::true_ {}; +template +struct is_explicitly_convertible, + cpp_dec_float> + : public mpl::true_ {}; -} +} // namespace detail #endif +} // namespace multiprecision +} // namespace boost -}} - -namespace std -{ - template - class numeric_limits, ExpressionTemplates> > - { - public: - BOOST_STATIC_CONSTEXPR bool is_specialized = true; - BOOST_STATIC_CONSTEXPR bool is_signed = true; - BOOST_STATIC_CONSTEXPR bool is_integer = false; - BOOST_STATIC_CONSTEXPR bool is_exact = false; - BOOST_STATIC_CONSTEXPR bool is_bounded = true; - BOOST_STATIC_CONSTEXPR bool is_modulo = false; - BOOST_STATIC_CONSTEXPR bool is_iec559 = false; - BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::cpp_dec_float::cpp_dec_float_digits10; - BOOST_STATIC_CONSTEXPR int digits10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_digits10; - BOOST_STATIC_CONSTEXPR int max_digits10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_total_digits10; - BOOST_STATIC_CONSTEXPR ExponentType min_exponent = boost::multiprecision::cpp_dec_float::cpp_dec_float_min_exp; // Type differs from int. - BOOST_STATIC_CONSTEXPR ExponentType min_exponent10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_min_exp10; // Type differs from int. - BOOST_STATIC_CONSTEXPR ExponentType max_exponent = boost::multiprecision::cpp_dec_float::cpp_dec_float_max_exp; // Type differs from int. - BOOST_STATIC_CONSTEXPR ExponentType max_exponent10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_max_exp10; // Type differs from int. - BOOST_STATIC_CONSTEXPR int radix = boost::multiprecision::cpp_dec_float::cpp_dec_float_radix; - BOOST_STATIC_CONSTEXPR std::float_round_style round_style = std::round_indeterminate; - BOOST_STATIC_CONSTEXPR bool has_infinity = true; - BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true; - BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; - BOOST_STATIC_CONSTEXPR std::float_denorm_style has_denorm = std::denorm_absent; - BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; - BOOST_STATIC_CONSTEXPR bool traps = false; - BOOST_STATIC_CONSTEXPR bool tinyness_before = false; - - BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> (min) () { return (boost::multiprecision::cpp_dec_float::min)(); } - BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> (max) () { return (boost::multiprecision::cpp_dec_float::max)(); } - BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> lowest () { return boost::multiprecision::cpp_dec_float::zero(); } - BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> epsilon () { return boost::multiprecision::cpp_dec_float::eps(); } - BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> round_error () { return 0.5L; } - BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> infinity () { return boost::multiprecision::cpp_dec_float::inf(); } - BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> quiet_NaN () { return boost::multiprecision::cpp_dec_float::nan(); } - BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> signaling_NaN() { return boost::multiprecision::cpp_dec_float::zero(); } - BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> denorm_min () { return boost::multiprecision::cpp_dec_float::zero(); } - }; +namespace std { +template +class numeric_limits, + ExpressionTemplates>> { +public: + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = true; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR int digits = + boost::multiprecision::cpp_dec_float::cpp_dec_float_digits10; + BOOST_STATIC_CONSTEXPR int digits10 = + boost::multiprecision::cpp_dec_float::cpp_dec_float_digits10; + BOOST_STATIC_CONSTEXPR int max_digits10 = + boost::multiprecision::cpp_dec_float< + Digits10, ExponentType, Allocator>::cpp_dec_float_total_digits10; + BOOST_STATIC_CONSTEXPR ExponentType min_exponent = + boost::multiprecision::cpp_dec_float:: + cpp_dec_float_min_exp; // Type differs from int. + BOOST_STATIC_CONSTEXPR ExponentType min_exponent10 = + boost::multiprecision::cpp_dec_float:: + cpp_dec_float_min_exp10; // Type differs from int. + BOOST_STATIC_CONSTEXPR ExponentType max_exponent = + boost::multiprecision::cpp_dec_float:: + cpp_dec_float_max_exp; // Type differs from int. + BOOST_STATIC_CONSTEXPR ExponentType max_exponent10 = + boost::multiprecision::cpp_dec_float:: + cpp_dec_float_max_exp10; // Type differs from int. + BOOST_STATIC_CONSTEXPR int radix = + boost::multiprecision::cpp_dec_float::cpp_dec_float_radix; + BOOST_STATIC_CONSTEXPR std::float_round_style round_style = + std::round_indeterminate; + BOOST_STATIC_CONSTEXPR bool has_infinity = true; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR std::float_denorm_style has_denorm = + std::denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + + BOOST_STATIC_CONSTEXPR boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates>(min)() { + return (boost::multiprecision::cpp_dec_float::min)(); + } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates>(max)() { + return (boost::multiprecision::cpp_dec_float::max)(); + } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates> + lowest() { + return boost::multiprecision::cpp_dec_float::zero(); + } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates> + epsilon() { + return boost::multiprecision::cpp_dec_float::eps(); + } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates> + round_error() { + return 0.5L; + } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates> + infinity() { + return boost::multiprecision::cpp_dec_float::inf(); + } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates> + quiet_NaN() { + return boost::multiprecision::cpp_dec_float::nan(); + } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates> + signaling_NaN() { + return boost::multiprecision::cpp_dec_float::zero(); + } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates> + denorm_min() { + return boost::multiprecision::cpp_dec_float::zero(); + } +}; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; -template -BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits, ExpressionTemplates> >::min_exponent; -template -BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits, ExpressionTemplates> >::min_exponent10; -template -BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits, ExpressionTemplates> >::max_exponent; -template -BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits, ExpressionTemplates> >::max_exponent10; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; -template -BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; -template -BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::radix; +template +BOOST_CONSTEXPR_OR_CONST ExponentType + numeric_limits, + ExpressionTemplates>>::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST ExponentType + numeric_limits, + ExpressionTemplates>>::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST ExponentType + numeric_limits, + ExpressionTemplates>>::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST ExponentType + numeric_limits, + ExpressionTemplates>>::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style + numeric_limits, + ExpressionTemplates>>::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style + numeric_limits, + ExpressionTemplates>>::round_style; #endif -} - -namespace boost{ namespace math{ - -namespace policies{ - -template -struct precision< boost::multiprecision::number, ExpressionTemplates>, Policy> -{ - // Define a local copy of cpp_dec_float_digits10 because it might differ - // from the template parameter Digits10 for small or large digit counts. - static const boost::int32_t cpp_dec_float_digits10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_digits10; - - typedef typename Policy::precision_type precision_type; - typedef digits2<((cpp_dec_float_digits10 + 1LL) * 1000LL) / 301LL> digits_2; - typedef typename mpl::if_c< - ((digits_2::value <= precision_type::value) - || (Policy::precision_type::value <= 0)), - // Default case, full precision for RealType: - digits_2, - // User customized precision: - precision_type - >::type type; +} // namespace std + +namespace boost { +namespace math { + +namespace policies { + +template +struct precision< + boost::multiprecision::number< + boost::multiprecision::cpp_dec_float, + ExpressionTemplates>, + Policy> { + // Define a local copy of cpp_dec_float_digits10 because it might differ + // from the template parameter Digits10 for small or large digit counts. + static const boost::int32_t cpp_dec_float_digits10 = + boost::multiprecision::cpp_dec_float::cpp_dec_float_digits10; + + typedef typename Policy::precision_type precision_type; + typedef digits2<((cpp_dec_float_digits10 + 1LL) * 1000LL) / 301LL> digits_2; + typedef typename mpl::if_c<((digits_2::value <= precision_type::value) || + (Policy::precision_type::value <= 0)), + // Default case, full precision for RealType: + digits_2, + // User customized precision: + precision_type>::type type; }; } // namespace policies -}} // namespaces boost::math +} // namespace math +} // namespace boost #ifdef BOOST_MSVC #pragma warning(pop) diff --git a/include/boost/multiprecision/cpp_int/add.hpp b/include/boost/multiprecision/cpp_int/add.hpp index 8da7e1d85..4a0404a25 100644 --- a/include/boost/multiprecision/cpp_int/add.hpp +++ b/include/boost/multiprecision/cpp_int/add.hpp @@ -8,28 +8,28 @@ #ifndef BOOST_MP_CPP_INT_ADD_HPP #define BOOST_MP_CPP_INT_ADD_HPP -namespace boost{ namespace multiprecision{ namespace backends{ +namespace boost { namespace multiprecision { namespace backends { #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable : 4127) // conditional expression is constant #endif // // This is the key addition routine where all the argument types are non-trivial cpp_int's: // template -inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int::value) +inline void add_unsigned(CppInt1 &result, const CppInt2 &a, const CppInt3 &b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int::value) { using std::swap; // Nothing fancy, just let uintmax_t take the strain: double_limb_type carry = 0; - unsigned m, x; - unsigned as = a.size(); - unsigned bs = b.size(); + unsigned m, x; + unsigned as = a.size(); + unsigned bs = b.size(); minmax(as, bs, m, x); - if(x == 1) + if (x == 1) { bool s = a.sign(); result = static_cast(*a.limbs()) + static_cast(*b.limbs()); @@ -37,16 +37,16 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO return; } result.resize(x, x); - typename CppInt2::const_limb_pointer pa = a.limbs(); - typename CppInt3::const_limb_pointer pb = b.limbs(); - typename CppInt1::limb_pointer pr = result.limbs(); - typename CppInt1::limb_pointer pr_end = pr + m; + typename CppInt2::const_limb_pointer pa = a.limbs(); + typename CppInt3::const_limb_pointer pb = b.limbs(); + typename CppInt1::limb_pointer pr = result.limbs(); + typename CppInt1::limb_pointer pr_end = pr + m; - if(as < bs) + if (as < bs) swap(pa, pb); - + // First where a and b overlap: - while(pr != pr_end) + while (pr != pr_end) { carry += static_cast(*pa) + static_cast(*pb); #ifdef __MSVC_RUNTIME_CHECKS @@ -59,13 +59,13 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO } pr_end += x - m; // Now where only a has digits: - while(pr != pr_end) + while (pr != pr_end) { - if(!carry) + if (!carry) { - if(pa != pr) + if (pa != pr) #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) - std::copy(pa, pa + (pr_end - pr), stdext::checked_array_iterator(pr, result.size())); + std::copy(pa, pa + (pr_end - pr), stdext::checked_array_iterator(pr, result.size())); #else std::copy(pa, pa + (pr_end - pr), pr); #endif @@ -75,16 +75,16 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO #ifdef __MSVC_RUNTIME_CHECKS *pr = static_cast(carry & ~static_cast(0)); #else - *pr = static_cast(carry); + *pr = static_cast(carry); #endif carry >>= CppInt1::limb_bits; ++pr, ++pa; } - if(carry) + if (carry) { // We overflowed, need to add one more limb: result.resize(x + 1, x + 1); - if(result.size() > x) + if (result.size() > x) result.limbs()[x] = static_cast(carry); } result.normalize(); @@ -94,18 +94,18 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO // As above, but for adding a single limb to a non-trivial cpp_int: // template -inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int::value) +inline void add_unsigned(CppInt1 &result, const CppInt2 &a, const limb_type &o) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int::value) { // Addition using modular arithmetic. // Nothing fancy, just let uintmax_t take the strain: - if(&result != &a) + if (&result != &a) result.resize(a.size(), a.size()); - double_limb_type carry = o; - typename CppInt1::limb_pointer pr = result.limbs(); - typename CppInt2::const_limb_pointer pa = a.limbs(); - unsigned i = 0; + double_limb_type carry = o; + typename CppInt1::limb_pointer pr = result.limbs(); + typename CppInt2::const_limb_pointer pa = a.limbs(); + unsigned i = 0; // Addition with carry until we either run out of digits or carry is zero: - for(; carry && (i < result.size()); ++i) + for (; carry && (i < result.size()); ++i) { carry += static_cast(pa[i]); #ifdef __MSVC_RUNTIME_CHECKS @@ -116,17 +116,17 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) carry >>= CppInt1::limb_bits; } // Just copy any remaining digits: - if(&a != &result) + if (&a != &result) { - for(; i < result.size(); ++i) + for (; i < result.size(); ++i) pr[i] = pa[i]; } - if(carry) + if (carry) { // We overflowed, need to add one more limb: unsigned x = result.size(); result.resize(x + 1, x + 1); - if(result.size() > x) + if (result.size() > x) result.limbs()[x] = static_cast(carry); } result.normalize(); @@ -136,23 +136,23 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) // Core subtraction routine for all non-trivial cpp_int's: // template -inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int::value) +inline void subtract_unsigned(CppInt1 &result, const CppInt2 &a, const CppInt3 &b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int::value) { using std::swap; // Nothing fancy, just let uintmax_t take the strain: double_limb_type borrow = 0; - unsigned m, x; + unsigned m, x; minmax(a.size(), b.size(), m, x); // // special cases for small limb counts: // - if(x == 1) + if (x == 1) { - bool s = a.sign(); + bool s = a.sign(); limb_type al = *a.limbs(); limb_type bl = *b.limbs(); - if(bl > al) + if (bl > al) { std::swap(al, bl); s = !s; @@ -167,42 +167,42 @@ inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& // Set up the result vector: result.resize(x, x); // Now that a, b, and result are stable, get pointers to their limbs: - typename CppInt2::const_limb_pointer pa = a.limbs(); - typename CppInt3::const_limb_pointer pb = b.limbs(); - typename CppInt1::limb_pointer pr = result.limbs(); - bool swapped = false; - if(c < 0) + typename CppInt2::const_limb_pointer pa = a.limbs(); + typename CppInt3::const_limb_pointer pb = b.limbs(); + typename CppInt1::limb_pointer pr = result.limbs(); + bool swapped = false; + if (c < 0) { swap(pa, pb); swapped = true; } - else if(c == 0) + else if (c == 0) { result = static_cast(0); return; } - + unsigned i = 0; // First where a and b overlap: - while(i < m) + while (i < m) { borrow = static_cast(pa[i]) - static_cast(pb[i]) - borrow; - pr[i] = static_cast(borrow); + pr[i] = static_cast(borrow); borrow = (borrow >> CppInt1::limb_bits) & 1u; ++i; } // Now where only a has digits, only as long as we've borrowed: - while(borrow && (i < x)) + while (borrow && (i < x)) { borrow = static_cast(pa[i]) - borrow; - pr[i] = static_cast(borrow); + pr[i] = static_cast(borrow); borrow = (borrow >> CppInt1::limb_bits) & 1u; ++i; } // Any remaining digits are the same as those in pa: - if((x != i) && (pa != pr)) + if ((x != i) && (pa != pr)) #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) - std::copy(pa + i, pa + x, stdext::checked_array_iterator(pr + i, result.size() - i)); + std::copy(pa + i, pa + x, stdext::checked_array_iterator(pr + i, result.size() - i)); #else std::copy(pa + i, pa + x, pr + i); #endif @@ -213,58 +213,58 @@ inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& // result.normalize(); result.sign(a.sign()); - if(swapped) + if (swapped) result.negate(); } // // And again to subtract a single limb: // template -inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int::value) +inline void subtract_unsigned(CppInt1 &result, const CppInt2 &a, const limb_type &b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int::value) { // Subtract one limb. // Nothing fancy, just let uintmax_t take the strain: BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast(CppInt1::max_limb_value) + 1); result.resize(a.size(), a.size()); - typename CppInt1::limb_pointer pr = result.limbs(); + typename CppInt1::limb_pointer pr = result.limbs(); typename CppInt2::const_limb_pointer pa = a.limbs(); - if(*pa >= b) + if (*pa >= b) { *pr = *pa - b; - if(&result != &a) + if (&result != &a) { #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) - std::copy(pa + 1, pa + a.size(), stdext::checked_array_iterator(pr + 1, result.size() - 1)); + std::copy(pa + 1, pa + a.size(), stdext::checked_array_iterator(pr + 1, result.size() - 1)); #else std::copy(pa + 1, pa + a.size(), pr + 1); #endif result.sign(a.sign()); } - else if((result.size() == 1) && (*pr == 0)) + else if ((result.size() == 1) && (*pr == 0)) { result.sign(false); // zero is unsigned. } } - else if(result.size() == 1) + else if (result.size() == 1) { *pr = b - *pa; result.sign(!a.sign()); } else { - *pr = static_cast((borrow + *pa) - b); + *pr = static_cast((borrow + *pa) - b); unsigned i = 1; - while(!pa[i]) + while (!pa[i]) { pr[i] = CppInt1::max_limb_value; ++i; } pr[i] = pa[i] - 1; - if(&result != &a) + if (&result != &a) { ++i; #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) - std::copy(pa + i, pa + a.size(), stdext::checked_array_iterator(pr + i, result.size() - i)); + std::copy(pa + i, pa + a.size(), stdext::checked_array_iterator(pr + i, result.size() - i)); #else std::copy(pa + i, pa + a.size(), pr + i); #endif @@ -278,21 +278,21 @@ inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type // Now the actual functions called by the front end, all of which forward to one of the above: // template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_add( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_add( + cpp_int_backend & result, + const cpp_int_backend &o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { eval_add(result, result, o); } template -inline typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type - eval_add( - cpp_int_backend& result, - const cpp_int_backend& a, - const cpp_int_backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +inline typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value>::type +eval_add( + cpp_int_backend & result, + const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(a.sign() != b.sign()) + if (a.sign() != b.sign()) { subtract_unsigned(result, a, b); return; @@ -300,10 +300,10 @@ inline typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_add(cpp_int_backend& result, const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_add(cpp_int_backend &result, const limb_type &o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(result.sign()) + if (result.sign()) { subtract_unsigned(result, result, o); } @@ -311,13 +311,13 @@ BOOST_MP_FORCEINLINE typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_add( - cpp_int_backend& result, - const cpp_int_backend& a, - const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_add( + cpp_int_backend & result, + const cpp_int_backend &a, + const limb_type & o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(a.sign()) + if (a.sign()) { subtract_unsigned(result, a, o); } @@ -325,37 +325,37 @@ BOOST_MP_FORCEINLINE typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_add( - cpp_int_backend& result, - const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_add( + cpp_int_backend &result, + const signed_limb_type & o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(o < 0) + if (o < 0) eval_subtract(result, static_cast(boost::multiprecision::detail::unsigned_abs(o))); - else if(o > 0) + else if (o > 0) eval_add(result, static_cast(o)); } template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_add( - cpp_int_backend& result, - const cpp_int_backend& a, - const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_add( + cpp_int_backend & result, + const cpp_int_backend &a, + const signed_limb_type & o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(o < 0) + if (o < 0) eval_subtract(result, a, static_cast(boost::multiprecision::detail::unsigned_abs(o))); - else if(o > 0) + else if (o > 0) eval_add(result, a, static_cast(o)); - else if(&result != &a) + else if (&result != &a) result = a; } template -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_subtract( - cpp_int_backend& result, - const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_subtract( + cpp_int_backend &result, + const limb_type & o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(result.sign()) + if (result.sign()) { add_unsigned(result, result, o); } @@ -363,13 +363,13 @@ BOOST_MP_FORCEINLINE typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_subtract( - cpp_int_backend& result, - const cpp_int_backend& a, - const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_subtract( + cpp_int_backend & result, + const cpp_int_backend &a, + const limb_type & o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(a.sign()) + if (a.sign()) { add_unsigned(result, a, o); } @@ -379,43 +379,43 @@ BOOST_MP_FORCEINLINE typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_subtract( - cpp_int_backend& result, - const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_subtract( + cpp_int_backend &result, + const signed_limb_type & o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(o) + if (o) { - if(o < 0) + if (o < 0) eval_add(result, static_cast(boost::multiprecision::detail::unsigned_abs(o))); else eval_subtract(result, static_cast(o)); } } template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_subtract( - cpp_int_backend& result, - const cpp_int_backend& a, - const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_subtract( + cpp_int_backend & result, + const cpp_int_backend &a, + const signed_limb_type & o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(o) + if (o) { - if(o < 0) + if (o < 0) eval_add(result, a, static_cast(boost::multiprecision::detail::unsigned_abs(o))); else eval_subtract(result, a, static_cast(o)); } - else if(&result != &a) + else if (&result != &a) result = a; } template -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_increment(cpp_int_backend& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_increment(cpp_int_backend &result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { static const limb_type one = 1; - if(!result.sign() && (result.limbs()[0] < cpp_int_backend::max_limb_value)) + if (!result.sign() && (result.limbs()[0] < cpp_int_backend::max_limb_value)) ++result.limbs()[0]; else if (result.sign() && result.limbs()[0]) { @@ -427,11 +427,11 @@ BOOST_MP_FORCEINLINE typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_decrement(cpp_int_backend& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_decrement(cpp_int_backend &result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { static const limb_type one = 1; - if(!result.sign() && result.limbs()[0]) + if (!result.sign() && result.limbs()[0]) --result.limbs()[0]; else if (result.sign() && (result.limbs()[0] < cpp_int_backend::max_limb_value)) ++result.limbs()[0]; @@ -439,21 +439,21 @@ BOOST_MP_FORCEINLINE typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_subtract( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_subtract( + cpp_int_backend & result, + const cpp_int_backend &o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { eval_subtract(result, result, o); } template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type - eval_subtract( - cpp_int_backend& result, - const cpp_int_backend& a, - const cpp_int_backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value>::type +eval_subtract( + cpp_int_backend & result, + const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(a.sign() != b.sign()) + if (a.sign() != b.sign()) { add_unsigned(result, a, b); return; @@ -468,17 +468,14 @@ BOOST_MP_FORCEINLINE typename enable_if_c inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && (is_signed_number >::value || is_signed_number >::value) - >::type - eval_add( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) + is_trivial_cpp_int >::value && is_trivial_cpp_int >::value && (is_signed_number >::value || is_signed_number >::value)>::type +eval_add( + cpp_int_backend & result, + const cpp_int_backend &o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(result.sign() != o.sign()) + if (result.sign() != o.sign()) { - if(*o.limbs() > *result.limbs()) + if (*o.limbs() > *result.limbs()) { *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend::checked_type()); result.negate(); @@ -493,13 +490,9 @@ inline typename enable_if_c< // Simple version for two unsigned arguments: template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && is_unsigned_number >::value - && is_unsigned_number >::value - >::type - eval_add(cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) + is_trivial_cpp_int >::value && is_trivial_cpp_int >::value && is_unsigned_number >::value && is_unsigned_number >::value>::type +eval_add(cpp_int_backend & result, + const cpp_int_backend &o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); result.normalize(); @@ -508,19 +501,16 @@ BOOST_MP_FORCEINLINE typename enable_if_c< // signed subtraction: template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && (is_signed_number >::value || is_signed_number >::value) - >::type - eval_subtract( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) + is_trivial_cpp_int >::value && is_trivial_cpp_int >::value && (is_signed_number >::value || is_signed_number >::value)>::type +eval_subtract( + cpp_int_backend & result, + const cpp_int_backend &o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(result.sign() != o.sign()) + if (result.sign() != o.sign()) { *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); } - else if(*result.limbs() < *o.limbs()) + else if (*result.limbs() < *o.limbs()) { *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend::checked_type()); result.negate(); @@ -532,14 +522,10 @@ inline typename enable_if_c< template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && is_unsigned_number >::value - && is_unsigned_number >::value - >::type - eval_subtract( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) + is_trivial_cpp_int >::value && is_trivial_cpp_int >::value && is_unsigned_number >::value && is_unsigned_number >::value>::type +eval_subtract( + cpp_int_backend & result, + const cpp_int_backend &o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); result.normalize(); @@ -549,6 +535,6 @@ BOOST_MP_FORCEINLINE typename enable_if_c< #pragma warning(pop) #endif -}}} // namespaces +}}} // namespace boost::multiprecision::backends #endif diff --git a/include/boost/multiprecision/cpp_int/bitwise.hpp b/include/boost/multiprecision/cpp_int/bitwise.hpp index 307ff885b..a191f5395 100644 --- a/include/boost/multiprecision/cpp_int/bitwise.hpp +++ b/include/boost/multiprecision/cpp_int/bitwise.hpp @@ -10,830 +10,1039 @@ #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4319) +#pragma warning(disable : 4319) #endif -namespace boost{ namespace multiprecision{ namespace backends{ - -template -void is_valid_bitwise_op( - cpp_int_backend& result, - const cpp_int_backend& o, const mpl::int_&) -{ - if(result.sign() || o.sign()) - BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior.")); +namespace boost { +namespace multiprecision { +namespace backends { + +template +void is_valid_bitwise_op(cpp_int_backend &result, + const cpp_int_backend &o, + const mpl::int_ &) { + if (result.sign() || o.sign()) + BOOST_THROW_EXCEPTION( + std::range_error("Bitwise operations on negative values results in " + "undefined behavior.")); } -template +template void is_valid_bitwise_op( - cpp_int_backend&, - const cpp_int_backend& , const mpl::int_&){} + cpp_int_backend &, + const cpp_int_backend + &, + const mpl::int_ &) {} -template +template void is_valid_bitwise_op( - const cpp_int_backend& result, const mpl::int_&) -{ - if(result.sign()) - BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior.")); + const cpp_int_backend &result, + const mpl::int_ &) { + if (result.sign()) + BOOST_THROW_EXCEPTION( + std::range_error("Bitwise operations on negative values results in " + "undefined behavior.")); } -template +template void is_valid_bitwise_op( - const cpp_int_backend&, const mpl::int_&){} + const cpp_int_backend &, + const mpl::int_ &) {} -template +template void is_valid_bitwise_op( - cpp_int_backend&, const mpl::int_&){} + cpp_int_backend &, + const mpl::int_ &) {} template -void bitwise_op( - CppInt1& result, - const CppInt2& o, - Op op, const mpl::true_&) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int::value)) -{ - // - // There are 4 cases: - // * Both positive. - // * result negative, o positive. - // * o negative, result positive. - // * Both negative. - // - // When one arg is negative we convert to 2's complement form "on the fly", - // and then convert back to signed-magnitude form at the end. - // - // Note however, that if the type is checked, then bitwise ops on negative values - // are not permitted and an exception will result. - // - is_valid_bitwise_op(result, o, typename CppInt1::checked_type()); - // - // First figure out how big the result needs to be and set up some data: - // - unsigned rs = result.size(); - unsigned os = o.size(); - unsigned m, x; - minmax(rs, os, m, x); - result.resize(x, x); - typename CppInt1::limb_pointer pr = result.limbs(); - typename CppInt2::const_limb_pointer po = o.limbs(); - for(unsigned i = rs; i < x; ++i) - pr[i] = 0; - - limb_type next_limb = 0; - - if(!result.sign()) - { - if(!o.sign()) - { - for(unsigned i = 0; i < os; ++i) - pr[i] = op(pr[i], po[i]); - for(unsigned i = os; i < x; ++i) - pr[i] = op(pr[i], limb_type(0)); +void bitwise_op(CppInt1 &result, const CppInt2 &o, Op op, const mpl::true_ &) + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int::value)) { + // + // There are 4 cases: + // * Both positive. + // * result negative, o positive. + // * o negative, result positive. + // * Both negative. + // + // When one arg is negative we convert to 2's complement form "on the fly", + // and then convert back to signed-magnitude form at the end. + // + // Note however, that if the type is checked, then bitwise ops on negative + // values are not permitted and an exception will result. + // + is_valid_bitwise_op(result, o, typename CppInt1::checked_type()); + // + // First figure out how big the result needs to be and set up some data: + // + unsigned rs = result.size(); + unsigned os = o.size(); + unsigned m, x; + minmax(rs, os, m, x); + result.resize(x, x); + typename CppInt1::limb_pointer pr = result.limbs(); + typename CppInt2::const_limb_pointer po = o.limbs(); + for (unsigned i = rs; i < x; ++i) + pr[i] = 0; + + limb_type next_limb = 0; + + if (!result.sign()) { + if (!o.sign()) { + for (unsigned i = 0; i < os; ++i) + pr[i] = op(pr[i], po[i]); + for (unsigned i = os; i < x; ++i) + pr[i] = op(pr[i], limb_type(0)); + } else { + // "o" is negative: + double_limb_type carry = 1; + for (unsigned i = 0; i < os; ++i) { + carry += static_cast(~po[i]); + pr[i] = op(pr[i], static_cast(carry)); + carry >>= CppInt1::limb_bits; } - else - { - // "o" is negative: - double_limb_type carry = 1; - for(unsigned i = 0; i < os; ++i) - { - carry += static_cast(~po[i]); - pr[i] = op(pr[i], static_cast(carry)); - carry >>= CppInt1::limb_bits; - } - for(unsigned i = os; i < x; ++i) - { - carry += static_cast(~limb_type(0)); - pr[i] = op(pr[i], static_cast(carry)); - carry >>= CppInt1::limb_bits; - } - // Set the overflow into the "extra" limb: - carry += static_cast(~limb_type(0)); - next_limb = op(limb_type(0), static_cast(carry)); + for (unsigned i = os; i < x; ++i) { + carry += static_cast(~limb_type(0)); + pr[i] = op(pr[i], static_cast(carry)); + carry >>= CppInt1::limb_bits; } - } - else - { - if(!o.sign()) - { - // "result" is negative: - double_limb_type carry = 1; - for(unsigned i = 0; i < os; ++i) - { - carry += static_cast(~pr[i]); - pr[i] = op(static_cast(carry), po[i]); - carry >>= CppInt1::limb_bits; - } - for(unsigned i = os; i < x; ++i) - { - carry += static_cast(~pr[i]); - pr[i] = op(static_cast(carry), limb_type(0)); - carry >>= CppInt1::limb_bits; - } - // Set the overflow into the "extra" limb: - carry += static_cast(~limb_type(0)); - next_limb = op(static_cast(carry), limb_type(0)); + // Set the overflow into the "extra" limb: + carry += static_cast(~limb_type(0)); + next_limb = op(limb_type(0), static_cast(carry)); + } + } else { + if (!o.sign()) { + // "result" is negative: + double_limb_type carry = 1; + for (unsigned i = 0; i < os; ++i) { + carry += static_cast(~pr[i]); + pr[i] = op(static_cast(carry), po[i]); + carry >>= CppInt1::limb_bits; } - else - { - // both are negative: - double_limb_type r_carry = 1; - double_limb_type o_carry = 1; - for(unsigned i = 0; i < os; ++i) - { - r_carry += static_cast(~pr[i]); - o_carry += static_cast(~po[i]); - pr[i] = op(static_cast(r_carry), static_cast(o_carry)); - r_carry >>= CppInt1::limb_bits; - o_carry >>= CppInt1::limb_bits; - } - for(unsigned i = os; i < x; ++i) - { - r_carry += static_cast(~pr[i]); - o_carry += static_cast(~limb_type(0)); - pr[i] = op(static_cast(r_carry), static_cast(o_carry)); - r_carry >>= CppInt1::limb_bits; - o_carry >>= CppInt1::limb_bits; - } - // Set the overflow into the "extra" limb: - r_carry += static_cast(~limb_type(0)); - o_carry += static_cast(~limb_type(0)); - next_limb = op(static_cast(r_carry), static_cast(o_carry)); + for (unsigned i = os; i < x; ++i) { + carry += static_cast(~pr[i]); + pr[i] = op(static_cast(carry), limb_type(0)); + carry >>= CppInt1::limb_bits; } - } - // - // See if the result is negative or not: - // - if(static_cast(next_limb) < 0) - { - double_limb_type carry = 1; - for(unsigned i = 0; i < x; ++i) - { - carry += static_cast(~pr[i]); - pr[i] = static_cast(carry); - carry >>= CppInt1::limb_bits; + // Set the overflow into the "extra" limb: + carry += static_cast(~limb_type(0)); + next_limb = op(static_cast(carry), limb_type(0)); + } else { + // both are negative: + double_limb_type r_carry = 1; + double_limb_type o_carry = 1; + for (unsigned i = 0; i < os; ++i) { + r_carry += static_cast(~pr[i]); + o_carry += static_cast(~po[i]); + pr[i] = op(static_cast(r_carry), + static_cast(o_carry)); + r_carry >>= CppInt1::limb_bits; + o_carry >>= CppInt1::limb_bits; } - if(carry) - { - result.resize(x + 1, x); - if(result.size() > x) - result.limbs()[x] = static_cast(carry); + for (unsigned i = os; i < x; ++i) { + r_carry += static_cast(~pr[i]); + o_carry += static_cast(~limb_type(0)); + pr[i] = op(static_cast(r_carry), + static_cast(o_carry)); + r_carry >>= CppInt1::limb_bits; + o_carry >>= CppInt1::limb_bits; } - result.sign(true); - } - else - result.sign(false); - - result.normalize(); + // Set the overflow into the "extra" limb: + r_carry += static_cast(~limb_type(0)); + o_carry += static_cast(~limb_type(0)); + next_limb = + op(static_cast(r_carry), static_cast(o_carry)); + } + } + // + // See if the result is negative or not: + // + if (static_cast(next_limb) < 0) { + double_limb_type carry = 1; + for (unsigned i = 0; i < x; ++i) { + carry += static_cast(~pr[i]); + pr[i] = static_cast(carry); + carry >>= CppInt1::limb_bits; + } + if (carry) { + result.resize(x + 1, x); + if (result.size() > x) + result.limbs()[x] = static_cast(carry); + } + result.sign(true); + } else + result.sign(false); + + result.normalize(); } template -void bitwise_op( - CppInt1& result, - const CppInt2& o, - Op op, const mpl::false_&) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int::value)) -{ - // - // Both arguments are unsigned types, very simple case handled as a special case. - // - // First figure out how big the result needs to be and set up some data: - // - unsigned rs = result.size(); - unsigned os = o.size(); - unsigned m, x; - minmax(rs, os, m, x); - result.resize(x, x); - typename CppInt1::limb_pointer pr = result.limbs(); - typename CppInt2::const_limb_pointer po = o.limbs(); - for(unsigned i = rs; i < x; ++i) - pr[i] = 0; - - for(unsigned i = 0; i < os; ++i) - pr[i] = op(pr[i], po[i]); - for(unsigned i = os; i < x; ++i) - pr[i] = op(pr[i], limb_type(0)); - - result.normalize(); +void bitwise_op(CppInt1 &result, const CppInt2 &o, Op op, const mpl::false_ &) + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int::value)) { + // + // Both arguments are unsigned types, very simple case handled as a special + // case. + // + // First figure out how big the result needs to be and set up some data: + // + unsigned rs = result.size(); + unsigned os = o.size(); + unsigned m, x; + minmax(rs, os, m, x); + result.resize(x, x); + typename CppInt1::limb_pointer pr = result.limbs(); + typename CppInt2::const_limb_pointer po = o.limbs(); + for (unsigned i = rs; i < x; ++i) + pr[i] = 0; + + for (unsigned i = 0; i < os; ++i) + pr[i] = op(pr[i], po[i]); + for (unsigned i = os; i < x; ++i) + pr[i] = op(pr[i], limb_type(0)); + + result.normalize(); } -struct bit_and{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a & b; } }; -struct bit_or { limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a | b; } }; -struct bit_xor{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a ^ b; } }; - -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_bitwise_and( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - bitwise_op(result, o, bit_and(), - mpl::bool_ > >::is_signed || std::numeric_limits > >::is_signed>()); +struct bit_and { + limb_type operator()(limb_type a, limb_type b) const BOOST_NOEXCEPT { + return a & b; + } +}; +struct bit_or { + limb_type operator()(limb_type a, limb_type b) const BOOST_NOEXCEPT { + return a | b; + } +}; +struct bit_xor { + limb_type operator()(limb_type a, limb_type b) const BOOST_NOEXCEPT { + return a ^ b; + } +}; + +template +BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int>::value && + !is_trivial_cpp_int>::value>::type +eval_bitwise_and(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + bitwise_op( + result, o, bit_and(), + mpl::bool_ < + std::numeric_limits< + number>>::is_signed || + std::numeric_limits< + number>>::is_signed > ()); } -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_bitwise_or( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - bitwise_op(result, o, bit_or(), - mpl::bool_ > >::is_signed || std::numeric_limits > >::is_signed>()); +template +BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int>::value && + !is_trivial_cpp_int>::value>::type +eval_bitwise_or(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + bitwise_op( + result, o, bit_or(), + mpl::bool_ < + std::numeric_limits< + number>>::is_signed || + std::numeric_limits< + number>>::is_signed > ()); } -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_bitwise_xor( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - bitwise_op(result, o, bit_xor(), - mpl::bool_ > >::is_signed || std::numeric_limits > >::is_signed>()); +template +BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int>::value && + !is_trivial_cpp_int>::value>::type +eval_bitwise_xor(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + bitwise_op( + result, o, bit_xor(), + mpl::bool_ < + std::numeric_limits< + number>>::is_signed || + std::numeric_limits< + number>>::is_signed > ()); } // // Again for operands which are single limbs: // -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_bitwise_and( - cpp_int_backend& result, - limb_type l) BOOST_NOEXCEPT -{ - result.limbs()[0] &= l; - result.resize(1, 1); +template +BOOST_MP_FORCEINLINE typename enable_if_c>::value>::type +eval_bitwise_and(cpp_int_backend &result, + limb_type l) BOOST_NOEXCEPT { + result.limbs()[0] &= l; + result.resize(1, 1); } -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_bitwise_or( - cpp_int_backend& result, - limb_type l) BOOST_NOEXCEPT -{ - result.limbs()[0] |= l; +template +BOOST_MP_FORCEINLINE typename enable_if_c>::value>::type +eval_bitwise_or(cpp_int_backend &result, + limb_type l) BOOST_NOEXCEPT { + result.limbs()[0] |= l; } -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_bitwise_xor( - cpp_int_backend& result, - limb_type l) BOOST_NOEXCEPT -{ - result.limbs()[0] ^= l; +template +BOOST_MP_FORCEINLINE typename enable_if_c>::value>::type +eval_bitwise_xor(cpp_int_backend &result, + limb_type l) BOOST_NOEXCEPT { + result.limbs()[0] ^= l; } -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type - eval_complement( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior."); - // Increment and negate: - result = o; - eval_increment(result); - result.negate(); +template +BOOST_MP_FORCEINLINE typename enable_if_c< + is_signed_number>::value && + !is_trivial_cpp_int>::value && + !is_trivial_cpp_int>::value>::type +eval_complement(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), + "Attempt to take the complement of a signed type " + "results in undefined behavior."); + // Increment and negate: + result = o; + eval_increment(result); + result.negate(); } -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type - eval_complement( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - unsigned os = o.size(); - result.resize(UINT_MAX, os); - for(unsigned i = 0; i < os; ++i) - result.limbs()[i] = ~o.limbs()[i]; - for(unsigned i = os; i < result.size(); ++i) - result.limbs()[i] = ~static_cast(0); - result.normalize(); +template +BOOST_MP_FORCEINLINE typename enable_if_c< + is_unsigned_number>::value && + !is_trivial_cpp_int>::value && + !is_trivial_cpp_int>::value>::type +eval_complement(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + unsigned os = o.size(); + result.resize(UINT_MAX, os); + for (unsigned i = 0; i < os; ++i) + result.limbs()[i] = ~o.limbs()[i]; + for (unsigned i = os; i < result.size(); ++i) + result.limbs()[i] = ~static_cast(0); + result.normalize(); } template -inline void left_shift_byte(Int& result, double_limb_type s) -{ - limb_type offset = static_cast(s / Int::limb_bits); - limb_type shift = static_cast(s % Int::limb_bits); - unsigned ors = result.size(); - if((ors == 1) && (!*result.limbs())) - return; // shifting zero yields zero. - unsigned rs = ors; - if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift))) - ++rs; // Most significant limb will overflow when shifted - rs += offset; - result.resize(rs, rs); - rs = result.size(); - - typename Int::limb_pointer pr = result.limbs(); - - if(rs != ors) - pr[rs - 1] = 0u; - std::size_t bytes = static_cast(s / CHAR_BIT); - std::size_t len = (std::min)(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes); - if(bytes >= rs * sizeof(limb_type)) - result = static_cast(0u); - else - { - unsigned char* pc = reinterpret_cast(pr); - std::memmove(pc + bytes, pc, len); - std::memset(pc, 0, bytes); - } +inline void left_shift_byte(Int &result, double_limb_type s) { + limb_type offset = static_cast(s / Int::limb_bits); + limb_type shift = static_cast(s % Int::limb_bits); + unsigned ors = result.size(); + if ((ors == 1) && (!*result.limbs())) + return; // shifting zero yields zero. + unsigned rs = ors; + if (shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift))) + ++rs; // Most significant limb will overflow when shifted + rs += offset; + result.resize(rs, rs); + rs = result.size(); + + typename Int::limb_pointer pr = result.limbs(); + + if (rs != ors) + pr[rs - 1] = 0u; + std::size_t bytes = static_cast(s / CHAR_BIT); + std::size_t len = + (std::min)(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes); + if (bytes >= rs * sizeof(limb_type)) + result = static_cast(0u); + else { + unsigned char *pc = reinterpret_cast(pr); + std::memmove(pc + bytes, pc, len); + std::memset(pc, 0, bytes); + } } template -inline void left_shift_limb(Int& result, double_limb_type s) -{ - limb_type offset = static_cast(s / Int::limb_bits); - limb_type shift = static_cast(s % Int::limb_bits); - - unsigned ors = result.size(); - if((ors == 1) && (!*result.limbs())) - return; // shifting zero yields zero. - unsigned rs = ors; - if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift))) - ++rs; // Most significant limb will overflow when shifted - rs += offset; - result.resize(rs, rs); - - typename Int::limb_pointer pr = result.limbs(); - - if(offset > rs) - { - // The result is shifted past the end of the result: - result = static_cast(0); - return; - } - - unsigned i = rs - result.size(); - for(; i < ors; ++i) - pr[rs - 1 - i] = pr[ors - 1 - i]; - for(; i < rs; ++i) - pr[rs - 1 - i] = 0; +inline void left_shift_limb(Int &result, double_limb_type s) { + limb_type offset = static_cast(s / Int::limb_bits); + limb_type shift = static_cast(s % Int::limb_bits); + + unsigned ors = result.size(); + if ((ors == 1) && (!*result.limbs())) + return; // shifting zero yields zero. + unsigned rs = ors; + if (shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift))) + ++rs; // Most significant limb will overflow when shifted + rs += offset; + result.resize(rs, rs); + + typename Int::limb_pointer pr = result.limbs(); + + if (offset > rs) { + // The result is shifted past the end of the result: + result = static_cast(0); + return; + } + + unsigned i = rs - result.size(); + for (; i < ors; ++i) + pr[rs - 1 - i] = pr[ors - 1 - i]; + for (; i < rs; ++i) + pr[rs - 1 - i] = 0; } template -inline void left_shift_generic(Int& result, double_limb_type s) -{ - limb_type offset = static_cast(s / Int::limb_bits); - limb_type shift = static_cast(s % Int::limb_bits); - - unsigned ors = result.size(); - if((ors == 1) && (!*result.limbs())) - return; // shifting zero yields zero. - unsigned rs = ors; - if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift))) - ++rs; // Most significant limb will overflow when shifted - rs += offset; - result.resize(rs, rs); - bool truncated = result.size() != rs; - - typename Int::limb_pointer pr = result.limbs(); - - if(offset > rs) - { - // The result is shifted past the end of the result: - result = static_cast(0); - return; - } - - unsigned i = rs - result.size(); - // This code only works when shift is non-zero, otherwise we invoke undefined behaviour! - BOOST_ASSERT(shift); - if(!truncated) - { - if(rs > ors + offset) - { - pr[rs - 1 - i] = pr[ors - 1 - i] >> (Int::limb_bits - shift); - --rs; - } - else - { - pr[rs - 1 - i] = pr[ors - 1 - i] << shift; - if(ors > 1) - pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift); - ++i; - } - } - for(; rs - i >= 2 + offset; ++i) - { - pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift; - pr[rs - 1 - i] |= pr[rs - 2 - i - offset] >> (Int::limb_bits - shift); - } - if(rs - i >= 1 + offset) - { - pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift; +inline void left_shift_generic(Int &result, double_limb_type s) { + limb_type offset = static_cast(s / Int::limb_bits); + limb_type shift = static_cast(s % Int::limb_bits); + + unsigned ors = result.size(); + if ((ors == 1) && (!*result.limbs())) + return; // shifting zero yields zero. + unsigned rs = ors; + if (shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift))) + ++rs; // Most significant limb will overflow when shifted + rs += offset; + result.resize(rs, rs); + bool truncated = result.size() != rs; + + typename Int::limb_pointer pr = result.limbs(); + + if (offset > rs) { + // The result is shifted past the end of the result: + result = static_cast(0); + return; + } + + unsigned i = rs - result.size(); + // This code only works when shift is non-zero, otherwise we invoke undefined + // behaviour! + BOOST_ASSERT(shift); + if (!truncated) { + if (rs > ors + offset) { + pr[rs - 1 - i] = pr[ors - 1 - i] >> (Int::limb_bits - shift); + --rs; + } else { + pr[rs - 1 - i] = pr[ors - 1 - i] << shift; + if (ors > 1) + pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift); ++i; - } - for(; i < rs; ++i) - pr[rs - 1 - i] = 0; + } + } + for (; rs - i >= 2 + offset; ++i) { + pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift; + pr[rs - 1 - i] |= pr[rs - 2 - i - offset] >> (Int::limb_bits - shift); + } + if (rs - i >= 1 + offset) { + pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift; + ++i; + } + for (; i < rs; ++i) + pr[rs - 1 - i] = 0; } -template -inline typename enable_if_c >::value>::type - eval_left_shift( - cpp_int_backend& result, - double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - is_valid_bitwise_op(result, typename cpp_int_backend::checked_type()); - if(!s) - return; +template +inline typename enable_if_c>::value>::type +eval_left_shift(cpp_int_backend &result, + double_limb_type s) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + is_valid_bitwise_op( + result, typename cpp_int_backend::checked_type()); + if (!s) + return; #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT) - static const limb_type limb_shift_mask = cpp_int_backend::limb_bits - 1; - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if((s & limb_shift_mask) == 0) - { - left_shift_limb(result, s); - } - else if((s & byte_shift_mask) == 0) - { - left_shift_byte(result, s); - } + static const limb_type limb_shift_mask = + cpp_int_backend::limb_bits - + 1; + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & limb_shift_mask) == 0) { + left_shift_limb(result, s); + } else if ((s & byte_shift_mask) == 0) { + left_shift_byte(result, s); + } #elif BOOST_ENDIAN_LITTLE_BYTE - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if((s & byte_shift_mask) == 0) - { - left_shift_byte(result, s); - } + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & byte_shift_mask) == 0) { + left_shift_byte(result, s); + } #else - static const limb_type limb_shift_mask = cpp_int_backend::limb_bits - 1; - if((s & limb_shift_mask) == 0) - { - left_shift_limb(result, s); - } + static const limb_type limb_shift_mask = + cpp_int_backend::limb_bits - + 1; + if ((s & limb_shift_mask) == 0) { + left_shift_limb(result, s); + } #endif - else - { - left_shift_generic(result, s); - } - // - // We may have shifted off the end and have leading zeros: - // - result.normalize(); + else { + left_shift_generic(result, s); + } + // + // We may have shifted off the end and have leading zeros: + // + result.normalize(); } template -inline void right_shift_byte(Int& result, double_limb_type s) -{ - limb_type offset = static_cast(s / Int::limb_bits); - limb_type shift; - BOOST_ASSERT((s % CHAR_BIT) == 0); - unsigned ors = result.size(); - unsigned rs = ors; - if(offset >= rs) - { - result = limb_type(0); - return; - } - rs -= offset; - typename Int::limb_pointer pr = result.limbs(); - unsigned char* pc = reinterpret_cast(pr); - shift = static_cast(s / CHAR_BIT); - std::memmove(pc, pc + shift, ors * sizeof(pr[0]) - shift); - shift = (sizeof(limb_type) - shift % sizeof(limb_type)) * CHAR_BIT; - if(shift < Int::limb_bits) - { - pr[ors - offset - 1] &= (static_cast(1u) << shift) - 1; - if(!pr[ors - offset - 1] && (rs > 1)) - --rs; - } - result.resize(rs, rs); +inline void right_shift_byte(Int &result, double_limb_type s) { + limb_type offset = static_cast(s / Int::limb_bits); + limb_type shift; + BOOST_ASSERT((s % CHAR_BIT) == 0); + unsigned ors = result.size(); + unsigned rs = ors; + if (offset >= rs) { + result = limb_type(0); + return; + } + rs -= offset; + typename Int::limb_pointer pr = result.limbs(); + unsigned char *pc = reinterpret_cast(pr); + shift = static_cast(s / CHAR_BIT); + std::memmove(pc, pc + shift, ors * sizeof(pr[0]) - shift); + shift = (sizeof(limb_type) - shift % sizeof(limb_type)) * CHAR_BIT; + if (shift < Int::limb_bits) { + pr[ors - offset - 1] &= (static_cast(1u) << shift) - 1; + if (!pr[ors - offset - 1] && (rs > 1)) + --rs; + } + result.resize(rs, rs); } template -inline void right_shift_limb(Int& result, double_limb_type s) -{ - limb_type offset = static_cast(s / Int::limb_bits); - BOOST_ASSERT((s % Int::limb_bits) == 0); - unsigned ors = result.size(); - unsigned rs = ors; - if(offset >= rs) - { - result = limb_type(0); - return; - } - rs -= offset; - typename Int::limb_pointer pr = result.limbs(); - unsigned i = 0; - for(; i < rs; ++i) - pr[i] = pr[i + offset]; - result.resize(rs, rs); +inline void right_shift_limb(Int &result, double_limb_type s) { + limb_type offset = static_cast(s / Int::limb_bits); + BOOST_ASSERT((s % Int::limb_bits) == 0); + unsigned ors = result.size(); + unsigned rs = ors; + if (offset >= rs) { + result = limb_type(0); + return; + } + rs -= offset; + typename Int::limb_pointer pr = result.limbs(); + unsigned i = 0; + for (; i < rs; ++i) + pr[i] = pr[i + offset]; + result.resize(rs, rs); } template -inline void right_shift_generic(Int& result, double_limb_type s) -{ - limb_type offset = static_cast(s / Int::limb_bits); - limb_type shift = static_cast(s % Int::limb_bits); - unsigned ors = result.size(); - unsigned rs = ors; - if(offset >= rs) - { +inline void right_shift_generic(Int &result, double_limb_type s) { + limb_type offset = static_cast(s / Int::limb_bits); + limb_type shift = static_cast(s % Int::limb_bits); + unsigned ors = result.size(); + unsigned rs = ors; + if (offset >= rs) { + result = limb_type(0); + return; + } + rs -= offset; + typename Int::limb_pointer pr = result.limbs(); + if ((pr[ors - 1] >> shift) == 0) { + if (--rs == 0) { result = limb_type(0); return; - } - rs -= offset; - typename Int::limb_pointer pr = result.limbs(); - if((pr[ors - 1] >> shift) == 0) - { - if(--rs == 0) - { - result = limb_type(0); - return; - } - } - unsigned i = 0; - - // This code only works for non-zero shift, otherwise we invoke undefined behaviour! - BOOST_ASSERT(shift); - for(; i + offset + 1 < ors; ++i) - { - pr[i] = pr[i + offset] >> shift; - pr[i] |= pr[i + offset + 1] << (Int::limb_bits - shift); - } - pr[i] = pr[i + offset] >> shift; - result.resize(rs, rs); + } + } + unsigned i = 0; + + // This code only works for non-zero shift, otherwise we invoke undefined + // behaviour! + BOOST_ASSERT(shift); + for (; i + offset + 1 < ors; ++i) { + pr[i] = pr[i + offset] >> shift; + pr[i] |= pr[i + offset + 1] << (Int::limb_bits - shift); + } + pr[i] = pr[i + offset] >> shift; + result.resize(rs, rs); } -template -inline typename enable_if_c >::value>::type - eval_right_shift( - cpp_int_backend& result, - double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - is_valid_bitwise_op(result, typename cpp_int_backend::checked_type()); - if(!s) - return; +template +inline typename enable_if_c>::value>::type +eval_right_shift(cpp_int_backend &result, + double_limb_type s) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + cpp_int_backend>::value)) { + is_valid_bitwise_op( + result, typename cpp_int_backend::checked_type()); + if (!s) + return; #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT) - static const limb_type limb_shift_mask = cpp_int_backend::limb_bits - 1; - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if((s & limb_shift_mask) == 0) - right_shift_limb(result, s); - else if((s & byte_shift_mask) == 0) - right_shift_byte(result, s); + static const limb_type limb_shift_mask = + cpp_int_backend::limb_bits - + 1; + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & limb_shift_mask) == 0) + right_shift_limb(result, s); + else if ((s & byte_shift_mask) == 0) + right_shift_byte(result, s); #elif BOOST_ENDIAN_LITTLE_BYTE - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if((s & byte_shift_mask) == 0) - right_shift_byte(result, s); + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & byte_shift_mask) == 0) + right_shift_byte(result, s); #else - static const limb_type limb_shift_mask = cpp_int_backend::limb_bits - 1; - if((s & limb_shift_mask) == 0) - right_shift_limb(result, s); + static const limb_type limb_shift_mask = + cpp_int_backend::limb_bits - + 1; + if ((s & limb_shift_mask) == 0) + right_shift_limb(result, s); #endif - else - right_shift_generic(result, s); + else + right_shift_generic(result, s); } -template -inline typename enable_if_c >::value>::type - eval_right_shift( - cpp_int_backend& result, - double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - is_valid_bitwise_op(result, typename cpp_int_backend::checked_type()); - if(!s) - return; - - bool is_neg = result.sign(); - if(is_neg) - eval_increment(result); +template +inline typename enable_if_c>::value>::type +eval_right_shift(cpp_int_backend &result, + double_limb_type s) + BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< + cpp_int_backend>::value)) { + is_valid_bitwise_op( + result, typename cpp_int_backend::checked_type()); + if (!s) + return; + + bool is_neg = result.sign(); + if (is_neg) + eval_increment(result); #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT) - static const limb_type limb_shift_mask = cpp_int_backend::limb_bits - 1; - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if((s & limb_shift_mask) == 0) - right_shift_limb(result, s); - else if((s & byte_shift_mask) == 0) - right_shift_byte(result, s); + static const limb_type limb_shift_mask = + cpp_int_backend::limb_bits - + 1; + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & limb_shift_mask) == 0) + right_shift_limb(result, s); + else if ((s & byte_shift_mask) == 0) + right_shift_byte(result, s); #elif BOOST_ENDIAN_LITTLE_BYTE - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if((s & byte_shift_mask) == 0) - right_shift_byte(result, s); + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & byte_shift_mask) == 0) + right_shift_byte(result, s); #else - static const limb_type limb_shift_mask = cpp_int_backend::limb_bits - 1; - if((s & limb_shift_mask) == 0) - right_shift_limb(result, s); + static const limb_type limb_shift_mask = + cpp_int_backend::limb_bits - + 1; + if ((s & limb_shift_mask) == 0) + right_shift_limb(result, s); #endif - else - right_shift_generic(result, s); - if(is_neg) - eval_decrement(result); + else + right_shift_generic(result, s); + if (is_neg) + eval_decrement(result); } // // Over again for trivial cpp_int's: // -template -BOOST_MP_FORCEINLINE typename enable_if > >::type - eval_left_shift(cpp_int_backend& result, T s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - is_valid_bitwise_op(result, typename cpp_int_backend::checked_type()); - *result.limbs() = detail::checked_left_shift(*result.limbs(), s, typename cpp_int_backend::checked_type()); - result.normalize(); +template +BOOST_MP_FORCEINLINE typename enable_if>>::type +eval_left_shift(cpp_int_backend &result, + T s) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + is_valid_bitwise_op( + result, typename cpp_int_backend::checked_type()); + *result.limbs() = detail::checked_left_shift( + *result.limbs(), s, + typename cpp_int_backend::checked_type()); + result.normalize(); } -template -BOOST_MP_FORCEINLINE typename enable_if > >::type - eval_right_shift(cpp_int_backend& result, T s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - // Nothing to check here... just make sure we don't invoke undefined behavior: - is_valid_bitwise_op(result, typename cpp_int_backend::checked_type()); - *result.limbs() = (static_cast(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign() ? ((--*result.limbs()) >> s) + 1 : *result.limbs() >> s); - if(result.sign() && (*result.limbs() == 0)) - result = static_cast(-1); +template +BOOST_MP_FORCEINLINE typename enable_if>>::type +eval_right_shift(cpp_int_backend &result, + T s) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + // Nothing to check here... just make sure we don't invoke undefined behavior: + is_valid_bitwise_op( + result, typename cpp_int_backend::checked_type()); + *result.limbs() = + (static_cast(s) >= sizeof(*result.limbs()) * CHAR_BIT) + ? 0 + : (result.sign() ? ((--*result.limbs()) >> s) + 1 + : *result.limbs() >> s); + if (result.sign() && (*result.limbs() == 0)) + result = static_cast(-1); } -template +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && (is_signed_number >::value || is_signed_number >::value) - >::type - eval_complement( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior."); - // - // If we're not checked then emulate 2's complement behavior: - // - if(o.sign()) - { - *result.limbs() = *o.limbs() - 1; - result.sign(false); - } - else - { - *result.limbs() = 1 + *o.limbs(); - result.sign(true); - } - result.normalize(); + is_trivial_cpp_int>::value && + is_trivial_cpp_int>::value && + (is_signed_number>::value || + is_signed_number>::value)>::type +eval_complement(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), + "Attempt to take the complement of a signed type " + "results in undefined behavior."); + // + // If we're not checked then emulate 2's complement behavior: + // + if (o.sign()) { + *result.limbs() = *o.limbs() - 1; + result.sign(false); + } else { + *result.limbs() = 1 + *o.limbs(); + result.sign(true); + } + result.normalize(); } -template +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && is_unsigned_number >::value - && is_unsigned_number >::value - >::type - eval_complement( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - *result.limbs() = ~*o.limbs(); - result.normalize(); + is_trivial_cpp_int>::value && + is_trivial_cpp_int>::value && + is_unsigned_number>::value && + is_unsigned_number>::value>::type +eval_complement(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + *result.limbs() = ~*o.limbs(); + result.normalize(); } -template +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && is_unsigned_number >::value - && is_unsigned_number >::value - >::type - eval_bitwise_and( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - *result.limbs() &= *o.limbs(); + is_trivial_cpp_int>::value && + is_trivial_cpp_int>::value && + is_unsigned_number>::value && + is_unsigned_number>::value>::type +eval_bitwise_and(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + *result.limbs() &= *o.limbs(); } -template +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && (is_signed_number >::value || is_signed_number >::value) - >::type - eval_bitwise_and( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - is_valid_bitwise_op(result, o, typename cpp_int_backend::checked_type()); - - using default_ops::eval_bit_test; - using default_ops::eval_increment; - - if(result.sign() || o.sign()) - { - static const unsigned m = static_unsigned_max::value, static_unsigned_max::value>::value; - cpp_int_backend t1(result); - cpp_int_backend t2(o); - eval_bitwise_and(t1, t2); - bool s = eval_bit_test(t1, m + 1); - if(s) - { - eval_complement(t1, t1); - eval_increment(t1); - } - result = t1; - result.sign(s); - } - else - { - *result.limbs() &= *o.limbs(); - } + is_trivial_cpp_int>::value && + is_trivial_cpp_int>::value && + (is_signed_number>::value || + is_signed_number>::value)>::type +eval_bitwise_and(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + is_valid_bitwise_op( + result, o, + typename cpp_int_backend::checked_type()); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if (result.sign() || o.sign()) { + static const unsigned m = static_unsigned_max< + static_unsigned_max::value, + static_unsigned_max::value>::value; + cpp_int_backend t1( + result); + cpp_int_backend t2(o); + eval_bitwise_and(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if (s) { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } else { + *result.limbs() &= *o.limbs(); + } } -template +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && is_unsigned_number >::value - && is_unsigned_number >::value - >::type - eval_bitwise_or( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - *result.limbs() |= *o.limbs(); + is_trivial_cpp_int>::value && + is_trivial_cpp_int>::value && + is_unsigned_number>::value && + is_unsigned_number>::value>::type +eval_bitwise_or(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + *result.limbs() |= *o.limbs(); } -template +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && (is_signed_number >::value || is_signed_number >::value) - >::type - eval_bitwise_or( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - is_valid_bitwise_op(result, o, typename cpp_int_backend::checked_type()); - - using default_ops::eval_bit_test; - using default_ops::eval_increment; - - if(result.sign() || o.sign()) - { - static const unsigned m = static_unsigned_max::value, static_unsigned_max::value>::value; - cpp_int_backend t1(result); - cpp_int_backend t2(o); - eval_bitwise_or(t1, t2); - bool s = eval_bit_test(t1, m + 1); - if(s) - { - eval_complement(t1, t1); - eval_increment(t1); - } - result = t1; - result.sign(s); - } - else - { - *result.limbs() |= *o.limbs(); - result.normalize(); - } + is_trivial_cpp_int>::value && + is_trivial_cpp_int>::value && + (is_signed_number>::value || + is_signed_number>::value)>::type +eval_bitwise_or(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + is_valid_bitwise_op( + result, o, + typename cpp_int_backend::checked_type()); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if (result.sign() || o.sign()) { + static const unsigned m = static_unsigned_max< + static_unsigned_max::value, + static_unsigned_max::value>::value; + cpp_int_backend t1( + result); + cpp_int_backend t2(o); + eval_bitwise_or(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if (s) { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } else { + *result.limbs() |= *o.limbs(); + result.normalize(); + } } -template +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && is_unsigned_number >::value - && is_unsigned_number >::value - >::type - eval_bitwise_xor( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - *result.limbs() ^= *o.limbs(); + is_trivial_cpp_int>::value && + is_trivial_cpp_int>::value && + is_unsigned_number>::value && + is_unsigned_number>::value>::type +eval_bitwise_xor(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + *result.limbs() ^= *o.limbs(); } -template +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && (is_signed_number >::value || is_signed_number >::value) - >::type - eval_bitwise_xor( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - is_valid_bitwise_op(result, o, typename cpp_int_backend::checked_type()); - - using default_ops::eval_bit_test; - using default_ops::eval_increment; - - if(result.sign() || o.sign()) - { - static const unsigned m = static_unsigned_max::value, static_unsigned_max::value>::value; - cpp_int_backend t1(result); - cpp_int_backend t2(o); - eval_bitwise_xor(t1, t2); - bool s = eval_bit_test(t1, m + 1); - if(s) - { - eval_complement(t1, t1); - eval_increment(t1); - } - result = t1; - result.sign(s); - } - else - { - *result.limbs() ^= *o.limbs(); - } + is_trivial_cpp_int>::value && + is_trivial_cpp_int>::value && + (is_signed_number>::value || + is_signed_number>::value)>::type +eval_bitwise_xor(cpp_int_backend &result, + const cpp_int_backend &o) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + is_valid_bitwise_op( + result, o, + typename cpp_int_backend::checked_type()); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if (result.sign() || o.sign()) { + static const unsigned m = static_unsigned_max< + static_unsigned_max::value, + static_unsigned_max::value>::value; + cpp_int_backend t1( + result); + cpp_int_backend t2(o); + eval_bitwise_xor(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if (s) { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } else { + *result.limbs() ^= *o.limbs(); + } } -}}} // namespaces +} // namespace backends +} // namespace multiprecision +} // namespace boost #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/multiprecision/cpp_int/comparison.hpp b/include/boost/multiprecision/cpp_int/comparison.hpp index cf58ee0b0..8ee0b2df6 100644 --- a/include/boost/multiprecision/cpp_int/comparison.hpp +++ b/include/boost/multiprecision/cpp_int/comparison.hpp @@ -10,390 +10,502 @@ #include -namespace boost{ namespace multiprecision{ namespace backends{ +namespace boost { +namespace multiprecision { +namespace backends { #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:4018 4389 4996) +#pragma warning(disable : 4018 4389 4996) #endif // // Start with non-trivial cpp_int's: // -template +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type - eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT -{ + !is_trivial_cpp_int< + cpp_int_backend>::value, + bool>::type +eval_eq( + const cpp_int_backend &a, + const cpp_int_backend &b) + BOOST_NOEXCEPT { #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) - return (a.sign() == b.sign()) - && (a.size() == b.size()) - && std::equal(a.limbs(), a.limbs() + a.size(), - stdext::checked_array_iterator::const_limb_pointer>(b.limbs(), b.size())); + return (a.sign() == b.sign()) && (a.size() == b.size()) && + std::equal(a.limbs(), a.limbs() + a.size(), + stdext::checked_array_iterator< + cpp_int_backend::const_limb_pointer>( + b.limbs(), b.size())); #else - return (a.sign() == b.sign()) - && (a.size() == b.size()) - && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); + return (a.sign() == b.sign()) && (a.size() == b.size()) && + std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); #endif } -template +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value - && !is_trivial_cpp_int >::value, - bool - >::type - eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT -{ + !is_trivial_cpp_int>::value && + !is_trivial_cpp_int>::value, + bool>::type +eval_eq(const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_NOEXCEPT { #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) - return (a.sign() == b.sign()) - && (a.size() == b.size()) - && std::equal(a.limbs(), a.limbs() + a.size(), stdext::checked_array_iterator::const_limb_pointer>(b.limbs(), b.size())); + return (a.sign() == b.sign()) && (a.size() == b.size()) && + std::equal(a.limbs(), a.limbs() + a.size(), + stdext::checked_array_iterator< + cpp_int_backend::const_limb_pointer>( + b.limbs(), b.size())); #else - return (a.sign() == b.sign()) - && (a.size() == b.size()) - && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); + return (a.sign() == b.sign()) && (a.size() == b.size()) && + std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); #endif } -template +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_eq(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT -{ - return (a.sign() == false) - && (a.size() == 1) - && (*a.limbs() == b); -} -template + !is_trivial_cpp_int>::value, + bool>::type +eval_eq(const cpp_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + return (a.sign() == false) && (a.size() == 1) && (*a.limbs() == b); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_eq(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT -{ - return (a.sign() == (b < 0)) - && (a.size() == 1) - && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b)); -} -template + !is_trivial_cpp_int>::value, + bool>::type +eval_eq(const cpp_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + return (a.sign() == (b < 0)) && (a.size() == 1) && + (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b)); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_eq(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT -{ - return (a.size() == 1) - && (*a.limbs() == b); -} -template + !is_trivial_cpp_int>::value, + bool>::type +eval_eq(const cpp_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + return (a.size() == 1) && (*a.limbs() == b); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_eq(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT -{ - return (b < 0) ? eval_eq(a, cpp_int_backend(b)) : eval_eq(a, static_cast(b)); // Use bit pattern of b for comparison + !is_trivial_cpp_int>::value, + bool>::type +eval_eq(const cpp_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + return (b < 0) + ? eval_eq(a, cpp_int_backend(b)) + : eval_eq(a, static_cast( + b)); // Use bit pattern of b for comparison } -template +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT -{ - if(a.sign()) + !is_trivial_cpp_int>::value, + bool>::type +eval_lt(const cpp_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + if (a.sign()) + return true; + if (a.size() > 1) + return false; + return *a.limbs() < b; +} +template +inline typename enable_if_c< + !is_trivial_cpp_int>::value, + bool>::type +eval_lt(const cpp_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + if ((b == 0) || (a.sign() != (b < 0))) + return a.sign(); + if (a.sign()) { + if (a.size() > 1) return true; - if(a.size() > 1) + return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b); + } else { + if (a.size() > 1) return false; - return *a.limbs() < b; -} -template -inline typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT -{ - if((b == 0) || (a.sign() != (b < 0))) - return a.sign(); - if(a.sign()) - { - if(a.size() > 1) - return true; - return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b); - } - else - { - if(a.size() > 1) - return false; - return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b); - } + return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b); + } } -template +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT -{ - if(a.size() > 1) - return false; - return *a.limbs() < b; -} -template + !is_trivial_cpp_int>::value, + bool>::type +eval_lt(const cpp_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + if (a.size() > 1) + return false; + return *a.limbs() < b; +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT -{ - return (b < 0) ? a.compare(b) < 0 : eval_lt(a, static_cast(b)); // Use bit pattern of b for comparison + !is_trivial_cpp_int>::value, + bool>::type +eval_lt(const cpp_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + return (b < 0) ? a.compare(b) < 0 + : eval_lt(a, static_cast( + b)); // Use bit pattern of b for comparison } -template +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT -{ - if(a.sign()) + !is_trivial_cpp_int>::value, + bool>::type +eval_gt(const cpp_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + if (a.sign()) + return false; + if (a.size() > 1) + return true; + return *a.limbs() > b; +} +template +inline typename enable_if_c< + !is_trivial_cpp_int>::value, + bool>::type +eval_gt(const cpp_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + if (b == 0) + return !a.sign() && ((a.size() > 1) || *a.limbs()); + if (a.sign() != (b < 0)) + return !a.sign(); + if (a.sign()) { + if (a.size() > 1) return false; - if(a.size() > 1) + return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b); + } else { + if (a.size() > 1) return true; - return *a.limbs() > b; -} -template -inline typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT -{ - if(b == 0) - return !a.sign() && ((a.size() > 1) || *a.limbs()); - if(a.sign() != (b < 0)) - return !a.sign(); - if(a.sign()) - { - if(a.size() > 1) - return false; - return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b); - } - else - { - if(a.size() > 1) - return true; - return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b); - } + return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b); + } } -template +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT -{ - if(a.size() > 1) - return true; - return *a.limbs() > b; -} -template + !is_trivial_cpp_int>::value, + bool>::type +eval_gt(const cpp_int_backend &a, + limb_type b) BOOST_NOEXCEPT { + if (a.size() > 1) + return true; + return *a.limbs() > b; +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT -{ - return (b < 0) ? a.compare(b) > 0 : eval_gt(a, static_cast(b)); // Use bit pattern of b for comparison. + !is_trivial_cpp_int>::value, + bool>::type +eval_gt(const cpp_int_backend &a, + signed_limb_type b) BOOST_NOEXCEPT { + return (b < 0) ? a.compare(b) > 0 + : eval_gt(a, static_cast( + b)); // Use bit pattern of b for comparison. } // // And again for trivial cpp_ints: // template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value, - bool - >::value eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT -{ - return (a.sign() == b.sign()) && (*a.limbs() == *b.limbs()); + is_trivial_cpp_int>::value, + bool>::value +eval_eq( + const cpp_int_backend &a, + const cpp_int_backend &b) + BOOST_NOEXCEPT { + return (a.sign() == b.sign()) && (*a.limbs() == *b.limbs()); } template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value, - bool - >::value eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT -{ - return *a.limbs() == *b.limbs(); -} -template + is_trivial_cpp_int>::value, + bool>::value +eval_eq(const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_NOEXCEPT { + return *a.limbs() == *b.limbs(); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_unsigned::value && is_trivial_cpp_int >::value, - bool - >::type eval_eq(const cpp_int_backend& a, U b) BOOST_NOEXCEPT -{ - return !a.sign() && (*a.limbs() == b); -} -template + is_unsigned::value && + is_trivial_cpp_int>::value, + bool>::type +eval_eq( + const cpp_int_backend &a, + U b) BOOST_NOEXCEPT { + return !a.sign() && (*a.limbs() == b); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_signed::value && is_trivial_cpp_int >::value, - bool - >::type eval_eq(const cpp_int_backend& a, S b) BOOST_NOEXCEPT -{ - return (a.sign() == (b < 0)) && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b)); -} -template + is_signed::value && + is_trivial_cpp_int>::value, + bool>::type +eval_eq( + const cpp_int_backend &a, + S b) BOOST_NOEXCEPT { + return (a.sign() == (b < 0)) && + (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b)); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_unsigned::value && is_trivial_cpp_int >::value, - bool - >::type eval_eq(const cpp_int_backend& a, U b) BOOST_NOEXCEPT -{ - return *a.limbs() == b; -} -template + is_unsigned::value && + is_trivial_cpp_int>::value, + bool>::type +eval_eq(const cpp_int_backend &a, + U b) BOOST_NOEXCEPT { + return *a.limbs() == b; +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_signed::value && is_trivial_cpp_int >::value, - bool - >::type eval_eq(const cpp_int_backend& a, S b) BOOST_NOEXCEPT -{ - typedef typename make_unsigned::type ui_type; - if(b < 0) - { - cpp_int_backend t(b); - return *a.limbs() == *t.limbs(); - } - else - { - return *a.limbs() == static_cast(b); - } + is_signed::value && + is_trivial_cpp_int>::value, + bool>::type +eval_eq(const cpp_int_backend &a, + S b) BOOST_NOEXCEPT { + typedef typename make_unsigned::type ui_type; + if (b < 0) { + cpp_int_backend t(b); + return *a.limbs() == *t.limbs(); + } else { + return *a.limbs() == static_cast(b); + } } template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT -{ - if(a.sign() != b.sign()) - return a.sign(); - return a.sign() ? *a.limbs() > *b.limbs() : *a.limbs() < *b.limbs(); + is_trivial_cpp_int>::value, + bool>::type +eval_lt( + const cpp_int_backend &a, + const cpp_int_backend + &b) BOOST_NOEXCEPT { + if (a.sign() != b.sign()) + return a.sign(); + return a.sign() ? *a.limbs() > *b.limbs() : *a.limbs() < *b.limbs(); } template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT -{ - return *a.limbs() < *b.limbs(); -} -template + is_trivial_cpp_int>::value, + bool>::type +eval_lt(const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_NOEXCEPT { + return *a.limbs() < *b.limbs(); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_unsigned::value && is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT -{ - if(a.sign()) - return true; - return *a.limbs() < b; -} -template + is_unsigned::value && + is_trivial_cpp_int>::value, + bool>::type +eval_lt( + const cpp_int_backend &a, + U b) BOOST_NOEXCEPT { + if (a.sign()) + return true; + return *a.limbs() < b; +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_signed::value && is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT -{ - if(a.sign() != (b < 0)) - return a.sign(); - return a.sign() ? (*a.limbs() > boost::multiprecision::detail::unsigned_abs(b)) : (*a.limbs() < boost::multiprecision::detail::unsigned_abs(b)); -} -template + is_signed::value && + is_trivial_cpp_int>::value, + bool>::type +eval_lt( + const cpp_int_backend &a, + S b) BOOST_NOEXCEPT { + if (a.sign() != (b < 0)) + return a.sign(); + return a.sign() + ? (*a.limbs() > boost::multiprecision::detail::unsigned_abs(b)) + : (*a.limbs() < boost::multiprecision::detail::unsigned_abs(b)); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_unsigned::value && is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT -{ - return *a.limbs() < b; -} -template + is_unsigned::value && + is_trivial_cpp_int>::value, + bool>::type +eval_lt(const cpp_int_backend &a, + U b) BOOST_NOEXCEPT { + return *a.limbs() < b; +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_signed::value && is_trivial_cpp_int >::value, - bool - >::type eval_lt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT -{ - typedef typename make_unsigned::type ui_type; - if(b < 0) - { - cpp_int_backend t(b); - return *a.limbs() < *t.limbs(); - } - else - { - return *a.limbs() < static_cast(b); - } + is_signed::value && + is_trivial_cpp_int>::value, + bool>::type +eval_lt(const cpp_int_backend &a, + S b) BOOST_NOEXCEPT { + typedef typename make_unsigned::type ui_type; + if (b < 0) { + cpp_int_backend t(b); + return *a.limbs() < *t.limbs(); + } else { + return *a.limbs() < static_cast(b); + } } template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT -{ - if(a.sign() != b.sign()) - return !a.sign(); - return a.sign() ? *a.limbs() < *b.limbs() : *a.limbs() > *b.limbs(); + is_trivial_cpp_int>::value, + bool>::type +eval_gt( + const cpp_int_backend &a, + const cpp_int_backend &b) + BOOST_NOEXCEPT { + if (a.sign() != b.sign()) + return !a.sign(); + return a.sign() ? *a.limbs() < *b.limbs() : *a.limbs() > *b.limbs(); } template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT -{ - return *a.limbs() > *b.limbs(); -} -template + is_trivial_cpp_int>::value, + bool>::type +eval_gt(const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_NOEXCEPT { + return *a.limbs() > *b.limbs(); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_unsigned::value && is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT -{ - if(a.sign()) - return false; - return *a.limbs() > b; -} -template + is_unsigned::value && + is_trivial_cpp_int>::value, + bool>::type +eval_gt( + const cpp_int_backend &a, + U b) BOOST_NOEXCEPT { + if (a.sign()) + return false; + return *a.limbs() > b; +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_signed::value && is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT -{ - if(a.sign() != (b < 0)) - return !a.sign(); - return a.sign() ? (*a.limbs() < boost::multiprecision::detail::unsigned_abs(b)) : (*a.limbs() > boost::multiprecision::detail::unsigned_abs(b)); -} -template + is_signed::value && + is_trivial_cpp_int>::value, + bool>::type +eval_gt( + const cpp_int_backend &a, + S b) BOOST_NOEXCEPT { + if (a.sign() != (b < 0)) + return !a.sign(); + return a.sign() + ? (*a.limbs() < boost::multiprecision::detail::unsigned_abs(b)) + : (*a.limbs() > boost::multiprecision::detail::unsigned_abs(b)); +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_unsigned::value && is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT -{ - return *a.limbs() > b; -} -template + is_unsigned::value && + is_trivial_cpp_int>::value, + bool>::type +eval_gt(const cpp_int_backend &a, + U b) BOOST_NOEXCEPT { + return *a.limbs() > b; +} +template BOOST_MP_FORCEINLINE typename enable_if_c< - is_signed::value && is_trivial_cpp_int >::value, - bool - >::type eval_gt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT -{ - typedef typename make_unsigned::type ui_type; - if(b < 0) - { - cpp_int_backend t(b); - return *a.limbs() > *t.limbs(); - } - else - { - return *a.limbs() > static_cast(b); - } + is_signed::value && + is_trivial_cpp_int>::value, + bool>::type +eval_gt(const cpp_int_backend &a, + S b) BOOST_NOEXCEPT { + typedef typename make_unsigned::type ui_type; + if (b < 0) { + cpp_int_backend t(b); + return *a.limbs() > *t.limbs(); + } else { + return *a.limbs() > static_cast(b); + } } #ifdef BOOST_MSVC #pragma warning(pop) #endif -}}} // namespaces +} // namespace backends +} // namespace multiprecision +} // namespace boost #endif diff --git a/include/boost/multiprecision/cpp_int/import_export.hpp b/include/boost/multiprecision/cpp_int/import_export.hpp index 9aad882b2..4f2b06a30 100644 --- a/include/boost/multiprecision/cpp_int/import_export.hpp +++ b/include/boost/multiprecision/cpp_int/import_export.hpp @@ -6,246 +6,306 @@ #ifndef BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP #define BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP - namespace boost { - namespace multiprecision { - - namespace detail { - - template - void assign_bits(Backend& val, Unsigned bits, unsigned bit_location, unsigned chunk_bits, const mpl::false_& tag) - { - unsigned limb = bit_location / (sizeof(limb_type) * CHAR_BIT); - unsigned shift = bit_location % (sizeof(limb_type) * CHAR_BIT); - - limb_type mask = chunk_bits >= sizeof(limb_type) * CHAR_BIT ? ~static_cast(0u) : (static_cast(1u) << chunk_bits) - 1; - - limb_type value = static_cast(bits & mask) << shift; - if(value) - { - if(val.size() == limb) - { - val.resize(limb + 1, limb + 1); - if(val.size() > limb) - val.limbs()[limb] = value; - } - else if(val.size() > limb) - val.limbs()[limb] |= value; - } - if(chunk_bits > sizeof(limb_type) * CHAR_BIT - shift) - { - shift = sizeof(limb_type) * CHAR_BIT - shift; - chunk_bits -= shift; - bit_location += shift; - bits >>= shift; - if(bits) - assign_bits(val, bits, bit_location, chunk_bits, tag); - } - } - template - void assign_bits(Backend& val, Unsigned bits, unsigned bit_location, unsigned chunk_bits, const mpl::true_&) - { - typedef typename Backend::local_limb_type local_limb_type; - // - // Check for possible overflow, this may trigger an exception, or have no effect - // depending on whether this is a checked integer or not: - // - if((bit_location >= sizeof(local_limb_type) * CHAR_BIT) && bits) - val.resize(2, 2); - else - { - local_limb_type mask = chunk_bits >= sizeof(local_limb_type) * CHAR_BIT ? ~static_cast(0u) : (static_cast(1u) << chunk_bits) - 1; - local_limb_type value = (static_cast(bits) & mask) << bit_location; - *val.limbs() |= value; - // - // Check for overflow bits: - // - bit_location = sizeof(local_limb_type) * CHAR_BIT - bit_location; - if((bit_location < sizeof(bits)*CHAR_BIT) && (bits >>= bit_location)) - val.resize(2, 2); // May throw! - } - } - - template - inline void resize_to_bit_size(cpp_int_backend& newval, unsigned bits, const mpl::false_&) - { - unsigned limb_count = static_cast(bits / (sizeof(limb_type) * CHAR_BIT)); - if(bits % (sizeof(limb_type) * CHAR_BIT)) - ++limb_count; - static const unsigned max_limbs = MaxBits ? MaxBits / (CHAR_BIT * sizeof(limb_type)) + ((MaxBits % (CHAR_BIT * sizeof(limb_type))) ? 1 : 0) : (std::numeric_limits::max)(); - if(limb_count > max_limbs) - limb_count = max_limbs; - newval.resize(limb_count, limb_count); - std::memset(newval.limbs(), 0, newval.size() * sizeof(limb_type)); - } - template - inline void resize_to_bit_size(cpp_int_backend& newval, unsigned, const mpl::true_&) - { - *newval.limbs() = 0; - } - - template - number, ExpressionTemplates>& - import_bits_generic( - number, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true) - { - typename number, ExpressionTemplates>::backend_type newval; - - typedef typename std::iterator_traits::value_type value_type; - typedef typename boost::make_unsigned::type unsigned_value_type; - typedef typename std::iterator_traits::difference_type difference_type; - typedef typename boost::make_unsigned::type size_type; - typedef typename cpp_int_backend::trivial_tag tag_type; - - if(!chunk_size) - chunk_size = std::numeric_limits::digits; - - size_type limbs = std::distance(i, j); - size_type bits = limbs * chunk_size; - - detail::resize_to_bit_size(newval, static_cast(bits), tag_type()); - - difference_type bit_location = msv_first ? bits - chunk_size : 0; - difference_type bit_location_change = msv_first ? -static_cast(chunk_size) : chunk_size; - - while(i != j) - { - detail::assign_bits(newval, static_cast(*i), static_cast(bit_location), chunk_size, tag_type()); - ++i; - bit_location += bit_location_change; - } - - newval.normalize(); - - val.backend().swap(newval); - return val; - } - - template - inline typename boost::disable_if_c >::value, number, ExpressionTemplates>&>::type - import_bits_fast( - number, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0) - { - std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i)); - std::size_t limb_len = byte_len / sizeof(limb_type); - if(byte_len % sizeof(limb_type)) - ++limb_len; - cpp_int_backend& result = val.backend(); - result.resize(static_cast(limb_len), static_cast(limb_len)); // checked types may throw here if they're not large enough to hold the data! - result.limbs()[result.size() - 1] = 0u; - std::memcpy(result.limbs(), i, (std::min)(byte_len, result.size() * sizeof(limb_type))); - result.normalize(); // In case data has leading zeros. - return val; - } - template - inline typename boost::enable_if_c >::value, number, ExpressionTemplates>&>::type - import_bits_fast( - number, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0) - { - cpp_int_backend& result = val.backend(); - std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i)); - std::size_t limb_len = byte_len / sizeof(result.limbs()[0]); - if(byte_len % sizeof(result.limbs()[0])) - ++limb_len; - result.limbs()[0] = 0u; - result.resize(static_cast(limb_len), static_cast(limb_len)); // checked types may throw here if they're not large enough to hold the data! - std::memcpy(result.limbs(), i, (std::min)(byte_len, result.size() * sizeof(result.limbs()[0]))); - result.normalize(); // In case data has leading zeros. - return val; - } - } - - - template - inline number, ExpressionTemplates>& - import_bits( - number, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true) - { - return detail::import_bits_generic(val, i, j, chunk_size, msv_first); - } - - template - inline number, ExpressionTemplates>& - import_bits( - number, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0, bool msv_first = true) - { +namespace multiprecision { + +namespace detail { + +template +void assign_bits(Backend &val, Unsigned bits, unsigned bit_location, + unsigned chunk_bits, const mpl::false_ &tag) { + unsigned limb = bit_location / (sizeof(limb_type) * CHAR_BIT); + unsigned shift = bit_location % (sizeof(limb_type) * CHAR_BIT); + + limb_type mask = chunk_bits >= sizeof(limb_type) * CHAR_BIT + ? ~static_cast(0u) + : (static_cast(1u) << chunk_bits) - 1; + + limb_type value = static_cast(bits & mask) << shift; + if (value) { + if (val.size() == limb) { + val.resize(limb + 1, limb + 1); + if (val.size() > limb) + val.limbs()[limb] = value; + } else if (val.size() > limb) + val.limbs()[limb] |= value; + } + if (chunk_bits > sizeof(limb_type) * CHAR_BIT - shift) { + shift = sizeof(limb_type) * CHAR_BIT - shift; + chunk_bits -= shift; + bit_location += shift; + bits >>= shift; + if (bits) + assign_bits(val, bits, bit_location, chunk_bits, tag); + } +} +template +void assign_bits(Backend &val, Unsigned bits, unsigned bit_location, + unsigned chunk_bits, const mpl::true_ &) { + typedef typename Backend::local_limb_type local_limb_type; + // + // Check for possible overflow, this may trigger an exception, or have no + // effect depending on whether this is a checked integer or not: + // + if ((bit_location >= sizeof(local_limb_type) * CHAR_BIT) && bits) + val.resize(2, 2); + else { + local_limb_type mask = + chunk_bits >= sizeof(local_limb_type) * CHAR_BIT + ? ~static_cast(0u) + : (static_cast(1u) << chunk_bits) - 1; + local_limb_type value = (static_cast(bits) & mask) + << bit_location; + *val.limbs() |= value; + // + // Check for overflow bits: + // + bit_location = sizeof(local_limb_type) * CHAR_BIT - bit_location; + if ((bit_location < sizeof(bits) * CHAR_BIT) && (bits >>= bit_location)) + val.resize(2, 2); // May throw! + } +} + +template +inline void resize_to_bit_size( + cpp_int_backend &newval, + unsigned bits, const mpl::false_ &) { + unsigned limb_count = + static_cast(bits / (sizeof(limb_type) * CHAR_BIT)); + if (bits % (sizeof(limb_type) * CHAR_BIT)) + ++limb_count; + static const unsigned max_limbs = + MaxBits ? MaxBits / (CHAR_BIT * sizeof(limb_type)) + + ((MaxBits % (CHAR_BIT * sizeof(limb_type))) ? 1 : 0) + : (std::numeric_limits::max)(); + if (limb_count > max_limbs) + limb_count = max_limbs; + newval.resize(limb_count, limb_count); + std::memset(newval.limbs(), 0, newval.size() * sizeof(limb_type)); +} +template +inline void resize_to_bit_size( + cpp_int_backend &newval, + unsigned, const mpl::true_ &) { + *newval.limbs() = 0; +} + +template +number, + ExpressionTemplates> & +import_bits_generic( + number, + ExpressionTemplates> &val, + Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true) { + typename number< + cpp_int_backend, + ExpressionTemplates>::backend_type newval; + + typedef typename std::iterator_traits::value_type value_type; + typedef typename boost::make_unsigned::type unsigned_value_type; + typedef + typename std::iterator_traits::difference_type difference_type; + typedef typename boost::make_unsigned::type size_type; + typedef typename cpp_int_backend::trivial_tag tag_type; + + if (!chunk_size) + chunk_size = std::numeric_limits::digits; + + size_type limbs = std::distance(i, j); + size_type bits = limbs * chunk_size; + + detail::resize_to_bit_size(newval, static_cast(bits), tag_type()); + + difference_type bit_location = msv_first ? bits - chunk_size : 0; + difference_type bit_location_change = + msv_first ? -static_cast(chunk_size) : chunk_size; + + while (i != j) { + detail::assign_bits(newval, static_cast(*i), + static_cast(bit_location), chunk_size, + tag_type()); + ++i; + bit_location += bit_location_change; + } + + newval.normalize(); + + val.backend().swap(newval); + return val; +} + +template +inline typename boost::disable_if_c< + boost::multiprecision::backends::is_trivial_cpp_int< + cpp_int_backend>::value, + number, + ExpressionTemplates> &>::type +import_bits_fast( + number, + ExpressionTemplates> &val, + T *i, T *j, unsigned chunk_size = 0) { + std::size_t byte_len = + (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i)); + std::size_t limb_len = byte_len / sizeof(limb_type); + if (byte_len % sizeof(limb_type)) + ++limb_len; + cpp_int_backend &result = + val.backend(); + result.resize(static_cast(limb_len), + static_cast( + limb_len)); // checked types may throw here if they're not + // large enough to hold the data! + result.limbs()[result.size() - 1] = 0u; + std::memcpy(result.limbs(), i, + (std::min)(byte_len, result.size() * sizeof(limb_type))); + result.normalize(); // In case data has leading zeros. + return val; +} +template +inline typename boost::enable_if_c< + boost::multiprecision::backends::is_trivial_cpp_int< + cpp_int_backend>::value, + number, + ExpressionTemplates> &>::type +import_bits_fast( + number, + ExpressionTemplates> &val, + T *i, T *j, unsigned chunk_size = 0) { + cpp_int_backend &result = + val.backend(); + std::size_t byte_len = + (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i)); + std::size_t limb_len = byte_len / sizeof(result.limbs()[0]); + if (byte_len % sizeof(result.limbs()[0])) + ++limb_len; + result.limbs()[0] = 0u; + result.resize(static_cast(limb_len), + static_cast( + limb_len)); // checked types may throw here if they're not + // large enough to hold the data! + std::memcpy(result.limbs(), i, + (std::min)(byte_len, result.size() * sizeof(result.limbs()[0]))); + result.normalize(); // In case data has leading zeros. + return val; +} +} // namespace detail + +template +inline number, + ExpressionTemplates> & +import_bits( + number, + ExpressionTemplates> &val, + Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true) { + return detail::import_bits_generic(val, i, j, chunk_size, msv_first); +} + +template +inline number, + ExpressionTemplates> & +import_bits( + number, + ExpressionTemplates> &val, + T *i, T *j, unsigned chunk_size = 0, bool msv_first = true) { #if BOOST_ENDIAN_LITTLE_BYTE - if(((chunk_size % CHAR_BIT) == 0) && !msv_first) - return detail::import_bits_fast(val, i, j, chunk_size); + if (((chunk_size % CHAR_BIT) == 0) && !msv_first) + return detail::import_bits_fast(val, i, j, chunk_size); #endif - return detail::import_bits_generic(val, i, j, chunk_size, msv_first); - } - - namespace detail { - - template - boost::uintmax_t extract_bits(const Backend& val, unsigned location, unsigned count, const mpl::false_& tag) - { - unsigned limb = location / (sizeof(limb_type) * CHAR_BIT); - unsigned shift = location % (sizeof(limb_type) * CHAR_BIT); - boost::uintmax_t result = 0; - boost::uintmax_t mask = count == std::numeric_limits::digits ? ~static_cast(0) : (static_cast(1u) << count) - 1; - if(count > (sizeof(limb_type) * CHAR_BIT - shift)) - { - result = extract_bits(val, location + sizeof(limb_type) * CHAR_BIT - shift, count - sizeof(limb_type) * CHAR_BIT + shift, tag); - result <<= sizeof(limb_type) * CHAR_BIT - shift; - } - if(limb < val.size()) - result |= (val.limbs()[limb] >> shift) & mask; - return result; - } - - template - inline boost::uintmax_t extract_bits(const Backend& val, unsigned location, unsigned count, const mpl::true_&) - { - typename Backend::local_limb_type result = *val.limbs(); - typename Backend::local_limb_type mask = count >= std::numeric_limits::digits ? ~static_cast(0) : (static_cast(1u) << count) - 1; - return (result >> location) & mask; - } - - } - - template - OutputIterator export_bits( - const number, ExpressionTemplates>& val, OutputIterator out, unsigned chunk_size, bool msv_first = true) - { + return detail::import_bits_generic(val, i, j, chunk_size, msv_first); +} + +namespace detail { + +template +boost::uintmax_t extract_bits(const Backend &val, unsigned location, + unsigned count, const mpl::false_ &tag) { + unsigned limb = location / (sizeof(limb_type) * CHAR_BIT); + unsigned shift = location % (sizeof(limb_type) * CHAR_BIT); + boost::uintmax_t result = 0; + boost::uintmax_t mask = + count == std::numeric_limits::digits + ? ~static_cast(0) + : (static_cast(1u) << count) - 1; + if (count > (sizeof(limb_type) * CHAR_BIT - shift)) { + result = extract_bits(val, location + sizeof(limb_type) * CHAR_BIT - shift, + count - sizeof(limb_type) * CHAR_BIT + shift, tag); + result <<= sizeof(limb_type) * CHAR_BIT - shift; + } + if (limb < val.size()) + result |= (val.limbs()[limb] >> shift) & mask; + return result; +} + +template +inline boost::uintmax_t extract_bits(const Backend &val, unsigned location, + unsigned count, const mpl::true_ &) { + typename Backend::local_limb_type result = *val.limbs(); + typename Backend::local_limb_type mask = + count >= std::numeric_limits::digits + ? ~static_cast(0) + : (static_cast(1u) << count) - 1; + return (result >> location) & mask; +} + +} // namespace detail + +template +OutputIterator +export_bits(const number< + cpp_int_backend, + ExpressionTemplates> &val, + OutputIterator out, unsigned chunk_size, bool msv_first = true) { #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4244) +#pragma warning(disable : 4244) #endif - typedef typename cpp_int_backend::trivial_tag tag_type; - if(!val) - { - *out = 0; - ++out; - return out; - } - unsigned bitcount = boost::multiprecision::backends::eval_msb_imp(val.backend()) + 1; - unsigned chunks = bitcount / chunk_size; - if(bitcount % chunk_size) - ++chunks; - - int bit_location = msv_first ? bitcount - chunk_size : 0; - int bit_step = msv_first ? -static_cast(chunk_size) : chunk_size; - while(bit_location % bit_step) ++bit_location; - - do - { - *out = detail::extract_bits(val.backend(), bit_location, chunk_size, tag_type()); - ++out; - bit_location += bit_step; - } while((bit_location >= 0) && (bit_location < (int)bitcount)); - - return out; + typedef typename cpp_int_backend::trivial_tag tag_type; + if (!val) { + *out = 0; + ++out; + return out; + } + unsigned bitcount = + boost::multiprecision::backends::eval_msb_imp(val.backend()) + 1; + unsigned chunks = bitcount / chunk_size; + if (bitcount % chunk_size) + ++chunks; + + int bit_location = msv_first ? bitcount - chunk_size : 0; + int bit_step = msv_first ? -static_cast(chunk_size) : chunk_size; + while (bit_location % bit_step) + ++bit_location; + + do { + *out = detail::extract_bits(val.backend(), bit_location, chunk_size, + tag_type()); + ++out; + bit_location += bit_step; + } while ((bit_location >= 0) && (bit_location < (int)bitcount)); + + return out; #ifdef _MSC_VER #pragma warning(pop) #endif - } - - } } - +} // namespace multiprecision +} // namespace boost #endif // BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP - diff --git a/include/boost/multiprecision/cpp_int/limits.hpp b/include/boost/multiprecision/cpp_int/limits.hpp index 7b1e59e7f..90508c169 100644 --- a/include/boost/multiprecision/cpp_int/limits.hpp +++ b/include/boost/multiprecision/cpp_int/limits.hpp @@ -8,211 +8,462 @@ #ifndef BOOST_MP_CPP_INT_LIM_HPP #define BOOST_MP_CPP_INT_LIM_HPP -namespace std{ +namespace std { -namespace detail{ +namespace detail { #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4307) +#pragma warning(disable : 4307) #endif -template -inline boost::multiprecision::number, ExpressionTemplates> - get_min(const boost::mpl::true_&, const boost::mpl::true_&) -{ - // Bounded and signed. - typedef boost::multiprecision::number, ExpressionTemplates> result_type; - typedef boost::multiprecision::number, ExpressionTemplates> ui_type; - static const result_type val = -result_type(~ui_type(0)); - return val; +template +inline boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> +get_min(const boost::mpl::true_ &, const boost::mpl::true_ &) { + // Bounded and signed. + typedef boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> + result_type; + typedef boost::multiprecision::number< + boost::multiprecision::cpp_int_backend< + MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, + boost::multiprecision::unchecked>, + ExpressionTemplates> + ui_type; + static const result_type val = -result_type(~ui_type(0)); + return val; } -template -inline boost::multiprecision::number, ExpressionTemplates> - get_min(const boost::mpl::true_&, const boost::mpl::false_&) -{ - // Bounded and unsigned: - static const boost::multiprecision::number, ExpressionTemplates> val(0u); - return val; +template +inline boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> +get_min(const boost::mpl::true_ &, const boost::mpl::false_ &) { + // Bounded and unsigned: + static const boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> + val(0u); + return val; } -template -inline boost::multiprecision::number, ExpressionTemplates> - get_min(const boost::mpl::false_&, const boost::mpl::true_&) -{ - // Unbounded and signed. - // There is no minimum value, just return 0: - static const boost::multiprecision::number, ExpressionTemplates> val(0u); - return val; +template +inline boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> +get_min(const boost::mpl::false_ &, const boost::mpl::true_ &) { + // Unbounded and signed. + // There is no minimum value, just return 0: + static const boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> + val(0u); + return val; } -template -inline boost::multiprecision::number, ExpressionTemplates> - get_min(const boost::mpl::false_&, const boost::mpl::false_&) -{ - // Unbound and unsigned: - static const boost::multiprecision::number, ExpressionTemplates> val(0u); - return val; +template +inline boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> +get_min(const boost::mpl::false_ &, const boost::mpl::false_ &) { + // Unbound and unsigned: + static const boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> + val(0u); + return val; } -template -inline boost::multiprecision::number, ExpressionTemplates> - get_max(const boost::mpl::true_&, const boost::mpl::true_&) -{ - // Bounded and signed. - typedef boost::multiprecision::number, ExpressionTemplates> result_type; - typedef boost::multiprecision::number, ExpressionTemplates> ui_type; - static const result_type val = ~ui_type(0); - return val; +template +inline boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> +get_max(const boost::mpl::true_ &, const boost::mpl::true_ &) { + // Bounded and signed. + typedef boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> + result_type; + typedef boost::multiprecision::number< + boost::multiprecision::cpp_int_backend< + MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, + boost::multiprecision::unchecked>, + ExpressionTemplates> + ui_type; + static const result_type val = ~ui_type(0); + return val; } -template -inline boost::multiprecision::number, ExpressionTemplates> - get_max(const boost::mpl::true_&, const boost::mpl::false_&) -{ - // Bound and unsigned: - typedef boost::multiprecision::number, ExpressionTemplates> result_type; - typedef boost::multiprecision::number, ExpressionTemplates> ui_type; - static const result_type val = ~ui_type(0); - return val; +template +inline boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> +get_max(const boost::mpl::true_ &, const boost::mpl::false_ &) { + // Bound and unsigned: + typedef boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> + result_type; + typedef boost::multiprecision::number< + boost::multiprecision::cpp_int_backend< + MinBits, MaxBits, boost::multiprecision::unsigned_magnitude, + boost::multiprecision::unchecked, Allocator>, + ExpressionTemplates> + ui_type; + static const result_type val = ~ui_type(0); + return val; } -template -inline boost::multiprecision::number, ExpressionTemplates> - get_max(const boost::mpl::false_&, const boost::mpl::true_&) -{ - // Unbounded and signed. - // There is no maximum value, just return 0: - static const boost::multiprecision::number, ExpressionTemplates> val(0u); - return val; +template +inline boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> +get_max(const boost::mpl::false_ &, const boost::mpl::true_ &) { + // Unbounded and signed. + // There is no maximum value, just return 0: + static const boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> + val(0u); + return val; } -template -inline boost::multiprecision::number, ExpressionTemplates> - get_max(const boost::mpl::false_&, const boost::mpl::false_&) -{ - // Unbound and unsigned: - static const boost::multiprecision::number, ExpressionTemplates> val(0u); - return val; +template +inline boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> +get_max(const boost::mpl::false_ &, const boost::mpl::false_ &) { + // Unbound and unsigned: + static const boost::multiprecision::number< + boost::multiprecision::cpp_int_backend, + ExpressionTemplates> + val(0u); + return val; } -} +} // namespace detail -template -class numeric_limits, ExpressionTemplates> > -{ - typedef boost::multiprecision::cpp_int_backend backend_type; - typedef boost::multiprecision::number number_type; +template +class numeric_limits, + ExpressionTemplates>> { + typedef boost::multiprecision::cpp_int_backend + backend_type; + typedef boost::multiprecision::number + number_type; - struct inititializer - { - inititializer() - { - (std::numeric_limits::max)(); - (std::numeric_limits::min)(); - } - void do_nothing()const{} - }; + struct inititializer { + inititializer() { + (std::numeric_limits::max)(); + (std::numeric_limits::min)(); + } + void do_nothing() const {} + }; - static const inititializer init; + static const inititializer init; public: - BOOST_STATIC_CONSTEXPR bool is_specialized = true; - // - // Largest and smallest numbers are bounded only by available memory, set - // to zero: - // - static number_type (min)() - { - init.do_nothing(); - return detail::get_min(boost::multiprecision::backends::is_fixed_precision(), boost::multiprecision::is_signed_number()); - } - static number_type (max)() - { - init.do_nothing(); - return detail::get_max(boost::multiprecision::backends::is_fixed_precision(), boost::multiprecision::is_signed_number()); - } - static number_type lowest() { return (min)(); } - BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::backends::max_precision::value == UINT_MAX ? INT_MAX : boost::multiprecision::backends::max_precision::value; - BOOST_STATIC_CONSTEXPR int digits10 = (digits > INT_MAX / 301) ? (digits / 1000) * 301L : (digits * 301) / 1000; - BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 3; - BOOST_STATIC_CONSTEXPR bool is_signed = boost::multiprecision::is_signed_number::value; - BOOST_STATIC_CONSTEXPR bool is_integer = true; - BOOST_STATIC_CONSTEXPR bool is_exact = true; - BOOST_STATIC_CONSTEXPR int radix = 2; - static number_type epsilon() { return 0; } - static number_type round_error() { return 0; } - BOOST_STATIC_CONSTEXPR int min_exponent = 0; - BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; - BOOST_STATIC_CONSTEXPR int max_exponent = 0; - BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; - BOOST_STATIC_CONSTEXPR bool has_infinity = false; - BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; - BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; - BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; - BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; - static number_type infinity() { return 0; } - static number_type quiet_NaN() { return 0; } - static number_type signaling_NaN() { return 0; } - static number_type denorm_min() { return 0; } - BOOST_STATIC_CONSTEXPR bool is_iec559 = false; - BOOST_STATIC_CONSTEXPR bool is_bounded = boost::multiprecision::backends::is_fixed_precision::value; - BOOST_STATIC_CONSTEXPR bool is_modulo = (boost::multiprecision::backends::is_fixed_precision::value && (Checked == boost::multiprecision::unchecked)); - BOOST_STATIC_CONSTEXPR bool traps = false; - BOOST_STATIC_CONSTEXPR bool tinyness_before = false; - BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + // + // Largest and smallest numbers are bounded only by available memory, set + // to zero: + // + static number_type(min)() { + init.do_nothing(); + return detail::get_min( + boost::multiprecision::backends::is_fixed_precision(), + boost::multiprecision::is_signed_number()); + } + static number_type(max)() { + init.do_nothing(); + return detail::get_max( + boost::multiprecision::backends::is_fixed_precision(), + boost::multiprecision::is_signed_number()); + } + static number_type lowest() { return (min)(); } + BOOST_STATIC_CONSTEXPR int digits = + boost::multiprecision::backends::max_precision::value == + UINT_MAX + ? INT_MAX + : boost::multiprecision::backends::max_precision::value; + BOOST_STATIC_CONSTEXPR int digits10 = + (digits > INT_MAX / 301) ? (digits / 1000) * 301L : (digits * 301) / 1000; + BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 3; + BOOST_STATIC_CONSTEXPR bool is_signed = + boost::multiprecision::is_signed_number::value; + BOOST_STATIC_CONSTEXPR bool is_integer = true; + BOOST_STATIC_CONSTEXPR bool is_exact = true; + BOOST_STATIC_CONSTEXPR int radix = 2; + static number_type epsilon() { return 0; } + static number_type round_error() { return 0; } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() { return 0; } + static number_type quiet_NaN() { return 0; } + static number_type signaling_NaN() { return 0; } + static number_type denorm_min() { return 0; } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = + boost::multiprecision::backends::is_fixed_precision::value; + BOOST_STATIC_CONSTEXPR bool is_modulo = + (boost::multiprecision::backends::is_fixed_precision< + backend_type>::value && + (Checked == boost::multiprecision::unchecked)); + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; }; -template -const typename numeric_limits, ExpressionTemplates> >::inititializer numeric_limits, ExpressionTemplates> >::init; +template +const typename numeric_limits, + ExpressionTemplates>>::inititializer + numeric_limits, + ExpressionTemplates>>::init; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent10; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent10; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; -template -BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; -template -BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::radix; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, + ExpressionTemplates>>::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style + numeric_limits, + ExpressionTemplates>>::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, + ExpressionTemplates>>::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style + numeric_limits, + ExpressionTemplates>>::round_style; #endif #ifdef _MSC_VER diff --git a/include/boost/multiprecision/cpp_int/misc.hpp b/include/boost/multiprecision/cpp_int/misc.hpp index 9398db5cd..714187b44 100644 --- a/include/boost/multiprecision/cpp_int/misc.hpp +++ b/include/boost/multiprecision/cpp_int/misc.hpp @@ -8,706 +8,869 @@ #ifndef BOOST_MP_CPP_INT_MISC_HPP #define BOOST_MP_CPP_INT_MISC_HPP -#include // lsb etc -#include // gcd/lcm #include +#include // gcd/lcm +#include // lsb etc #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:4702) -#pragma warning(disable:4127) // conditional expression is constant -#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned +#pragma warning(disable : 4702) +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4146) // unary minus operator applied to unsigned + // type, result still unsigned #endif - -namespace boost{ namespace multiprecision{ namespace backends{ +namespace boost { +namespace multiprecision { +namespace backends { template -void check_in_range(const CppInt& val, const mpl::int_&) -{ - typedef typename boost::multiprecision::detail::canonical::type cast_type; - if(val.sign()) - { - if(boost::is_signed::value == false) - BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type.")); - if(val.compare(static_cast((std::numeric_limits::min)())) < 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range.")); - } - else - { - if(val.compare(static_cast((std::numeric_limits::max)())) > 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range.")); - } +void check_in_range(const CppInt &val, const mpl::int_ &) { + typedef typename boost::multiprecision::detail::canonical::type + cast_type; + if (val.sign()) { + if (boost::is_signed::value == false) + BOOST_THROW_EXCEPTION(std::range_error( + "Attempt to assign a negative value to an unsigned type.")); + if (val.compare(static_cast((std::numeric_limits::min)())) < + 0) + BOOST_THROW_EXCEPTION(std::overflow_error( + "Could not convert to the target type - -value is out of range.")); + } else { + if (val.compare(static_cast((std::numeric_limits::max)())) > + 0) + BOOST_THROW_EXCEPTION(std::overflow_error( + "Could not convert to the target type - -value is out of range.")); + } } template -inline void check_in_range(const CppInt& /*val*/, const mpl::int_&) BOOST_NOEXCEPT {} +inline void check_in_range(const CppInt & /*val*/, + const mpl::int_ &) BOOST_NOEXCEPT {} -inline void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {} -inline void check_is_negative(const mpl::false_&) -{ - BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type.")); +inline void check_is_negative(const mpl::true_ &) BOOST_NOEXCEPT {} +inline void check_is_negative(const mpl::false_ &) { + BOOST_THROW_EXCEPTION(std::range_error( + "Attempt to assign a negative value to an unsigned type.")); } template -inline Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT -{ - return -i; +inline Integer negate_integer(Integer i, const mpl::true_ &) BOOST_NOEXCEPT { + return -i; } template -inline Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT -{ - return ~(i-1); -} - -template -inline typename enable_if_c::value && !is_trivial_cpp_int >::value, void>::type - eval_convert_to(R* result, const cpp_int_backend& backend) -{ - typedef mpl::int_ checked_type; - check_in_range(backend, checked_type()); - - if (std::numeric_limits::digits < cpp_int_backend::limb_bits) - { - if ((backend.sign() && boost::is_signed::value) && (1 + static_cast((std::numeric_limits::max)()) <= backend.limbs()[0])) - { - *result = (std::numeric_limits::min)(); - return; - } - else if (boost::is_signed::value && !backend.sign() && static_cast((std::numeric_limits::max)()) <= backend.limbs()[0]) - { - *result = (std::numeric_limits::max)(); - return; - } - else - *result = static_cast(backend.limbs()[0]); - } - else +inline Integer negate_integer(Integer i, const mpl::false_ &) BOOST_NOEXCEPT { + return ~(i - 1); +} + +template +inline typename enable_if_c< + is_integral::value && + !is_trivial_cpp_int>::value, + void>::type +eval_convert_to(R *result, + const cpp_int_backend &backend) { + typedef mpl::int_ checked_type; + check_in_range(backend, checked_type()); + + if (std::numeric_limits::digits < + cpp_int_backend::limb_bits) { + if ((backend.sign() && boost::is_signed::value) && + (1 + static_cast( + (std::numeric_limits::max)()) <= + backend.limbs()[0])) { + *result = (std::numeric_limits::min)(); + return; + } else if (boost::is_signed::value && !backend.sign() && + static_cast( + (std::numeric_limits::max)()) <= backend.limbs()[0]) { + *result = (std::numeric_limits::max)(); + return; + } else *result = static_cast(backend.limbs()[0]); - unsigned shift = cpp_int_backend::limb_bits; - unsigned i = 1; - if (std::numeric_limits::digits > cpp_int_backend::limb_bits) - { - while ((i < backend.size()) && (shift < static_cast(std::numeric_limits::digits - cpp_int_backend::limb_bits))) - { - *result += static_cast(backend.limbs()[i]) << shift; - shift += cpp_int_backend::limb_bits; - ++i; - } - // - // We have one more limb to extract, but may not need all the bits, so treat this as a special case: - // - if (i < backend.size()) - { - static const limb_type mask = std::numeric_limits::digits - shift == cpp_int_backend::limb_bits ? - ~static_cast(0) : (static_cast(1u) << (std::numeric_limits::digits - shift)) - 1; - *result += (static_cast(backend.limbs()[i]) & mask) << shift; - if ((static_cast(backend.limbs()[i]) & static_cast(~mask)) || (i + 1 < backend.size())) - { - // Overflow: - if (backend.sign()) - { - check_is_negative(boost::is_signed()); - *result = (std::numeric_limits::min)(); - } - else if(boost::is_signed::value) - *result = (std::numeric_limits::max)(); - return; - } - } - } - else if (backend.size() > 1) - { - // Overflow: - if (backend.sign()) - { - check_is_negative(boost::is_signed()); - *result = (std::numeric_limits::min)(); + } else + *result = static_cast(backend.limbs()[0]); + unsigned shift = cpp_int_backend::limb_bits; + unsigned i = 1; + if (std::numeric_limits::digits > + cpp_int_backend::limb_bits) { + while ((i < backend.size()) && + (shift < static_cast( + std::numeric_limits::digits - + cpp_int_backend::limb_bits))) { + *result += static_cast(backend.limbs()[i]) << shift; + shift += cpp_int_backend::limb_bits; + ++i; + } + // + // We have one more limb to extract, but may not need all the bits, so treat + // this as a special case: + // + if (i < backend.size()) { + static const limb_type mask = + std::numeric_limits::digits - shift == + cpp_int_backend::limb_bits + ? ~static_cast(0) + : (static_cast(1u) + << (std::numeric_limits::digits - shift)) - + 1; + *result += (static_cast(backend.limbs()[i]) & mask) << shift; + if ((static_cast(backend.limbs()[i]) & + static_cast(~mask)) || + (i + 1 < backend.size())) { + // Overflow: + if (backend.sign()) { + check_is_negative(boost::is_signed()); + *result = (std::numeric_limits::min)(); + } else if (boost::is_signed::value) + *result = (std::numeric_limits::max)(); + return; } - else if(boost::is_signed::value) - *result = (std::numeric_limits::max)(); - return; - } - if(backend.sign()) - { + } + } else if (backend.size() > 1) { + // Overflow: + if (backend.sign()) { check_is_negative(boost::is_signed()); - *result = negate_integer(*result, boost::is_signed()); - } -} - -template -inline typename enable_if_c::value && !is_trivial_cpp_int >::value, void>::type - eval_convert_to(R* result, const cpp_int_backend& backend) BOOST_MP_NOEXCEPT_IF(is_arithmetic::value) -{ - typename cpp_int_backend::const_limb_pointer p = backend.limbs(); - unsigned shift = cpp_int_backend::limb_bits; - *result = static_cast(*p); - for(unsigned i = 1; i < backend.size(); ++i) - { - *result += static_cast(std::ldexp(static_cast(p[i]), shift)); - shift += cpp_int_backend::limb_bits; - } - if(backend.sign()) - *result = -*result; -} - -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value, bool>::type - eval_is_zero(const cpp_int_backend& val) BOOST_NOEXCEPT -{ - return (val.size() == 1) && (val.limbs()[0] == 0); -} -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value, int>::type - eval_get_sign(const cpp_int_backend& val) BOOST_NOEXCEPT -{ - return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1; -} -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_abs(cpp_int_backend& result, const cpp_int_backend& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - result = val; - result.sign(false); + *result = (std::numeric_limits::min)(); + } else if (boost::is_signed::value) + *result = (std::numeric_limits::max)(); + return; + } + if (backend.sign()) { + check_is_negative(boost::is_signed()); + *result = negate_integer(*result, boost::is_signed()); + } +} + +template +inline typename enable_if_c< + is_floating_point::value && + !is_trivial_cpp_int>::value, + void>::type +eval_convert_to(R *result, const cpp_int_backend &backend) + BOOST_MP_NOEXCEPT_IF(is_arithmetic::value) { + typename cpp_int_backend::const_limb_pointer p = backend.limbs(); + unsigned shift = cpp_int_backend::limb_bits; + *result = static_cast(*p); + for (unsigned i = 1; i < backend.size(); ++i) { + *result += + static_cast(std::ldexp(static_cast(p[i]), shift)); + shift += cpp_int_backend::limb_bits; + } + if (backend.sign()) + *result = -*result; +} + +template +BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int>::value, + bool>::type +eval_is_zero(const cpp_int_backend &val) BOOST_NOEXCEPT { + return (val.size() == 1) && (val.limbs()[0] == 0); +} +template +BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int>::value, + int>::type +eval_get_sign(const cpp_int_backend &val) BOOST_NOEXCEPT { + return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1; +} +template +BOOST_MP_FORCEINLINE typename enable_if_c>::value>::type +eval_abs(cpp_int_backend + &result, + const cpp_int_backend &val) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + result = val; + result.sign(false); } // // Get the location of the least-significant-bit: // -template -inline typename enable_if_c >::value, unsigned>::type - eval_lsb(const cpp_int_backend& a) -{ - using default_ops::eval_get_sign; - if(eval_get_sign(a) == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - if(a.sign()) - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - - // - // Find the index of the least significant limb that is non-zero: - // - unsigned index = 0; - while(!a.limbs()[index] && (index < a.size())) - ++index; - // - // Find the index of the least significant bit within that limb: - // - unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]); - - return result + index * cpp_int_backend::limb_bits; +template +inline typename enable_if_c< + !is_trivial_cpp_int>::value, + unsigned>::type +eval_lsb(const cpp_int_backend &a) { + using default_ops::eval_get_sign; + if (eval_get_sign(a) == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (a.sign()) { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + + // + // Find the index of the least significant limb that is non-zero: + // + unsigned index = 0; + while (!a.limbs()[index] && (index < a.size())) + ++index; + // + // Find the index of the least significant bit within that limb: + // + unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]); + + return result + index * cpp_int_backend::limb_bits; } // // Get the location of the most-significant-bit: // -template -inline typename enable_if_c >::value, unsigned>::type -eval_msb_imp(const cpp_int_backend& a) -{ - // - // Find the index of the most significant bit that is non-zero: - // - return (a.size() - 1) * cpp_int_backend::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]); -} - -template -inline typename enable_if_c >::value, unsigned>::type - eval_msb(const cpp_int_backend& a) -{ - using default_ops::eval_get_sign; - if(eval_get_sign(a) == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - if(a.sign()) - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - return eval_msb_imp(a); -} - -template -inline typename enable_if_c >::value, bool>::type - eval_bit_test(const cpp_int_backend& val, unsigned index) BOOST_NOEXCEPT -{ - unsigned offset = index / cpp_int_backend::limb_bits; - unsigned shift = index % cpp_int_backend::limb_bits; - limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); - if(offset >= val.size()) - return false; - return val.limbs()[offset] & mask ? true : false; -} - -template -inline typename enable_if_c >::value>::type - eval_bit_set(cpp_int_backend& val, unsigned index) -{ - unsigned offset = index / cpp_int_backend::limb_bits; - unsigned shift = index % cpp_int_backend::limb_bits; - limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); - if(offset >= val.size()) - { - unsigned os = val.size(); - val.resize(offset + 1, offset + 1); - if(offset >= val.size()) - return; // fixed precision overflow - for(unsigned i = os; i <= offset; ++i) - val.limbs()[i] = 0; - } - val.limbs()[offset] |= mask; -} - -template -inline typename enable_if_c >::value>::type - eval_bit_unset(cpp_int_backend& val, unsigned index) BOOST_NOEXCEPT -{ - unsigned offset = index / cpp_int_backend::limb_bits; - unsigned shift = index % cpp_int_backend::limb_bits; - limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); - if(offset >= val.size()) - return; - val.limbs()[offset] &= ~mask; - val.normalize(); -} - -template -inline typename enable_if_c >::value>::type - eval_bit_flip(cpp_int_backend& val, unsigned index) -{ - unsigned offset = index / cpp_int_backend::limb_bits; - unsigned shift = index % cpp_int_backend::limb_bits; - limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); - if(offset >= val.size()) - { - unsigned os = val.size(); - val.resize(offset + 1, offset + 1); - if(offset >= val.size()) - return; // fixed precision overflow - for(unsigned i = os; i <= offset; ++i) - val.limbs()[i] = 0; - } - val.limbs()[offset] ^= mask; - val.normalize(); -} - -template -inline typename enable_if_c >::value>::type - eval_qr( - const cpp_int_backend& x, - const cpp_int_backend& y, - cpp_int_backend& q, - cpp_int_backend& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - divide_unsigned_helper(&q, x, y, r); - q.sign(x.sign() != y.sign()); - r.sign(x.sign()); -} - -template -inline typename enable_if_c >::value>::type - eval_qr( - const cpp_int_backend& x, - limb_type y, - cpp_int_backend& q, - cpp_int_backend& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - divide_unsigned_helper(&q, x, y, r); - q.sign(x.sign()); - r.sign(x.sign()); -} - -template -inline typename enable_if_c::value>::type eval_qr( - const cpp_int_backend& x, - U y, - cpp_int_backend& q, - cpp_int_backend& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - using default_ops::eval_qr; - cpp_int_backend t; - t = y; - eval_qr(x, t, q, r); -} - -template -inline typename enable_if_c::value && !is_trivial_cpp_int >::value, Integer>::type - eval_integer_modulus(const cpp_int_backend& x, Integer val) -{ - if((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits::max)())) - { - cpp_int_backend d; - divide_unsigned_helper(static_cast*>(0), x, static_cast(val), d); - return d.limbs()[0]; - } - else - { - return default_ops::eval_integer_modulus(x, val); - } -} - -template -BOOST_MP_FORCEINLINE typename enable_if_c::value && !is_trivial_cpp_int >::value, Integer>::type - eval_integer_modulus(const cpp_int_backend& x, Integer val) -{ - return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val)); -} - -inline limb_type integer_gcd_reduce(limb_type u, limb_type v) -{ - do - { - if(u > v) - std::swap(u, v); - if(u == v) - break; - v -= u; - v >>= boost::multiprecision::detail::find_lsb(v); - } while(true); - return u; -} - -inline double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type v) -{ - do - { - if(u > v) - std::swap(u, v); - if(u == v) - break; - if(v <= ~static_cast(0)) - { - u = integer_gcd_reduce(static_cast(v), static_cast(u)); - break; - } - v -= u; +template +inline typename enable_if_c< + !is_trivial_cpp_int>::value, + unsigned>::type +eval_msb_imp(const cpp_int_backend &a) { + // + // Find the index of the most significant bit that is non-zero: + // + return (a.size() - 1) * cpp_int_backend::limb_bits + + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]); +} + +template +inline typename enable_if_c< + !is_trivial_cpp_int>::value, + unsigned>::type +eval_msb(const cpp_int_backend &a) { + using default_ops::eval_get_sign; + if (eval_get_sign(a) == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (a.sign()) { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + return eval_msb_imp(a); +} + +template +inline typename enable_if_c< + !is_trivial_cpp_int>::value, + bool>::type +eval_bit_test(const cpp_int_backend &val, + unsigned index) BOOST_NOEXCEPT { + unsigned offset = index / cpp_int_backend::limb_bits; + unsigned shift = index % cpp_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if (offset >= val.size()) + return false; + return val.limbs()[offset] & mask ? true : false; +} + +template +inline typename enable_if_c>::value>::type +eval_bit_set( + cpp_int_backend &val, + unsigned index) { + unsigned offset = index / cpp_int_backend::limb_bits; + unsigned shift = index % cpp_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if (offset >= val.size()) { + unsigned os = val.size(); + val.resize(offset + 1, offset + 1); + if (offset >= val.size()) + return; // fixed precision overflow + for (unsigned i = os; i <= offset; ++i) + val.limbs()[i] = 0; + } + val.limbs()[offset] |= mask; +} + +template +inline typename enable_if_c>::value>::type +eval_bit_unset( + cpp_int_backend &val, + unsigned index) BOOST_NOEXCEPT { + unsigned offset = index / cpp_int_backend::limb_bits; + unsigned shift = index % cpp_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if (offset >= val.size()) + return; + val.limbs()[offset] &= ~mask; + val.normalize(); +} + +template +inline typename enable_if_c>::value>::type +eval_bit_flip( + cpp_int_backend &val, + unsigned index) { + unsigned offset = index / cpp_int_backend::limb_bits; + unsigned shift = index % cpp_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if (offset >= val.size()) { + unsigned os = val.size(); + val.resize(offset + 1, offset + 1); + if (offset >= val.size()) + return; // fixed precision overflow + for (unsigned i = os; i <= offset; ++i) + val.limbs()[i] = 0; + } + val.limbs()[offset] ^= mask; + val.normalize(); +} + +template +inline typename enable_if_c>::value>::type +eval_qr(const cpp_int_backend &x, + const cpp_int_backend &y, + cpp_int_backend &q, + cpp_int_backend &r) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + divide_unsigned_helper(&q, x, y, r); + q.sign(x.sign() != y.sign()); + r.sign(x.sign()); +} + +template +inline typename enable_if_c>::value>::type +eval_qr(const cpp_int_backend &x, + limb_type y, + cpp_int_backend &q, + cpp_int_backend &r) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + divide_unsigned_helper(&q, x, y, r); + q.sign(x.sign()); + r.sign(x.sign()); +} + +template +inline typename enable_if_c::value>::type +eval_qr(const cpp_int_backend &x, + U y, + cpp_int_backend &q, + cpp_int_backend &r) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + using default_ops::eval_qr; + cpp_int_backend t; + t = y; + eval_qr(x, t, q, r); +} + +template +inline typename enable_if_c< + is_unsigned::value && + !is_trivial_cpp_int>::value, + Integer>::type +eval_integer_modulus(const cpp_int_backend &x, + Integer val) { + if ((sizeof(Integer) <= sizeof(limb_type)) || + (val <= (std::numeric_limits::max)())) { + cpp_int_backend d; + divide_unsigned_helper( + static_cast *>(0), + x, static_cast(val), d); + return d.limbs()[0]; + } else { + return default_ops::eval_integer_modulus(x, val); + } +} + +template +BOOST_MP_FORCEINLINE typename enable_if_c< + is_signed::value && + !is_trivial_cpp_int>::value, + Integer>::type +eval_integer_modulus(const cpp_int_backend &x, + Integer val) { + return eval_integer_modulus(x, + boost::multiprecision::detail::unsigned_abs(val)); +} + +inline limb_type integer_gcd_reduce(limb_type u, limb_type v) { + do { + if (u > v) + std::swap(u, v); + if (u == v) + break; + v -= u; + v >>= boost::multiprecision::detail::find_lsb(v); + } while (true); + return u; +} + +inline double_limb_type integer_gcd_reduce(double_limb_type u, + double_limb_type v) { + do { + if (u > v) + std::swap(u, v); + if (u == v) + break; + if (v <= ~static_cast(0)) { + u = integer_gcd_reduce(static_cast(v), + static_cast(u)); + break; + } + v -= u; #ifdef __MSVC_RUNTIME_CHECKS - while((v & 1u) == 0) + while ((v & 1u) == 0) #else - while((static_cast(v) & 1u) == 0) + while ((static_cast(v) & 1u) == 0) #endif - v >>= 1; - } while(true); - return u; -} - -template -inline typename enable_if_c >::value>::type - eval_gcd( - cpp_int_backend& result, - const cpp_int_backend& a, - limb_type v) -{ - using default_ops::eval_lsb; - using default_ops::eval_is_zero; - using default_ops::eval_get_sign; - - int shift; - - cpp_int_backend u(a); - - int s = eval_get_sign(u); - - /* GCD(0,x) := x */ - if(s < 0) - { - u.negate(); - } - else if(s == 0) - { - result = v; - return; - } - if(v == 0) - { - result = u; - return; - } - - /* Let shift := lg K, where K is the greatest power of 2 - dividing both u and v. */ - - unsigned us = eval_lsb(u); - unsigned vs = boost::multiprecision::detail::find_lsb(v); - shift = (std::min)(us, vs); - eval_right_shift(u, us); - if(vs) - v >>= vs; - - do - { - /* Now u and v are both odd, so diff(u, v) is even. - Let u = min(u, v), v = diff(u, v)/2. */ - if(u.size() <= 2) - { - if(u.size() == 1) - v = integer_gcd_reduce(*u.limbs(), v); - else - { - double_limb_type i; - i = u.limbs()[0] | (static_cast(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); - v = static_cast(integer_gcd_reduce(i, static_cast(v))); - } - break; + v >>= 1; + } while (true); + return u; +} + +template +inline typename enable_if_c>::value>::type +eval_gcd(cpp_int_backend + &result, + const cpp_int_backend &a, + limb_type v) { + using default_ops::eval_get_sign; + using default_ops::eval_is_zero; + using default_ops::eval_lsb; + + int shift; + + cpp_int_backend u(a); + + int s = eval_get_sign(u); + + /* GCD(0,x) := x */ + if (s < 0) { + u.negate(); + } else if (s == 0) { + result = v; + return; + } + if (v == 0) { + result = u; + return; + } + + /* Let shift := lg K, where K is the greatest power of 2 + dividing both u and v. */ + + unsigned us = eval_lsb(u); + unsigned vs = boost::multiprecision::detail::find_lsb(v); + shift = (std::min)(us, vs); + eval_right_shift(u, us); + if (vs) + v >>= vs; + + do { + /* Now u and v are both odd, so diff(u, v) is even. + Let u = min(u, v), v = diff(u, v)/2. */ + if (u.size() <= 2) { + if (u.size() == 1) + v = integer_gcd_reduce(*u.limbs(), v); + else { + double_limb_type i; + i = u.limbs()[0] | (static_cast(u.limbs()[1]) + << sizeof(limb_type) * CHAR_BIT); + v = static_cast( + integer_gcd_reduce(i, static_cast(v))); } - eval_subtract(u, v); - us = eval_lsb(u); - eval_right_shift(u, us); - } - while(true); - - result = v; - eval_left_shift(result, shift); -} -template -inline typename enable_if_c::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int >::value>::type - eval_gcd( - cpp_int_backend& result, - const cpp_int_backend& a, - const Integer& v) -{ - eval_gcd(result, a, static_cast(v)); -} -template -inline typename enable_if_c::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int >::value>::type - eval_gcd( - cpp_int_backend& result, - const cpp_int_backend& a, - const Integer& v) -{ - eval_gcd(result, a, static_cast(v < 0 ? -v : v)); -} - -template -inline typename enable_if_c >::value>::type - eval_gcd( - cpp_int_backend& result, - const cpp_int_backend& a, - const cpp_int_backend& b) -{ - using default_ops::eval_lsb; - using default_ops::eval_is_zero; - using default_ops::eval_get_sign; - - if(a.size() == 1) - { - eval_gcd(result, b, *a.limbs()); - return; - } - if(b.size() == 1) - { - eval_gcd(result, a, *b.limbs()); - return; - } - - int shift; - - cpp_int_backend u(a), v(b); - - int s = eval_get_sign(u); - - /* GCD(0,x) := x */ - if(s < 0) - { - u.negate(); - } - else if(s == 0) - { - result = v; - return; - } - s = eval_get_sign(v); - if(s < 0) - { - v.negate(); - } - else if(s == 0) - { - result = u; - return; - } - - /* Let shift := lg K, where K is the greatest power of 2 - dividing both u and v. */ - - unsigned us = eval_lsb(u); - unsigned vs = eval_lsb(v); - shift = (std::min)(us, vs); - eval_right_shift(u, us); - eval_right_shift(v, vs); - - do - { - /* Now u and v are both odd, so diff(u, v) is even. - Let u = min(u, v), v = diff(u, v)/2. */ - s = u.compare(v); - if(s > 0) - u.swap(v); - if(s == 0) - break; - if(v.size() <= 2) - { - if(v.size() == 1) - u = integer_gcd_reduce(*v.limbs(), *u.limbs()); - else - { - double_limb_type i, j; - i = v.limbs()[0] | (static_cast(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); - j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | (static_cast(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); - u = integer_gcd_reduce(i, j); - } - break; + break; + } + eval_subtract(u, v); + us = eval_lsb(u); + eval_right_shift(u, us); + } while (true); + + result = v; + eval_left_shift(result, shift); +} +template +inline typename enable_if_c< + is_unsigned::value && (sizeof(Integer) <= sizeof(limb_type)) && + !is_trivial_cpp_int>::value>::type +eval_gcd(cpp_int_backend + &result, + const cpp_int_backend &a, + const Integer &v) { + eval_gcd(result, a, static_cast(v)); +} +template +inline typename enable_if_c< + is_signed::value && (sizeof(Integer) <= sizeof(limb_type)) && + !is_trivial_cpp_int>::value>::type +eval_gcd(cpp_int_backend + &result, + const cpp_int_backend &a, + const Integer &v) { + eval_gcd(result, a, static_cast(v < 0 ? -v : v)); +} + +template +inline typename enable_if_c>::value>::type +eval_gcd(cpp_int_backend + &result, + const cpp_int_backend &a, + const cpp_int_backend &b) { + using default_ops::eval_get_sign; + using default_ops::eval_is_zero; + using default_ops::eval_lsb; + + if (a.size() == 1) { + eval_gcd(result, b, *a.limbs()); + return; + } + if (b.size() == 1) { + eval_gcd(result, a, *b.limbs()); + return; + } + + int shift; + + cpp_int_backend u(a), + v(b); + + int s = eval_get_sign(u); + + /* GCD(0,x) := x */ + if (s < 0) { + u.negate(); + } else if (s == 0) { + result = v; + return; + } + s = eval_get_sign(v); + if (s < 0) { + v.negate(); + } else if (s == 0) { + result = u; + return; + } + + /* Let shift := lg K, where K is the greatest power of 2 + dividing both u and v. */ + + unsigned us = eval_lsb(u); + unsigned vs = eval_lsb(v); + shift = (std::min)(us, vs); + eval_right_shift(u, us); + eval_right_shift(v, vs); + + do { + /* Now u and v are both odd, so diff(u, v) is even. + Let u = min(u, v), v = diff(u, v)/2. */ + s = u.compare(v); + if (s > 0) + u.swap(v); + if (s == 0) + break; + if (v.size() <= 2) { + if (v.size() == 1) + u = integer_gcd_reduce(*v.limbs(), *u.limbs()); + else { + double_limb_type i, j; + i = v.limbs()[0] | (static_cast(v.limbs()[1]) + << sizeof(limb_type) * CHAR_BIT); + j = (u.size() == 1) + ? *u.limbs() + : u.limbs()[0] | (static_cast(u.limbs()[1]) + << sizeof(limb_type) * CHAR_BIT); + u = integer_gcd_reduce(i, j); } - eval_subtract(v, u); - vs = eval_lsb(v); - eval_right_shift(v, vs); - } - while(true); + break; + } + eval_subtract(v, u); + vs = eval_lsb(v); + eval_right_shift(v, vs); + } while (true); - result = u; - eval_left_shift(result, shift); + result = u; + eval_left_shift(result, shift); } // // Now again for trivial backends: // -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_gcd(cpp_int_backend& result, const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT -{ - *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs()); -} -// This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version: -template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && (Checked1 == unchecked)>::type - eval_lcm(cpp_int_backend& result, const cpp_int_backend& a, const cpp_int_backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) -{ - *result.limbs() = boost::integer::lcm(*a.limbs(), *b.limbs()); - result.normalize(); // result may overflow the specified number of bits -} - -inline void conversion_overflow(const mpl::int_&) -{ - BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type")); -} -inline void conversion_overflow(const mpl::int_&){} - -template +template +BOOST_MP_FORCEINLINE typename enable_if_c>::value>::type +eval_gcd(cpp_int_backend + &result, + const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_NOEXCEPT { + *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs()); +} +// This one is only enabled for unchecked cpp_int's, for checked int's we need +// the checking in the default version: +template +BOOST_MP_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int>::value && + (Checked1 == unchecked)>::type +eval_lcm(cpp_int_backend + &result, + const cpp_int_backend &a, + const cpp_int_backend &b) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + *result.limbs() = boost::integer::lcm(*a.limbs(), *b.limbs()); + result.normalize(); // result may overflow the specified number of bits +} + +inline void conversion_overflow(const mpl::int_ &) { + BOOST_THROW_EXCEPTION( + std::overflow_error("Overflow in conversion to narrower type")); +} +inline void conversion_overflow(const mpl::int_ &) {} + +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_signed_number >::value - && boost::is_convertible::local_limb_type, R>::value - >::type - eval_convert_to(R* result, const cpp_int_backend& val) -{ - typedef typename common_type::local_limb_type>::type common_type; - if(std::numeric_limits::is_specialized && (static_cast(*val.limbs()) > static_cast((std::numeric_limits::max)()))) - { - if(val.isneg()) - { - check_is_negative(mpl::bool_::value || (number_category::value == number_kind_floating_point)>()); - if(static_cast(*val.limbs()) > -static_cast((std::numeric_limits::min)())) - conversion_overflow(typename cpp_int_backend::checked_type()); - *result = (std::numeric_limits::min)(); - } - else - { - conversion_overflow(typename cpp_int_backend::checked_type()); - *result = boost::is_signed::value ? (std::numeric_limits::max)() : static_cast(*val.limbs()); - } - } - else - { - *result = static_cast(*val.limbs()); - if(val.isneg()) - { - check_is_negative(mpl::bool_::value || (number_category::value == number_kind_floating_point)>()); - *result = negate_integer(*result, mpl::bool_::value || (number_category::value == number_kind_floating_point)>()); - } - } -} - -template + is_trivial_cpp_int>::value && + is_signed_number>::value && + boost::is_convertible< + typename cpp_int_backend::local_limb_type, + R>::value>::type +eval_convert_to(R *result, const cpp_int_backend &val) { + typedef typename common_type< + R, typename cpp_int_backend::local_limb_type>::type + common_type; + if (std::numeric_limits::is_specialized && + (static_cast(*val.limbs()) > + static_cast((std::numeric_limits::max)()))) { + if (val.isneg()) { + check_is_negative( + mpl::bool_ < boost::is_signed::value || + (number_category::value == number_kind_floating_point) > ()); + if (static_cast(*val.limbs()) > + -static_cast((std::numeric_limits::min)())) + conversion_overflow( + typename cpp_int_backend::checked_type()); + *result = (std::numeric_limits::min)(); + } else { + conversion_overflow( + typename cpp_int_backend::checked_type()); + *result = boost::is_signed::value ? (std::numeric_limits::max)() + : static_cast(*val.limbs()); + } + } else { + *result = static_cast(*val.limbs()); + if (val.isneg()) { + check_is_negative( + mpl::bool_ < boost::is_signed::value || + (number_category::value == number_kind_floating_point) > ()); + *result = + negate_integer(*result, mpl::bool_ < is_signed_number::value || + (number_category::value == + number_kind_floating_point) > ()); + } + } +} + +template +inline typename enable_if_c< + is_trivial_cpp_int>::value && + is_unsigned_number>::value && + boost::is_convertible< + typename cpp_int_backend::local_limb_type, + R>::value>::type +eval_convert_to(R *result, const cpp_int_backend &val) { + typedef typename common_type< + R, typename cpp_int_backend::local_limb_type>::type + common_type; + if (std::numeric_limits::is_specialized && + (static_cast(*val.limbs()) > + static_cast((std::numeric_limits::max)()))) { + conversion_overflow( + typename cpp_int_backend::checked_type()); + *result = boost::is_signed::value ? (std::numeric_limits::max)() + : static_cast(*val.limbs()); + } else + *result = static_cast(*val.limbs()); +} + +template +inline typename enable_if_c< + is_trivial_cpp_int>::value, + unsigned>::type +eval_lsb(const cpp_int_backend &a) { + using default_ops::eval_get_sign; + if (eval_get_sign(a) == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (a.sign()) { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + // + // Find the index of the least significant bit within that limb: + // + return boost::multiprecision::detail::find_lsb(*a.limbs()); +} + +template +inline typename enable_if_c< + is_trivial_cpp_int>::value, + unsigned>::type +eval_msb_imp(const cpp_int_backend &a) { + // + // Find the index of the least significant bit within that limb: + // + return boost::multiprecision::detail::find_msb(*a.limbs()); +} + +template inline typename enable_if_c< - is_trivial_cpp_int >::value - && is_unsigned_number >::value - && boost::is_convertible::local_limb_type, R>::value - >::type - eval_convert_to(R* result, const cpp_int_backend& val) -{ - typedef typename common_type::local_limb_type>::type common_type; - if(std::numeric_limits::is_specialized && (static_cast(*val.limbs()) > static_cast((std::numeric_limits::max)()))) - { - conversion_overflow(typename cpp_int_backend::checked_type()); - *result = boost::is_signed::value ? (std::numeric_limits::max)() : static_cast(*val.limbs()); - } - else - *result = static_cast(*val.limbs()); -} - -template -inline typename enable_if_c >::value, unsigned>::type - eval_lsb(const cpp_int_backend& a) -{ - using default_ops::eval_get_sign; - if(eval_get_sign(a) == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - if(a.sign()) - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - // - // Find the index of the least significant bit within that limb: - // - return boost::multiprecision::detail::find_lsb(*a.limbs()); -} - -template -inline typename enable_if_c >::value, unsigned>::type -eval_msb_imp(const cpp_int_backend& a) -{ - // - // Find the index of the least significant bit within that limb: - // - return boost::multiprecision::detail::find_msb(*a.limbs()); -} - -template -inline typename enable_if_c >::value, unsigned>::type - eval_msb(const cpp_int_backend& a) -{ - using default_ops::eval_get_sign; - if(eval_get_sign(a) == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - if(a.sign()) - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - return eval_msb_imp(a); -} - -template -inline std::size_t hash_value(const cpp_int_backend& val) BOOST_NOEXCEPT -{ - std::size_t result = 0; - for(unsigned i = 0; i < val.size(); ++i) - { - boost::hash_combine(result, val.limbs()[i]); - } - boost::hash_combine(result, val.sign()); - return result; + is_trivial_cpp_int>::value, + unsigned>::type +eval_msb(const cpp_int_backend &a) { + using default_ops::eval_get_sign; + if (eval_get_sign(a) == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (a.sign()) { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + return eval_msb_imp(a); +} + +template +inline std::size_t +hash_value(const cpp_int_backend &val) BOOST_NOEXCEPT { + std::size_t result = 0; + for (unsigned i = 0; i < val.size(); ++i) { + boost::hash_combine(result, val.limbs()[i]); + } + boost::hash_combine(result, val.sign()); + return result; } #ifdef BOOST_MSVC #pragma warning(pop) #endif -}}} // namespaces +} // namespace backends +} // namespace multiprecision +} // namespace boost #endif diff --git a/include/boost/multiprecision/cpp_int/multiply.hpp b/include/boost/multiprecision/cpp_int/multiply.hpp index f94ca84d5..1dc5bc0da 100644 --- a/include/boost/multiprecision/cpp_int/multiply.hpp +++ b/include/boost/multiprecision/cpp_int/multiply.hpp @@ -8,32 +8,32 @@ #ifndef BOOST_MP_CPP_INT_MUL_HPP #define BOOST_MP_CPP_INT_MUL_HPP -namespace boost{ namespace multiprecision{ namespace backends{ +namespace boost { namespace multiprecision { namespace backends { #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable : 4127) // conditional expression is constant #endif - - template -inline typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& a, - const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) + +template +inline typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &a, + const limb_type & val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(!val) + if (!val) { result = static_cast(0); return; } - if((void*)&a != (void*)&result) + if ((void *)&a != (void *)&result) result.resize(a.size(), a.size()); - double_limb_type carry = 0; - typename cpp_int_backend::limb_pointer p = result.limbs(); - typename cpp_int_backend::limb_pointer pe = result.limbs() + result.size(); - typename cpp_int_backend::const_limb_pointer pa = a.limbs(); - while(p != pe) + double_limb_type carry = 0; + typename cpp_int_backend::limb_pointer p = result.limbs(); + typename cpp_int_backend::limb_pointer pe = result.limbs() + result.size(); + typename cpp_int_backend::const_limb_pointer pa = a.limbs(); + while (p != pe) { carry += static_cast(*pa) * static_cast(val); #ifdef __MSVC_RUNTIME_CHECKS @@ -44,15 +44,15 @@ inline typename enable_if_c>= cpp_int_backend::limb_bits; ++p, ++pa; } - if(carry) + if (carry) { unsigned i = result.size(); result.resize(i + 1, i + 1); - if(result.size() > i) + if (result.size() > i) result.limbs()[i] = static_cast(carry); } result.sign(a.sign()); - if(!cpp_int_backend::variable) + if (!cpp_int_backend::variable) result.normalize(); } @@ -62,35 +62,35 @@ inline typename enable_if_c -inline void resize_for_carry(cpp_int_backend& /*result*/, unsigned /*required*/){} +inline void resize_for_carry(cpp_int_backend & /*result*/, unsigned /*required*/) {} template -inline void resize_for_carry(cpp_int_backend& result, unsigned required) +inline void resize_for_carry(cpp_int_backend &result, unsigned required) { - if(result.size() < required) + if (result.size() < required) result.resize(required, required); } template -inline typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& a, - const cpp_int_backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +inline typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { // Very simple long multiplication, only usable for small numbers of limb_type's // but that's the typical use case for this type anyway: // // Special cases first: // - unsigned as = a.size(); - unsigned bs = b.size(); + unsigned as = a.size(); + unsigned bs = b.size(); typename cpp_int_backend::const_limb_pointer pa = a.limbs(); typename cpp_int_backend::const_limb_pointer pb = b.limbs(); - if(as == 1) + if (as == 1) { bool s = b.sign() != a.sign(); - if(bs == 1) + if (bs == 1) { result = static_cast(*pa) * static_cast(*pb); } @@ -102,22 +102,22 @@ inline typename enable_if_c t(a); eval_multiply(result, t, b); return; } - if((void*)&result == (void*)&b) + if ((void *)&result == (void *)&b) { cpp_int_backend t(b); eval_multiply(result, a, t); @@ -127,27 +127,25 @@ inline typename enable_if_c::limb_pointer pr = result.limbs(); - static const double_limb_type limb_max = ~static_cast(0u); + static const double_limb_type limb_max = ~static_cast(0u); static const double_limb_type double_limb_max = ~static_cast(0u); BOOST_STATIC_ASSERT(double_limb_max - 2 * limb_max >= limb_max * limb_max); double_limb_type carry = 0; std::memset(pr, 0, result.size() * sizeof(limb_type)); - for(unsigned i = 0; i < as; ++i) + for (unsigned i = 0; i < as; ++i) { unsigned inner_limit = cpp_int_backend::variable ? bs : (std::min)(result.size() - i, bs); unsigned j; - for(j = 0; j < inner_limit; ++j) + for (j = 0; j < inner_limit; ++j) { - BOOST_ASSERT(i+j < result.size()); + BOOST_ASSERT(i + j < result.size()); #if (!defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || !BOOST_WORKAROUND(BOOST_GCC_VERSION, <= 50100) - BOOST_ASSERT(!std::numeric_limits::is_specialized - || ((std::numeric_limits::max)() - carry - > - static_cast(cpp_int_backend::max_limb_value) * static_cast(cpp_int_backend::max_limb_value))); + BOOST_ASSERT(!std::numeric_limits::is_specialized || ((std::numeric_limits::max)() - carry > + static_cast(cpp_int_backend::max_limb_value) * static_cast(cpp_int_backend::max_limb_value))); #endif carry += static_cast(pa[i]) * static_cast(pb[j]); - BOOST_ASSERT(!std::numeric_limits::is_specialized || ((std::numeric_limits::max)() - carry >= pr[i+j])); + BOOST_ASSERT(!std::numeric_limits::is_specialized || ((std::numeric_limits::max)() - carry >= pr[i + j])); carry += pr[i + j]; #ifdef __MSVC_RUNTIME_CHECKS pr[i + j] = static_cast(carry & ~static_cast(0)); @@ -157,10 +155,10 @@ inline typename enable_if_c>= cpp_int_backend::limb_bits; BOOST_ASSERT(carry <= (cpp_int_backend::max_limb_value)); } - if(carry) + if (carry) { - resize_for_carry(result, i + j + 1); // May throw if checking is enabled - if(i + j < result.size()) + resize_for_carry(result, i + j + 1); // May throw if checking is enabled + if (i + j < result.size()) #ifdef __MSVC_RUNTIME_CHECKS pr[i + j] = static_cast(carry & ~static_cast(0)); #else @@ -177,29 +175,29 @@ inline typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& a) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &a) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - eval_multiply(result, result, a); + eval_multiply(result, result, a); } template -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_multiply(cpp_int_backend& result, const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_multiply(cpp_int_backend &result, const limb_type &val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { eval_multiply(result, result, val); } template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& a, - const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &a, + const double_limb_type & val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(val <= (std::numeric_limits::max)()) + if (val <= (std::numeric_limits::max)()) { eval_multiply(result, a, static_cast(val)); } @@ -216,20 +214,20 @@ BOOST_MP_FORCEINLINE typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_multiply(cpp_int_backend& result, const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_multiply(cpp_int_backend &result, const double_limb_type &val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { eval_multiply(result, result, val); } template -BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& a, - const signed_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &a, + const signed_limb_type & val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(val > 0) + if (val > 0) eval_multiply(result, a, static_cast(val)); else { @@ -239,28 +237,28 @@ BOOST_MP_FORCEINLINE typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_multiply(cpp_int_backend& result, const signed_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_multiply(cpp_int_backend &result, const signed_limb_type &val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { eval_multiply(result, result, val); } template -inline typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& a, - const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +inline typename enable_if_c >::value && !is_trivial_cpp_int >::value>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &a, + const signed_double_limb_type & val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { - if(val > 0) + if (val > 0) { - if(val <= (std::numeric_limits::max)()) + if (val <= (std::numeric_limits::max)()) { eval_multiply(result, a, static_cast(val)); return; } } - else if(val >= -static_cast((std::numeric_limits::max)())) + else if (val >= -static_cast((std::numeric_limits::max)())) { eval_multiply(result, a, static_cast(boost::multiprecision::detail::unsigned_abs(val))); result.negate(); @@ -276,8 +274,8 @@ inline typename enable_if_c -BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type - eval_multiply(cpp_int_backend& result, const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +BOOST_MP_FORCEINLINE typename enable_if_c >::value>::type +eval_multiply(cpp_int_backend &result, const signed_double_limb_type &val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { eval_multiply(result, result, val); } @@ -287,14 +285,10 @@ BOOST_MP_FORCEINLINE typename enable_if_c BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && (is_signed_number >::value - || is_signed_number >::value) - >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) + is_trivial_cpp_int >::value && is_trivial_cpp_int >::value && (is_signed_number >::value || is_signed_number >::value)>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); result.sign(result.sign() != o.sign()); @@ -303,12 +297,10 @@ BOOST_MP_FORCEINLINE typename enable_if_c< template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value - && is_unsigned_number >::value - >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) + is_trivial_cpp_int >::value && is_unsigned_number >::value>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); result.normalize(); @@ -316,15 +308,11 @@ BOOST_MP_FORCEINLINE typename enable_if_c< template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && (is_signed_number >::value - || is_signed_number >::value) - >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& a, - const cpp_int_backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) + is_trivial_cpp_int >::value && is_trivial_cpp_int >::value && (is_signed_number >::value || is_signed_number >::value)>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend::checked_type()); result.sign(a.sign() != b.sign()); @@ -333,13 +321,11 @@ BOOST_MP_FORCEINLINE typename enable_if_c< template BOOST_MP_FORCEINLINE typename enable_if_c< - is_trivial_cpp_int >::value - && is_unsigned_number >::value - >::type - eval_multiply( - cpp_int_backend& result, - const cpp_int_backend& a, - const cpp_int_backend& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) + is_trivial_cpp_int >::value && is_unsigned_number >::value>::type +eval_multiply( + cpp_int_backend & result, + const cpp_int_backend &a, + const cpp_int_backend &b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) { *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend::checked_type()); result.normalize(); @@ -350,22 +336,21 @@ BOOST_MP_FORCEINLINE typename enable_if_c< // template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value - >::type - eval_multiply( - cpp_int_backend& result, - signed_double_limb_type a, signed_double_limb_type b) + !is_trivial_cpp_int >::value>::type +eval_multiply( + cpp_int_backend &result, + signed_double_limb_type a, signed_double_limb_type b) { - static const signed_double_limb_type mask = ~static_cast(0); - static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; - bool s = false; - double_limb_type w, x, y, z; - if(a < 0) + static const signed_double_limb_type mask = ~static_cast(0); + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + bool s = false; + double_limb_type w, x, y, z; + if (a < 0) { a = -a; s = true; } - if(b < 0) + if (b < 0) { b = -b; s = !s; @@ -376,7 +361,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c< z = b >> limb_bits; result.resize(4, 4); - limb_type* pr = result.limbs(); + limb_type *pr = result.limbs(); double_limb_type carry = w * y; #ifdef __MSVC_RUNTIME_CHECKS @@ -404,14 +389,13 @@ BOOST_MP_FORCEINLINE typename enable_if_c< template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value - >::type - eval_multiply( - cpp_int_backend& result, - double_limb_type a, double_limb_type b) + !is_trivial_cpp_int >::value>::type +eval_multiply( + cpp_int_backend &result, + double_limb_type a, double_limb_type b) { - static const signed_double_limb_type mask = ~static_cast(0); - static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + static const signed_double_limb_type mask = ~static_cast(0); + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; double_limb_type w, x, y, z; w = a & mask; @@ -420,7 +404,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c< z = b >> limb_bits; result.resize(4, 4); - limb_type* pr = result.limbs(); + limb_type *pr = result.limbs(); double_limb_type carry = w * y; #ifdef __MSVC_RUNTIME_CHECKS @@ -457,14 +441,11 @@ BOOST_MP_FORCEINLINE typename enable_if_c< template BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - && is_trivial_cpp_int >::value - >::type - eval_multiply( - cpp_int_backend& result, - cpp_int_backend const& a, - cpp_int_backend const& b) + !is_trivial_cpp_int >::value && is_trivial_cpp_int >::value && is_trivial_cpp_int >::value>::type +eval_multiply( + cpp_int_backend & result, + cpp_int_backend const &a, + cpp_int_backend const &b) { typedef typename boost::multiprecision::detail::canonical::local_limb_type, cpp_int_backend >::type canonical_type; eval_multiply(result, static_cast(*a.limbs()), static_cast(*b.limbs())); @@ -473,18 +454,18 @@ BOOST_MP_FORCEINLINE typename enable_if_c< template BOOST_MP_FORCEINLINE typename enable_if_c::value && (sizeof(SI) <= sizeof(signed_double_limb_type) / 2)>::type - eval_multiply( - cpp_int_backend& result, - SI a, SI b) +eval_multiply( + cpp_int_backend &result, + SI a, SI b) { result = static_cast(a) * static_cast(b); } template BOOST_MP_FORCEINLINE typename enable_if_c::value && (sizeof(UI) <= sizeof(signed_double_limb_type) / 2)>::type - eval_multiply( - cpp_int_backend& result, - UI a, UI b) +eval_multiply( + cpp_int_backend &result, + UI a, UI b) { result = static_cast(a) * static_cast(b); } @@ -493,6 +474,6 @@ BOOST_MP_FORCEINLINE typename enable_if_c::value && (sizeof(UI) #pragma warning(pop) #endif -}}} // namespaces +}}} // namespace boost::multiprecision::backends #endif diff --git a/include/boost/multiprecision/detail/default_ops.hpp b/include/boost/multiprecision/detail/default_ops.hpp index 459092c7e..41a64a980 100644 --- a/include/boost/multiprecision/detail/default_ops.hpp +++ b/include/boost/multiprecision/detail/default_ops.hpp @@ -6,16 +6,16 @@ #ifndef BOOST_MATH_BIG_NUM_DEF_OPS #define BOOST_MATH_BIG_NUM_DEF_OPS +#include #include -#include #include -#include #include -#include -#include +#include #include -#include +#include +#include #include +#include #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW #include #endif @@ -24,1855 +24,1731 @@ #ifndef BOOST_MP_INSTRUMENT #define INSTRUMENT_BACKEND(x) #else -#define INSTRUMENT_BACKEND(x)\ - std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl; +#define INSTRUMENT_BACKEND(x) \ + std::cout << BOOST_STRINGIZE(x) << " = " \ + << x.str(0, std::ios_base::scientific) << std::endl; #endif #endif +namespace boost { +namespace multiprecision { -namespace boost{ namespace multiprecision{ - - namespace detail { +namespace detail { - template - struct is_backend; +template struct is_backend; - template - void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/); - template - void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/); - template - void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/); - template - void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/); - template - void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/); +template +void generic_interconvert( + To &to, const From &from, + const mpl::int_ & /*to_type*/, + const mpl::int_ & /*from_type*/); +template +void generic_interconvert(To &to, const From &from, + const mpl::int_ & /*to_type*/, + const mpl::int_ & /*from_type*/); +template +void generic_interconvert( + To &to, const From &from, + const mpl::int_ & /*to_type*/, + const mpl::int_ & /*from_type*/); +template +void generic_interconvert( + To &to, const From &from, + const mpl::int_ & /*to_type*/, + const mpl::int_ & /*from_type*/); +template +void generic_interconvert(To &to, const From &from, + const mpl::int_ & /*to_type*/, + const mpl::int_ & /*from_type*/); -} - -namespace default_ops{ +} // namespace detail + +namespace default_ops { #ifdef BOOST_MSVC // warning C4127: conditional expression is constant -// warning C4146: unary minus operator applied to unsigned type, result still unsigned +// warning C4146: unary minus operator applied to unsigned type, result still +// unsigned #pragma warning(push) -#pragma warning(disable:4127 4146) +#pragma warning(disable : 4127 4146) #endif // // Default versions of mixed arithmetic, these just construct a temporary // from the arithmetic value and then do the arithmetic on that, two versions -// of each depending on whether the backend can be directly constructed from type V. +// of each depending on whether the backend can be directly constructed from +// type V. // -// Note that we have to provide *all* the template parameters to class number when used in -// enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter. -// Since the result of the test doesn't depend on whether expression templates are on or off -// we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the -// code even more.... +// Note that we have to provide *all* the template parameters to class number +// when used in enable_if as MSVC-10 won't compile the code if we rely on a +// computed-default parameter. Since the result of the test doesn't depend on +// whether expression templates are on or off we just use et_on everywhere. We +// could use a BOOST_WORKAROUND but that just obfuscates the code even more.... // template -inline typename disable_if_c::value >::type - eval_add(T& result, V const& v) -{ - T t; - t = v; - eval_add(result, t); +inline typename disable_if_c::value>::type +eval_add(T &result, V const &v) { + T t; + t = v; + eval_add(result, t); } template -inline typename enable_if_c::value >::type - eval_add(T& result, V const& v) -{ - T t(v); - eval_add(result, t); +inline typename enable_if_c::value>::type +eval_add(T &result, V const &v) { + T t(v); + eval_add(result, t); } template inline typename disable_if_c::value>::type - eval_subtract(T& result, V const& v) -{ - T t; - t = v; - eval_subtract(result, t); +eval_subtract(T &result, V const &v) { + T t; + t = v; + eval_subtract(result, t); } template inline typename enable_if_c::value>::type - eval_subtract(T& result, V const& v) -{ - T t(v); - eval_subtract(result, t); +eval_subtract(T &result, V const &v) { + T t(v); + eval_subtract(result, t); } template inline typename disable_if_c::value>::type - eval_multiply(T& result, V const& v) -{ - T t; - t = v; - eval_multiply(result, t); +eval_multiply(T &result, V const &v) { + T t; + t = v; + eval_multiply(result, t); } template inline typename enable_if_c::value>::type - eval_multiply(T& result, V const& v) -{ - T t(v); - eval_multiply(result, t); +eval_multiply(T &result, V const &v) { + T t(v); + eval_multiply(result, t); } template -void eval_multiply(T& t, const U& u, const V& v); +void eval_multiply(T &t, const U &u, const V &v); template -inline typename disable_if_c::value && is_same::value>::type eval_multiply_add(T& t, const U& u, const V& v) -{ - T z; - eval_multiply(z, u, v); - eval_add(t, z); +inline + typename disable_if_c::value && is_same::value>::type + eval_multiply_add(T &t, const U &u, const V &v) { + T z; + eval_multiply(z, u, v); + eval_add(t, z); } template -inline typename enable_if_c::value && is_same::value>::type eval_multiply_add(T& t, const U& u, const V& v) -{ - eval_multiply_add(t, v, u); +inline typename enable_if_c::value && is_same::value>::type +eval_multiply_add(T &t, const U &u, const V &v) { + eval_multiply_add(t, v, u); } template -inline typename disable_if_c::value && is_same::value>::type eval_multiply_subtract(T& t, const U& u, const V& v) -{ - T z; - eval_multiply(z, u, v); - eval_subtract(t, z); +inline + typename disable_if_c::value && is_same::value>::type + eval_multiply_subtract(T &t, const U &u, const V &v) { + T z; + eval_multiply(z, u, v); + eval_subtract(t, z); } template -inline typename enable_if_c::value && is_same::value>::type eval_multiply_subtract(T& t, const U& u, const V& v) -{ - eval_multiply_subtract(t, v, u); +inline typename enable_if_c::value && is_same::value>::type +eval_multiply_subtract(T &t, const U &u, const V &v) { + eval_multiply_subtract(t, v, u); } template -inline typename enable_if_c >::value && !is_convertible::value>::type - eval_divide(T& result, V const& v) -{ - T t; - t = v; - eval_divide(result, t); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_divide(T &result, V const &v) { + T t; + t = v; + eval_divide(result, t); } template -inline typename enable_if_c >::value && is_convertible::value>::type - eval_divide(T& result, V const& v) -{ - T t(v); - eval_divide(result, t); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_divide(T &result, V const &v) { + T t(v); + eval_divide(result, t); } template -inline typename enable_if_c >::value && !is_convertible::value>::type - eval_modulus(T& result, V const& v) -{ - T t; - t = v; - eval_modulus(result, t); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_modulus(T &result, V const &v) { + T t; + t = v; + eval_modulus(result, t); } template -inline typename enable_if_c >::value&& is_convertible::value>::type - eval_modulus(T& result, V const& v) -{ - T t(v); - eval_modulus(result, t); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_modulus(T &result, V const &v) { + T t(v); + eval_modulus(result, t); } template -inline typename enable_if_c >::value && !is_convertible::value>::type - eval_bitwise_and(T& result, V const& v) -{ - T t; - t = v; - eval_bitwise_and(result, t); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_bitwise_and(T &result, V const &v) { + T t; + t = v; + eval_bitwise_and(result, t); } template -inline typename enable_if_c >::value && is_convertible::value>::type - eval_bitwise_and(T& result, V const& v) -{ - T t(v); - eval_bitwise_and(result, t); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_bitwise_and(T &result, V const &v) { + T t(v); + eval_bitwise_and(result, t); } template -inline typename enable_if_c >::value && !is_convertible::value>::type - eval_bitwise_or(T& result, V const& v) -{ - T t; - t = v; - eval_bitwise_or(result, t); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_bitwise_or(T &result, V const &v) { + T t; + t = v; + eval_bitwise_or(result, t); } template -inline typename enable_if_c >::value && is_convertible::value>::type - eval_bitwise_or(T& result, V const& v) -{ - T t(v); - eval_bitwise_or(result, t); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_bitwise_or(T &result, V const &v) { + T t(v); + eval_bitwise_or(result, t); } template -inline typename enable_if_c >::value && !is_convertible::value>::type - eval_bitwise_xor(T& result, V const& v) -{ - T t; - t = v; - eval_bitwise_xor(result, t); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_bitwise_xor(T &result, V const &v) { + T t; + t = v; + eval_bitwise_xor(result, t); } template -inline typename enable_if_c >::value && is_convertible::value>::type - eval_bitwise_xor(T& result, V const& v) -{ - T t(v); - eval_bitwise_xor(result, t); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_bitwise_xor(T &result, V const &v) { + T t(v); + eval_bitwise_xor(result, t); } template -inline typename enable_if_c >::value && !is_convertible::value>::type - eval_complement(T& result, V const& v) -{ - T t; - t = v; - eval_complement(result, t); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_complement(T &result, V const &v) { + T t; + t = v; + eval_complement(result, t); } template -inline typename enable_if_c >::value && is_convertible::value>::type - eval_complement(T& result, V const& v) -{ - T t(v); - eval_complement(result, t); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_complement(T &result, V const &v) { + T t(v); + eval_complement(result, t); } // -// Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions: +// Default versions of 3-arg arithmetic functions, these mostly just forward to +// the 2 arg versions: // template -void eval_add(T& t, const U& u, const V& v); - -template -inline void eval_add_default(T& t, const T& u, const T& v) -{ - if(&t == &v) - { - eval_add(t, u); - } - else if(&t == &u) - { - eval_add(t, v); - } - else - { - t = u; - eval_add(t, v); - } +void eval_add(T &t, const U &u, const V &v); + +template inline void eval_add_default(T &t, const T &u, const T &v) { + if (&t == &v) { + eval_add(t, u); + } else if (&t == &u) { + eval_add(t, v); + } else { + t = u; + eval_add(t, v); + } } template -inline typename enable_if_c >::value && !is_convertible::value>::type eval_add_default(T& t, const T& u, const U& v) -{ - T vv; - vv = v; - eval_add(t, u, vv); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_add_default(T &t, const T &u, const U &v) { + T vv; + vv = v; + eval_add(t, u, vv); } template -inline typename enable_if_c >::value && is_convertible::value>::type eval_add_default(T& t, const T& u, const U& v) -{ - T vv(v); - eval_add(t, u, vv); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_add_default(T &t, const T &u, const U &v) { + T vv(v); + eval_add(t, u, vv); } template -inline typename enable_if_c >::value>::type eval_add_default(T& t, const U& u, const T& v) -{ - eval_add(t, v, u); +inline typename enable_if_c>::value>::type +eval_add_default(T &t, const U &u, const T &v) { + eval_add(t, v, u); } template -inline void eval_add_default(T& t, const U& u, const V& v) -{ - if(is_same::value && ((void*)&t == (void*)&v)) - { - eval_add(t, u); - } - else - { - t = u; - eval_add(t, v); - } +inline void eval_add_default(T &t, const U &u, const V &v) { + if (is_same::value && ((void *)&t == (void *)&v)) { + eval_add(t, u); + } else { + t = u; + eval_add(t, v); + } } template -inline void eval_add(T& t, const U& u, const V& v) -{ - eval_add_default(t, u, v); +inline void eval_add(T &t, const U &u, const V &v) { + eval_add_default(t, u, v); } template -void eval_subtract(T& t, const U& u, const V& v); +void eval_subtract(T &t, const U &u, const V &v); template -inline void eval_subtract_default(T& t, const T& u, const T& v) -{ - if((&t == &v) && is_signed_number::value) - { - eval_subtract(t, u); - t.negate(); - } - else if(&t == &u) - { - eval_subtract(t, v); - } - else - { - t = u; - eval_subtract(t, v); - } +inline void eval_subtract_default(T &t, const T &u, const T &v) { + if ((&t == &v) && is_signed_number::value) { + eval_subtract(t, u); + t.negate(); + } else if (&t == &u) { + eval_subtract(t, v); + } else { + t = u; + eval_subtract(t, v); + } } template -inline typename enable_if_c >::value && !is_convertible::value>::type eval_subtract_default(T& t, const T& u, const U& v) -{ - T vv; - vv = v; - eval_subtract(t, u, vv); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_subtract_default(T &t, const T &u, const U &v) { + T vv; + vv = v; + eval_subtract(t, u, vv); } template -inline typename enable_if_c >::value && is_convertible::value>::type eval_subtract_default(T& t, const T& u, const U& v) -{ - T vv(v); - eval_subtract(t, u, vv); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_subtract_default(T &t, const T &u, const U &v) { + T vv(v); + eval_subtract(t, u, vv); } template -inline typename enable_if_c >::value && is_signed_number::value>::type eval_subtract_default(T& t, const U& u, const T& v) -{ - eval_subtract(t, v, u); - t.negate(); +inline typename enable_if_c>::value && + is_signed_number::value>::type +eval_subtract_default(T &t, const U &u, const T &v) { + eval_subtract(t, v, u); + t.negate(); } template -inline typename enable_if_c >::value && !is_convertible::value && is_unsigned_number::value>::type eval_subtract_default(T& t, const U& u, const T& v) -{ - T temp; - temp = u; - eval_subtract(t, temp, v); +inline typename enable_if_c>::value && + !is_convertible::value && + is_unsigned_number::value>::type +eval_subtract_default(T &t, const U &u, const T &v) { + T temp; + temp = u; + eval_subtract(t, temp, v); } template -inline typename enable_if_c >::value && is_convertible::value && is_unsigned_number::value>::type eval_subtract_default(T& t, const U& u, const T& v) -{ - T temp(u); - eval_subtract(t, temp, v); +inline typename enable_if_c>::value && + is_convertible::value && + is_unsigned_number::value>::type +eval_subtract_default(T &t, const U &u, const T &v) { + T temp(u); + eval_subtract(t, temp, v); } template -inline void eval_subtract_default(T& t, const U& u, const V& v) -{ - if(is_same::value && ((void*)&t == (void*)&v)) - { - eval_subtract(t, u); - t.negate(); - } - else - { - t = u; - eval_subtract(t, v); - } +inline void eval_subtract_default(T &t, const U &u, const V &v) { + if (is_same::value && ((void *)&t == (void *)&v)) { + eval_subtract(t, u); + t.negate(); + } else { + t = u; + eval_subtract(t, v); + } } template -inline void eval_subtract(T& t, const U& u, const V& v) -{ - eval_subtract_default(t, u, v); +inline void eval_subtract(T &t, const U &u, const V &v) { + eval_subtract_default(t, u, v); } template -inline void eval_multiply_default(T& t, const T& u, const T& v) -{ - if(&t == &v) - { - eval_multiply(t, u); - } - else if(&t == &u) - { - eval_multiply(t, v); - } - else - { - t = u; - eval_multiply(t, v); - } +inline void eval_multiply_default(T &t, const T &u, const T &v) { + if (&t == &v) { + eval_multiply(t, u); + } else if (&t == &u) { + eval_multiply(t, v); + } else { + t = u; + eval_multiply(t, v); + } } #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900) template -inline typename enable_if_c >::value && !is_convertible::value>::type eval_multiply_default(T& t, const T& u, const U& v) -{ - T vv; - vv = v; - eval_multiply(t, u, vv); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_multiply_default(T &t, const T &u, const U &v) { + T vv; + vv = v; + eval_multiply(t, u, vv); } template -inline typename enable_if_c >::value && is_convertible::value>::type eval_multiply_default(T& t, const T& u, const U& v) -{ - T vv(v); - eval_multiply(t, u, vv); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_multiply_default(T &t, const T &u, const U &v) { + T vv(v); + eval_multiply(t, u, vv); } template -inline typename enable_if_c >::value>::type eval_multiply_default(T& t, const U& u, const T& v) -{ - eval_multiply(t, v, u); +inline typename enable_if_c>::value>::type +eval_multiply_default(T &t, const U &u, const T &v) { + eval_multiply(t, v, u); } #endif template -inline void eval_multiply_default(T& t, const U& u, const V& v) -{ - if(is_same::value && ((void*)&t == (void*)&v)) - { - eval_multiply(t, u); - } - else - { - t = number::canonical_value(u); - eval_multiply(t, v); - } +inline void eval_multiply_default(T &t, const U &u, const V &v) { + if (is_same::value && ((void *)&t == (void *)&v)) { + eval_multiply(t, u); + } else { + t = number::canonical_value(u); + eval_multiply(t, v); + } } template -inline void eval_multiply(T& t, const U& u, const V& v) -{ - eval_multiply_default(t, u, v); +inline void eval_multiply(T &t, const U &u, const V &v) { + eval_multiply_default(t, u, v); } template -inline void eval_multiply_add(T& t, const T& u, const T& v, const T& x) -{ - if((void*)&x == (void*)&t) - { - T z; - z = number::canonical_value(x); - eval_multiply_add(t, u, v, z); - } - else - { - eval_multiply(t, u, v); - eval_add(t, x); - } +inline void eval_multiply_add(T &t, const T &u, const T &v, const T &x) { + if ((void *)&x == (void *)&t) { + T z; + z = number::canonical_value(x); + eval_multiply_add(t, u, v, z); + } else { + eval_multiply(t, u, v); + eval_add(t, x); + } } template -inline typename boost::disable_if_c::value, T>::type make_T(const U& u) -{ - T t; - t = number::canonical_value(u); - return BOOST_MP_MOVE(t); -} -template -inline const T& make_T(const T& t) -{ - return t; +inline typename boost::disable_if_c::value, T>::type +make_T(const U &u) { + T t; + t = number::canonical_value(u); + return BOOST_MP_MOVE(t); } +template inline const T &make_T(const T &t) { return t; } template -inline typename disable_if_c::value && is_same::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x) -{ - eval_multiply_add(t, make_T(u), make_T(v), make_T(x)); +inline + typename disable_if_c::value && is_same::value>::type + eval_multiply_add(T &t, const U &u, const V &v, const X &x) { + eval_multiply_add(t, make_T(u), make_T(v), make_T(x)); } template -inline typename enable_if_c::value && is_same::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x) -{ - eval_multiply_add(t, v, u, x); +inline typename enable_if_c::value && is_same::value>::type +eval_multiply_add(T &t, const U &u, const V &v, const X &x) { + eval_multiply_add(t, v, u, x); } template -inline typename disable_if_c::value && is_same::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x) -{ - if((void*)&x == (void*)&t) - { - T z; - z = x; - eval_multiply_subtract(t, u, v, z); - } - else - { - eval_multiply(t, u, v); - eval_subtract(t, x); - } +inline + typename disable_if_c::value && is_same::value>::type + eval_multiply_subtract(T &t, const U &u, const V &v, const X &x) { + if ((void *)&x == (void *)&t) { + T z; + z = x; + eval_multiply_subtract(t, u, v, z); + } else { + eval_multiply(t, u, v); + eval_subtract(t, x); + } } template -inline typename enable_if_c::value && is_same::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x) -{ - eval_multiply_subtract(t, v, u, x); +inline typename enable_if_c::value && is_same::value>::type +eval_multiply_subtract(T &t, const U &u, const V &v, const X &x) { + eval_multiply_subtract(t, v, u, x); } template -void eval_divide(T& t, const U& u, const V& v); +void eval_divide(T &t, const U &u, const V &v); template -inline void eval_divide_default(T& t, const T& u, const T& v) -{ - if(&t == &u) - eval_divide(t, v); - else if(&t == &v) - { - T temp; - eval_divide(temp, u, v); - temp.swap(t); - } - else - { - t = u; - eval_divide(t, v); - } +inline void eval_divide_default(T &t, const T &u, const T &v) { + if (&t == &u) + eval_divide(t, v); + else if (&t == &v) { + T temp; + eval_divide(temp, u, v); + temp.swap(t); + } else { + t = u; + eval_divide(t, v); + } } #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900) template -inline typename enable_if_c >::value && !is_convertible::value>::type eval_divide_default(T& t, const T& u, const U& v) -{ - T vv; - vv = v; - eval_divide(t, u, vv); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_divide_default(T &t, const T &u, const U &v) { + T vv; + vv = v; + eval_divide(t, u, vv); } template -inline typename enable_if_c >::value && is_convertible::value>::type eval_divide_default(T& t, const T& u, const U& v) -{ - T vv(v); - eval_divide(t, u, vv); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_divide_default(T &t, const T &u, const U &v) { + T vv(v); + eval_divide(t, u, vv); } template -inline typename enable_if_c >::value && !is_convertible::value>::type eval_divide_default(T& t, const U& u, const T& v) -{ - T uu; - uu = u; - eval_divide(t, uu, v); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_divide_default(T &t, const U &u, const T &v) { + T uu; + uu = u; + eval_divide(t, uu, v); } template -inline typename enable_if_c >::value && is_convertible::value>::type eval_divide_default(T& t, const U& u, const T& v) -{ - T uu(u); - eval_divide(t, uu, v); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_divide_default(T &t, const U &u, const T &v) { + T uu(u); + eval_divide(t, uu, v); } #endif template -inline void eval_divide_default(T& t, const U& u, const V& v) -{ - if(is_same::value && ((void*)&t == (void*)&v)) - { - T temp; - temp = u; - eval_divide(temp, v); - t = temp; - } - else - { - t = u; - eval_divide(t, v); - } +inline void eval_divide_default(T &t, const U &u, const V &v) { + if (is_same::value && ((void *)&t == (void *)&v)) { + T temp; + temp = u; + eval_divide(temp, v); + t = temp; + } else { + t = u; + eval_divide(t, v); + } } template -inline void eval_divide(T& t, const U& u, const V& v) -{ - eval_divide_default(t, u, v); +inline void eval_divide(T &t, const U &u, const V &v) { + eval_divide_default(t, u, v); } template -void eval_modulus(T& t, const U& u, const V& v); +void eval_modulus(T &t, const U &u, const V &v); template -inline void eval_modulus_default(T& t, const T& u, const T& v) -{ - if(&t == &u) - eval_modulus(t, v); - else if(&t == &v) - { - T temp; - eval_modulus(temp, u, v); - temp.swap(t); - } - else - { - t = u; - eval_modulus(t, v); - } +inline void eval_modulus_default(T &t, const T &u, const T &v) { + if (&t == &u) + eval_modulus(t, v); + else if (&t == &v) { + T temp; + eval_modulus(temp, u, v); + temp.swap(t); + } else { + t = u; + eval_modulus(t, v); + } } template -inline typename enable_if_c >::value && !is_convertible::value>::type eval_modulus_default(T& t, const T& u, const U& v) -{ - T vv; - vv = v; - eval_modulus(t, u, vv); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_modulus_default(T &t, const T &u, const U &v) { + T vv; + vv = v; + eval_modulus(t, u, vv); } template -inline typename enable_if_c >::value && is_convertible::value>::type eval_modulus_default(T& t, const T& u, const U& v) -{ - T vv(v); - eval_modulus(t, u, vv); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_modulus_default(T &t, const T &u, const U &v) { + T vv(v); + eval_modulus(t, u, vv); } template -inline typename enable_if_c >::value && !is_convertible::value>::type eval_modulus_default(T& t, const U& u, const T& v) -{ - T uu; - uu = u; - eval_modulus(t, uu, v); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_modulus_default(T &t, const U &u, const T &v) { + T uu; + uu = u; + eval_modulus(t, uu, v); } template -inline typename enable_if_c >::value && is_convertible::value>::type eval_modulus_default(T& t, const U& u, const T& v) -{ - T uu(u); - eval_modulus(t, uu, v); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_modulus_default(T &t, const U &u, const T &v) { + T uu(u); + eval_modulus(t, uu, v); } template -inline void eval_modulus_default(T& t, const U& u, const V& v) -{ - if(is_same::value && ((void*)&t == (void*)&v)) - { - T temp(u); - eval_modulus(temp, v); - t = temp; - } - else - { - t = u; - eval_modulus(t, v); - } +inline void eval_modulus_default(T &t, const U &u, const V &v) { + if (is_same::value && ((void *)&t == (void *)&v)) { + T temp(u); + eval_modulus(temp, v); + t = temp; + } else { + t = u; + eval_modulus(t, v); + } } template -inline void eval_modulus(T& t, const U& u, const V& v) -{ - eval_modulus_default(t, u, v); +inline void eval_modulus(T &t, const U &u, const V &v) { + eval_modulus_default(t, u, v); } template -void eval_bitwise_and(T& t, const U& u, const V& v); +void eval_bitwise_and(T &t, const U &u, const V &v); template -inline void eval_bitwise_and_default(T& t, const T& u, const T& v) -{ - if(&t == &v) - { - eval_bitwise_and(t, u); - } - else if(&t == &u) - { - eval_bitwise_and(t, v); - } - else - { - t = u; - eval_bitwise_and(t, v); - } +inline void eval_bitwise_and_default(T &t, const T &u, const T &v) { + if (&t == &v) { + eval_bitwise_and(t, u); + } else if (&t == &u) { + eval_bitwise_and(t, v); + } else { + t = u; + eval_bitwise_and(t, v); + } } template -inline typename disable_if_c::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v) -{ - T vv; - vv = v; - eval_bitwise_and(t, u, vv); +inline typename disable_if_c::value>::type +eval_bitwise_and_default(T &t, const T &u, const U &v) { + T vv; + vv = v; + eval_bitwise_and(t, u, vv); } template -inline typename enable_if_c::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v) -{ - T vv(v); - eval_bitwise_and(t, u, vv); +inline typename enable_if_c::value>::type +eval_bitwise_and_default(T &t, const T &u, const U &v) { + T vv(v); + eval_bitwise_and(t, u, vv); } template -inline typename enable_if_c >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v) -{ - eval_bitwise_and(t, v, u); +inline typename enable_if_c>::value>::type +eval_bitwise_and_default(T &t, const U &u, const T &v) { + eval_bitwise_and(t, v, u); } template -inline typename disable_if_c::value || is_same::value>::type eval_bitwise_and_default(T& t, const U& u, const V& v) -{ - t = u; - eval_bitwise_and(t, v); +inline typename disable_if_c::value || is_same::value>::type +eval_bitwise_and_default(T &t, const U &u, const V &v) { + t = u; + eval_bitwise_and(t, v); } template -inline void eval_bitwise_and(T& t, const U& u, const V& v) -{ - eval_bitwise_and_default(t, u, v); +inline void eval_bitwise_and(T &t, const U &u, const V &v) { + eval_bitwise_and_default(t, u, v); } template -void eval_bitwise_or(T& t, const U& u, const V& v); +void eval_bitwise_or(T &t, const U &u, const V &v); template -inline void eval_bitwise_or_default(T& t, const T& u, const T& v) -{ - if(&t == &v) - { - eval_bitwise_or(t, u); - } - else if(&t == &u) - { - eval_bitwise_or(t, v); - } - else - { - t = u; - eval_bitwise_or(t, v); - } +inline void eval_bitwise_or_default(T &t, const T &u, const T &v) { + if (&t == &v) { + eval_bitwise_or(t, u); + } else if (&t == &u) { + eval_bitwise_or(t, v); + } else { + t = u; + eval_bitwise_or(t, v); + } } template -inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v) -{ - T vv; - vv = v; - eval_bitwise_or(t, u, vv); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_bitwise_or_default(T &t, const T &u, const U &v) { + T vv; + vv = v; + eval_bitwise_or(t, u, vv); } template -inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v) -{ - T vv(v); - eval_bitwise_or(t, u, vv); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_bitwise_or_default(T &t, const T &u, const U &v) { + T vv(v); + eval_bitwise_or(t, u, vv); } template -inline typename enable_if_c >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v) -{ - eval_bitwise_or(t, v, u); +inline typename enable_if_c>::value>::type +eval_bitwise_or_default(T &t, const U &u, const T &v) { + eval_bitwise_or(t, v, u); } template -inline void eval_bitwise_or_default(T& t, const U& u, const V& v) -{ - if(is_same::value && ((void*)&t == (void*)&v)) - { - eval_bitwise_or(t, u); - } - else - { - t = u; - eval_bitwise_or(t, v); - } +inline void eval_bitwise_or_default(T &t, const U &u, const V &v) { + if (is_same::value && ((void *)&t == (void *)&v)) { + eval_bitwise_or(t, u); + } else { + t = u; + eval_bitwise_or(t, v); + } } template -inline void eval_bitwise_or(T& t, const U& u, const V& v) -{ - eval_bitwise_or_default(t, u, v); +inline void eval_bitwise_or(T &t, const U &u, const V &v) { + eval_bitwise_or_default(t, u, v); } template -void eval_bitwise_xor(T& t, const U& u, const V& v); +void eval_bitwise_xor(T &t, const U &u, const V &v); template -inline void eval_bitwise_xor_default(T& t, const T& u, const T& v) -{ - if(&t == &v) - { - eval_bitwise_xor(t, u); - } - else if(&t == &u) - { - eval_bitwise_xor(t, v); - } - else - { - t = u; - eval_bitwise_xor(t, v); - } +inline void eval_bitwise_xor_default(T &t, const T &u, const T &v) { + if (&t == &v) { + eval_bitwise_xor(t, u); + } else if (&t == &u) { + eval_bitwise_xor(t, v); + } else { + t = u; + eval_bitwise_xor(t, v); + } } template -inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v) -{ - T vv; - vv = v; - eval_bitwise_xor(t, u, vv); +inline typename enable_if_c>::value && + !is_convertible::value>::type +eval_bitwise_xor_default(T &t, const T &u, const U &v) { + T vv; + vv = v; + eval_bitwise_xor(t, u, vv); } template -inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v) -{ - T vv(v); - eval_bitwise_xor(t, u, vv); +inline typename enable_if_c>::value && + is_convertible::value>::type +eval_bitwise_xor_default(T &t, const T &u, const U &v) { + T vv(v); + eval_bitwise_xor(t, u, vv); } template -inline typename enable_if_c >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v) -{ - eval_bitwise_xor(t, v, u); +inline typename enable_if_c>::value>::type +eval_bitwise_xor_default(T &t, const U &u, const T &v) { + eval_bitwise_xor(t, v, u); } template -inline void eval_bitwise_xor_default(T& t, const U& u, const V& v) -{ - if(is_same::value && ((void*)&t == (void*)&v)) - { - eval_bitwise_xor(t, u); - } - else - { - t = u; - eval_bitwise_xor(t, v); - } +inline void eval_bitwise_xor_default(T &t, const U &u, const V &v) { + if (is_same::value && ((void *)&t == (void *)&v)) { + eval_bitwise_xor(t, u); + } else { + t = u; + eval_bitwise_xor(t, v); + } } template -inline void eval_bitwise_xor(T& t, const U& u, const V& v) -{ - eval_bitwise_xor_default(t, u, v); +inline void eval_bitwise_xor(T &t, const U &u, const V &v) { + eval_bitwise_xor_default(t, u, v); } -template -inline void eval_increment(T& val) -{ - typedef typename mpl::front::type ui_type; - eval_add(val, static_cast(1u)); +template inline void eval_increment(T &val) { + typedef typename mpl::front::type ui_type; + eval_add(val, static_cast(1u)); } -template -inline void eval_decrement(T& val) -{ - typedef typename mpl::front::type ui_type; - eval_subtract(val, static_cast(1u)); +template inline void eval_decrement(T &val) { + typedef typename mpl::front::type ui_type; + eval_subtract(val, static_cast(1u)); } template -inline void eval_left_shift(T& result, const T& arg, const V val) -{ - result = arg; - eval_left_shift(result, val); +inline void eval_left_shift(T &result, const T &arg, const V val) { + result = arg; + eval_left_shift(result, val); } template -inline void eval_right_shift(T& result, const T& arg, const V val) -{ - result = arg; - eval_right_shift(result, val); +inline void eval_right_shift(T &result, const T &arg, const V val) { + result = arg; + eval_right_shift(result, val); } -template -inline bool eval_is_zero(const T& val) -{ - typedef typename mpl::front::type ui_type; - return val.compare(static_cast(0)) == 0; +template inline bool eval_is_zero(const T &val) { + typedef typename mpl::front::type ui_type; + return val.compare(static_cast(0)) == 0; } -template -inline int eval_get_sign(const T& val) -{ - typedef typename mpl::front::type ui_type; - return val.compare(static_cast(0)); +template inline int eval_get_sign(const T &val) { + typedef typename mpl::front::type ui_type; + return val.compare(static_cast(0)); } -template -inline void assign_components_imp(T& result, const long long& v1, const U& v2, const mpl::int_&) -{ - result.m_params = v2; - result = v1; - eval_multiply(result, v2.R2().backend()); - //eval_multiply(result, v1); +template +inline void assign_components_imp(T &result, const long long &v1, const U &v2, + const mpl::int_ &) { + result.m_params = v2; + result = v1; + eval_multiply(result, v2.R2().backend()); + // eval_multiply(result, v1); } template -inline void assign_components_imp(T& result, const V& v1, const U& v2, const mpl::int_&) -{ - result = v1; - T t; - t = v2; - eval_divide(result, t); +inline void assign_components_imp(T &result, const V &v1, const U &v2, + const mpl::int_ &) { + result = v1; + T t; + t = v2; + eval_divide(result, t); } template -inline void assign_components_imp(T& result, const V& v1, const U& v2, const mpl::int_&) -{ - typedef typename component_type >::type component_number_type; - component_number_type x(v1), y(v2); - assign_components(result, x.backend(), y.backend()); +inline void assign_components_imp(T &result, const V &v1, const U &v2, + const mpl::int_ &) { + typedef typename component_type>::type component_number_type; + component_number_type x(v1), y(v2); + assign_components(result, x.backend(), y.backend()); } template -inline void assign_components(T& result, const V& v1, const U& v2) -{ - return assign_components_imp(result, v1, v2, typename number_category::type()); +inline void assign_components(T &result, const V &v1, const U &v2) { + return assign_components_imp(result, v1, v2, + typename number_category::type()); } #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW template -inline void assign_from_string_view(Result& result, const std::basic_string_view& view) -{ - // since most (all?) backends require a const char* to construct from, we just - // convert to that: - std::string s(view); - result = s.c_str(); +inline void +assign_from_string_view(Result &result, + const std::basic_string_view &view) { + // since most (all?) backends require a const char* to construct from, we just + // convert to that: + std::string s(view); + result = s.c_str(); } template -inline void assign_from_string_view(Result& result, const std::basic_string_view& view_x, const std::basic_string_view& view_y) -{ - // since most (all?) backends require a const char* to construct from, we just - // convert to that: - std::string x(view_x), y(view_y); - assign_components(result, x.c_str(), y.c_str()); +inline void +assign_from_string_view(Result &result, + const std::basic_string_view &view_x, + const std::basic_string_view &view_y) { + // since most (all?) backends require a const char* to construct from, we just + // convert to that: + std::string x(view_x), y(view_y); + assign_components(result, x.c_str(), y.c_str()); } #endif -template -struct has_enough_bits -{ - template - struct type : public mpl::and_ >, mpl::bool_::digits >= b> >{}; +template struct has_enough_bits { + template + struct type + : public mpl::and_>, + mpl::bool_::digits >= b>> {}; }; -template -struct terminal -{ - terminal(const R& v) : value(v){} - terminal(){} - terminal& operator = (R val) { value = val; return *this; } - R value; - operator R()const { return value; } +template struct terminal { + terminal(const R &v) : value(v) {} + terminal() {} + terminal &operator=(R val) { + value = val; + return *this; + } + R value; + operator R() const { return value; } }; -template -struct calculate_next_larger_type -{ - // Find which list we're looking through: - typedef typename mpl::if_< - is_signed, - typename B::signed_types, - typename mpl::if_< - is_unsigned, - typename B::unsigned_types, - typename B::float_types - >::type - >::type list_type; - // A predicate to find a type with enough bits: - typedef typename has_enough_bits::digits>::template type pred_type; - // See if the last type is in the list, if so we have to start after this: - typedef typename mpl::find_if< - list_type, - is_same - >::type start_last; - // Where we're starting from, either the start of the sequence or the last type found: - typedef typename mpl::if_::type>, typename mpl::begin::type, start_last>::type start_seq; - // The range we're searching: - typedef mpl::iterator_range::type> range; - // Find the next type: - typedef typename mpl::find_if< - range, - pred_type - >::type iter_type; - // Either the next type, or a "terminal" to indicate we've run out of types to search: - typedef typename mpl::eval_if< +template struct calculate_next_larger_type { + // Find which list we're looking through: + typedef typename mpl::if_< + is_signed, typename B::signed_types, + typename mpl::if_, typename B::unsigned_types, + typename B::float_types>::type>::type list_type; + // A predicate to find a type with enough bits: + typedef typename has_enough_bits< + R, std::numeric_limits::digits>::template type + pred_type; + // See if the last type is in the list, if so we have to start after this: + typedef typename mpl::find_if>::type start_last; + // Where we're starting from, either the start of the sequence or the last + // type found: + typedef + typename mpl::if_::type>, + typename mpl::begin::type, start_last>::type + start_seq; + // The range we're searching: + typedef mpl::iterator_range::type> + range; + // Find the next type: + typedef typename mpl::find_if::type iter_type; + // Either the next type, or a "terminal" to indicate we've run out of types to + // search: + typedef typename mpl::eval_if< is_same::type, iter_type>, - mpl::identity >, - mpl::deref - >::type type; + mpl::identity>, mpl::deref>::type type; }; template -inline typename boost::enable_if_c::value, bool>::type check_in_range(const T& t) -{ - // Can t fit in an R? - if((t > 0) && std::numeric_limits::is_specialized && std::numeric_limits::is_bounded && (t > (std::numeric_limits::max)())) - return true; - else - return false; +inline typename boost::enable_if_c::value, bool>::type +check_in_range(const T &t) { + // Can t fit in an R? + if ((t > 0) && std::numeric_limits::is_specialized && + std::numeric_limits::is_bounded && + (t > (std::numeric_limits::max)())) + return true; + else + return false; } template -inline typename boost::enable_if_c::value>::type eval_convert_to(R* result, const B& backend) -{ - typedef typename calculate_next_larger_type::type next_type; - next_type n; - eval_convert_to(&n, backend); - if(!boost::is_unsigned::value && std::numeric_limits::is_specialized && std::numeric_limits::is_bounded && (n > (next_type)(std::numeric_limits::max)())) - { - *result = (std::numeric_limits::max)(); - } - else if (std::numeric_limits::is_specialized && std::numeric_limits::is_bounded && (n < (next_type)(std::numeric_limits::min)())) - { - *result = (std::numeric_limits::min)(); - } - else - *result = static_cast(n); +inline typename boost::enable_if_c::value>::type +eval_convert_to(R *result, const B &backend) { + typedef typename calculate_next_larger_type::type next_type; + next_type n; + eval_convert_to(&n, backend); + if (!boost::is_unsigned::value && std::numeric_limits::is_specialized && + std::numeric_limits::is_bounded && + (n > (next_type)(std::numeric_limits::max)())) { + *result = (std::numeric_limits::max)(); + } else if (std::numeric_limits::is_specialized && + std::numeric_limits::is_bounded && + (n < (next_type)(std::numeric_limits::min)())) { + *result = (std::numeric_limits::min)(); + } else + *result = static_cast(n); } template -inline typename boost::disable_if_c::value>::type eval_convert_to(R* result, const B& backend) -{ - typedef typename calculate_next_larger_type::type next_type; - next_type n; - eval_convert_to(&n, backend); - if(std::numeric_limits::is_specialized && std::numeric_limits::is_bounded && ((n > (next_type)(std::numeric_limits::max)() || (n < (next_type)-(std::numeric_limits::max)()) ))) - { - *result = n > 0 ? (std::numeric_limits::max)() : -(std::numeric_limits::max)(); - } - else - *result = static_cast(n); +inline typename boost::disable_if_c::value>::type +eval_convert_to(R *result, const B &backend) { + typedef typename calculate_next_larger_type::type next_type; + next_type n; + eval_convert_to(&n, backend); + if (std::numeric_limits::is_specialized && + std::numeric_limits::is_bounded && + ((n > (next_type)(std::numeric_limits::max)() || + (n < (next_type) - (std::numeric_limits::max)())))) { + *result = n > 0 ? (std::numeric_limits::max)() + : -(std::numeric_limits::max)(); + } else + *result = static_cast(n); } template -inline void last_chance_eval_convert_to(terminal* result, const B& backend, const mpl::false_&) -{ - // - // We ran out of types to try for the conversion, try - // a lexical_cast and hope for the best: - // - if (std::numeric_limits::is_integer && !std::numeric_limits::is_signed && (eval_get_sign(backend) < 0)) - BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour")); - try - { - result->value = boost::lexical_cast(backend.str(0, std::ios_base::fmtflags(0))); - } - catch (const bad_lexical_cast&) - { - if (eval_get_sign(backend) < 0) - { - *result = std::numeric_limits::is_integer && std::numeric_limits::is_signed ? (std::numeric_limits::min)() : -(std::numeric_limits::max)(); - } - else - *result = (std::numeric_limits::max)(); - } +inline void last_chance_eval_convert_to(terminal *result, const B &backend, + const mpl::false_ &) { + // + // We ran out of types to try for the conversion, try + // a lexical_cast and hope for the best: + // + if (std::numeric_limits::is_integer && + !std::numeric_limits::is_signed && (eval_get_sign(backend) < 0)) + BOOST_THROW_EXCEPTION( + std::range_error("Attempt to convert negative value to an unsigned " + "integer results in undefined behaviour")); + try { + result->value = + boost::lexical_cast(backend.str(0, std::ios_base::fmtflags(0))); + } catch (const bad_lexical_cast &) { + if (eval_get_sign(backend) < 0) { + *result = std::numeric_limits::is_integer && + std::numeric_limits::is_signed + ? (std::numeric_limits::min)() + : -(std::numeric_limits::max)(); + } else + *result = (std::numeric_limits::max)(); + } } template -inline void last_chance_eval_convert_to(terminal* result, const B& backend, const mpl::true_&) -{ - // - // We ran out of types to try for the conversion, try - // a lexical_cast and hope for the best: - // - if (std::numeric_limits::is_integer && !std::numeric_limits::is_signed && (eval_get_sign(backend) < 0)) - BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour")); - try - { - B t(backend); - R mask = ~static_cast(0u); - eval_bitwise_and(t, mask); - result->value = boost::lexical_cast(t.str(0, std::ios_base::fmtflags(0))); - } - catch (const bad_lexical_cast&) - { - if (eval_get_sign(backend) < 0) - { - *result = std::numeric_limits::is_integer && std::numeric_limits::is_signed ? (std::numeric_limits::min)() : -(std::numeric_limits::max)(); - } - else - *result = (std::numeric_limits::max)(); - } +inline void last_chance_eval_convert_to(terminal *result, const B &backend, + const mpl::true_ &) { + // + // We ran out of types to try for the conversion, try + // a lexical_cast and hope for the best: + // + if (std::numeric_limits::is_integer && + !std::numeric_limits::is_signed && (eval_get_sign(backend) < 0)) + BOOST_THROW_EXCEPTION( + std::range_error("Attempt to convert negative value to an unsigned " + "integer results in undefined behaviour")); + try { + B t(backend); + R mask = ~static_cast(0u); + eval_bitwise_and(t, mask); + result->value = + boost::lexical_cast(t.str(0, std::ios_base::fmtflags(0))); + } catch (const bad_lexical_cast &) { + if (eval_get_sign(backend) < 0) { + *result = std::numeric_limits::is_integer && + std::numeric_limits::is_signed + ? (std::numeric_limits::min)() + : -(std::numeric_limits::max)(); + } else + *result = (std::numeric_limits::max)(); + } } template -inline void eval_convert_to(terminal* result, const B& backend) -{ - typedef mpl::bool_::value && number_category::value == number_kind_integer> tag_type; - last_chance_eval_convert_to(result, backend, tag_type()); +inline void eval_convert_to(terminal *result, const B &backend) { + typedef mpl::bool_::value && + number_category::value == number_kind_integer> + tag_type; + last_chance_eval_convert_to(result, backend, tag_type()); } template -inline void eval_convert_to(terminal >* result, const B2& backend) -{ - // - // We ran out of types to try for the conversion, try - // a generic conversion and hope for the best: - // - boost::multiprecision::detail::generic_interconvert(result->value.backend(), backend, number_category(), number_category()); +inline void eval_convert_to(terminal> *result, + const B2 &backend) { + // + // We ran out of types to try for the conversion, try + // a generic conversion and hope for the best: + // + boost::multiprecision::detail::generic_interconvert( + result->value.backend(), backend, number_category(), + number_category()); } template -inline void eval_convert_to(std::string* result, const B& backend) -{ - *result = backend.str(0, std::ios_base::fmtflags(0)); +inline void eval_convert_to(std::string *result, const B &backend) { + *result = backend.str(0, std::ios_base::fmtflags(0)); } template -inline void eval_convert_to(std::complex* result, const B& backend) -{ - typedef typename scalar_result_from_possible_complex >::type scalar_type; - scalar_type re, im; - eval_real(re.backend(), backend); - eval_imag(im.backend(), backend); - - *result = std::complex(re.template convert_to(), im.template convert_to()); +inline void eval_convert_to(std::complex *result, const B &backend) { + typedef typename scalar_result_from_possible_complex< + multiprecision::number>::type scalar_type; + scalar_type re, im; + eval_real(re.backend(), backend); + eval_imag(im.backend(), backend); + + *result = std::complex(re.template convert_to(), + im.template convert_to()); } template -inline void eval_convert_to(std::complex* result, const B& backend) -{ - typedef typename scalar_result_from_possible_complex >::type scalar_type; - scalar_type re, im; - eval_real(re.backend(), backend); - eval_imag(im.backend(), backend); - - *result = std::complex(re.template convert_to(), im.template convert_to()); +inline void eval_convert_to(std::complex *result, const B &backend) { + typedef typename scalar_result_from_possible_complex< + multiprecision::number>::type scalar_type; + scalar_type re, im; + eval_real(re.backend(), backend); + eval_imag(im.backend(), backend); + + *result = std::complex(re.template convert_to(), + im.template convert_to()); } template -inline void eval_convert_to(std::complex* result, const B& backend) -{ - typedef typename scalar_result_from_possible_complex >::type scalar_type; - scalar_type re, im; - eval_real(re.backend(), backend); - eval_imag(im.backend(), backend); - - *result = std::complex(re.template convert_to(), im.template convert_to()); +inline void eval_convert_to(std::complex *result, + const B &backend) { + typedef typename scalar_result_from_possible_complex< + multiprecision::number>::type scalar_type; + scalar_type re, im; + eval_real(re.backend(), backend); + eval_imag(im.backend(), backend); + + *result = std::complex(re.template convert_to(), + im.template convert_to()); } // // Functions: // -template -void eval_abs(T& result, const T& arg) -{ - typedef typename T::signed_types type_list; - typedef typename mpl::front::type front; - result = arg; - if(arg.compare(front(0)) < 0) - result.negate(); -} -template -void eval_fabs(T& result, const T& arg) -{ - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The fabs function is only valid for floating point types."); - typedef typename T::signed_types type_list; - typedef typename mpl::front::type front; - result = arg; - if(arg.compare(front(0)) < 0) - result.negate(); -} - -template -inline int eval_fpclassify(const Backend& arg) -{ - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types."); - return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL; -} +template void eval_abs(T &result, const T &arg) { + typedef typename T::signed_types type_list; + typedef typename mpl::front::type front; + result = arg; + if (arg.compare(front(0)) < 0) + result.negate(); +} +template void eval_fabs(T &result, const T &arg) { + BOOST_STATIC_ASSERT_MSG( + number_category::value == number_kind_floating_point, + "The fabs function is only valid for floating point types."); + typedef typename T::signed_types type_list; + typedef typename mpl::front::type front; + result = arg; + if (arg.compare(front(0)) < 0) + result.negate(); +} + +template inline int eval_fpclassify(const Backend &arg) { + BOOST_STATIC_ASSERT_MSG( + number_category::value == number_kind_floating_point, + "The fpclassify function is only valid for floating point types."); + return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL; +} + +template inline void eval_fmod(T &result, const T &a, const T &b) { + BOOST_STATIC_ASSERT_MSG( + number_category::value == number_kind_floating_point, + "The fmod function is only valid for floating point types."); + if ((&result == &a) || (&result == &b)) { + T temp; + eval_fmod(temp, a, b); + result = temp; + return; + } + switch (eval_fpclassify(a)) { + case FP_ZERO: + result = a; + return; + case FP_INFINITE: + case FP_NAN: + result = std::numeric_limits>::quiet_NaN().backend(); + errno = EDOM; + return; + } + switch (eval_fpclassify(b)) { + case FP_ZERO: + case FP_NAN: + result = std::numeric_limits>::quiet_NaN().backend(); + errno = EDOM; + return; + } + T n; + eval_divide(result, a, b); + if (eval_get_sign(result) < 0) + eval_ceil(n, result); + else + eval_floor(n, result); + eval_multiply(n, b); + eval_subtract(result, a, n); +} +template +inline typename enable_if, void>::type +eval_fmod(T &result, const T &x, const A &a) { + typedef typename boost::multiprecision::detail::canonical::type + canonical_type; + typedef typename mpl::if_, T, canonical_type>::type + cast_type; + cast_type c; + c = a; + eval_fmod(result, x, c); +} + +template +inline typename enable_if, void>::type +eval_fmod(T &result, const A &x, const T &a) { + typedef typename boost::multiprecision::detail::canonical::type + canonical_type; + typedef typename mpl::if_, T, canonical_type>::type + cast_type; + cast_type c; + c = x; + eval_fmod(result, c, a); +} + +template void eval_round(T &result, const T &a); template -inline void eval_fmod(T& result, const T& a, const T& b) -{ - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The fmod function is only valid for floating point types."); - if((&result == &a) || (&result == &b)) - { - T temp; - eval_fmod(temp, a, b); - result = temp; - return; - } - switch(eval_fpclassify(a)) - { - case FP_ZERO: - result = a; - return; - case FP_INFINITE: - case FP_NAN: - result = std::numeric_limits >::quiet_NaN().backend(); - errno = EDOM; - return; - } - switch(eval_fpclassify(b)) - { - case FP_ZERO: - case FP_NAN: - result = std::numeric_limits >::quiet_NaN().backend(); - errno = EDOM; - return; - } - T n; - eval_divide(result, a, b); - if(eval_get_sign(result) < 0) - eval_ceil(n, result); - else - eval_floor(n, result); - eval_multiply(n, b); - eval_subtract(result, a, n); -} -template -inline typename enable_if, void>::type eval_fmod(T& result, const T& x, const A& a) -{ - typedef typename boost::multiprecision::detail::canonical::type canonical_type; - typedef typename mpl::if_, T, canonical_type>::type cast_type; - cast_type c; - c = a; - eval_fmod(result, x, c); -} - -template -inline typename enable_if, void>::type eval_fmod(T& result, const A& x, const T& a) -{ - typedef typename boost::multiprecision::detail::canonical::type canonical_type; - typedef typename mpl::if_, T, canonical_type>::type cast_type; - cast_type c; - c = x; - eval_fmod(result, c, a); -} - -template -void eval_round(T& result, const T& a); - -template -inline void eval_remquo(T& result, const T& a, const T& b, int* pi) -{ - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The remquo function is only valid for floating point types."); - if((&result == &a) || (&result == &b)) - { - T temp; - eval_remquo(temp, a, b, pi); - result = temp; - return; - } - T n; - eval_divide(result, a, b); - eval_round(n, result); - eval_convert_to(pi, n); - eval_multiply(n, b); - eval_subtract(result, a, n); -} -template -inline typename enable_if, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi) -{ - typedef typename boost::multiprecision::detail::canonical::type canonical_type; - typedef typename mpl::if_, T, canonical_type>::type cast_type; - cast_type c; - c = a; - eval_remquo(result, x, c, pi); -} -template -inline typename enable_if, void>::type eval_remquo(T& result, const A& x, const T& a, int* pi) -{ - typedef typename boost::multiprecision::detail::canonical::type canonical_type; - typedef typename mpl::if_, T, canonical_type>::type cast_type; - cast_type c; - c = x; - eval_remquo(result, c, a, pi); +inline void eval_remquo(T &result, const T &a, const T &b, int *pi) { + BOOST_STATIC_ASSERT_MSG( + number_category::value == number_kind_floating_point, + "The remquo function is only valid for floating point types."); + if ((&result == &a) || (&result == &b)) { + T temp; + eval_remquo(temp, a, b, pi); + result = temp; + return; + } + T n; + eval_divide(result, a, b); + eval_round(n, result); + eval_convert_to(pi, n); + eval_multiply(n, b); + eval_subtract(result, a, n); +} +template +inline typename enable_if, void>::type +eval_remquo(T &result, const T &x, const A &a, int *pi) { + typedef typename boost::multiprecision::detail::canonical::type + canonical_type; + typedef typename mpl::if_, T, canonical_type>::type + cast_type; + cast_type c; + c = a; + eval_remquo(result, x, c, pi); +} +template +inline typename enable_if, void>::type +eval_remquo(T &result, const A &x, const T &a, int *pi) { + typedef typename boost::multiprecision::detail::canonical::type + canonical_type; + typedef typename mpl::if_, T, canonical_type>::type + cast_type; + cast_type c; + c = x; + eval_remquo(result, c, a, pi); } template -inline void eval_remainder(T& result, const U& a, const V& b) -{ - int i; - eval_remquo(result, a, b, &i); -} - -template -bool eval_gt(const B& a, const B& b); -template -bool eval_gt(const T& a, const U& b); -template -bool eval_lt(const B& a, const B& b); -template -bool eval_lt(const T& a, const U& b); - -template -inline void eval_fdim(T& result, const T& a, const T& b) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - static const ui_type zero = 0u; - switch(eval_fpclassify(b)) - { - case FP_NAN: - case FP_INFINITE: - result = zero; - return; - } - switch(eval_fpclassify(a)) - { - case FP_NAN: - result = zero; - return; - case FP_INFINITE: - result = a; - return; - } - if(eval_gt(a, b)) - { - eval_subtract(result, a, b); - } - else - result = zero; -} - -template -inline typename boost::enable_if_c::value>::type eval_fdim(T& result, const T& a, const A& b) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - typedef typename boost::multiprecision::detail::canonical::type arithmetic_type; - static const ui_type zero = 0u; - arithmetic_type canonical_b = b; - switch((::boost::math::fpclassify)(b)) - { - case FP_NAN: - case FP_INFINITE: - result = zero; - return; - } - switch(eval_fpclassify(a)) - { - case FP_NAN: - result = zero; - return; - case FP_INFINITE: - result = a; - return; - } - if(eval_gt(a, canonical_b)) - { - eval_subtract(result, a, canonical_b); - } - else - result = zero; -} - -template -inline typename boost::enable_if_c::value>::type eval_fdim(T& result, const A& a, const T& b) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - typedef typename boost::multiprecision::detail::canonical::type arithmetic_type; - static const ui_type zero = 0u; - arithmetic_type canonical_a = a; - switch(eval_fpclassify(b)) - { - case FP_NAN: - case FP_INFINITE: - result = zero; - return; - } - switch((::boost::math::fpclassify)(a)) - { - case FP_NAN: - result = zero; - return; - case FP_INFINITE: - result = std::numeric_limits >::infinity().backend(); - return; - } - if(eval_gt(canonical_a, b)) - { - eval_subtract(result, canonical_a, b); - } - else - result = zero; -} - -template -inline void eval_trunc(T& result, const T& a) -{ - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The trunc function is only valid for floating point types."); - switch(eval_fpclassify(a)) - { - case FP_NAN: - errno = EDOM; - // fallthrough... - case FP_ZERO: - case FP_INFINITE: - result = a; - return; - } - if(eval_get_sign(a) < 0) - eval_ceil(result, a); - else - eval_floor(result, a); -} - -template -inline void eval_modf(T& result, T const& arg, T* pipart) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - int c = eval_fpclassify(arg); - if(c == (int)FP_NAN) - { - if(pipart) - *pipart = arg; - result = arg; - return; - } - else if(c == (int)FP_INFINITE) - { - if(pipart) - *pipart = arg; - result = ui_type(0u); - return; - } - if(pipart) - { - eval_trunc(*pipart, arg); - eval_subtract(result, arg, *pipart); - } - else - { - T ipart; - eval_trunc(ipart, arg); - eval_subtract(result, arg, ipart); - } -} - -template -inline void eval_round(T& result, const T& a) -{ - BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The round function is only valid for floating point types."); - typedef typename boost::multiprecision::detail::canonical::type fp_type; - int c = eval_fpclassify(a); - if(c == (int)FP_NAN) - { - result = a; - errno = EDOM; - return; - } - if((c == FP_ZERO) || (c == (int)FP_INFINITE)) - { - result = a; - } - else if(eval_get_sign(a) < 0) - { - eval_subtract(result, a, fp_type(0.5f)); - eval_ceil(result, result); - } - else - { - eval_add(result, a, fp_type(0.5f)); - eval_floor(result, result); - } -} - -template -void eval_lcm(B& result, const B& a, const B& b); -template -void eval_gcd(B& result, const B& a, const B& b); +inline void eval_remainder(T &result, const U &a, const V &b) { + int i; + eval_remquo(result, a, b, &i); +} + +template bool eval_gt(const B &a, const B &b); +template bool eval_gt(const T &a, const U &b); +template bool eval_lt(const B &a, const B &b); +template bool eval_lt(const T &a, const U &b); + +template inline void eval_fdim(T &result, const T &a, const T &b) { + typedef typename boost::multiprecision::detail::canonical::type + ui_type; + static const ui_type zero = 0u; + switch (eval_fpclassify(b)) { + case FP_NAN: + case FP_INFINITE: + result = zero; + return; + } + switch (eval_fpclassify(a)) { + case FP_NAN: + result = zero; + return; + case FP_INFINITE: + result = a; + return; + } + if (eval_gt(a, b)) { + eval_subtract(result, a, b); + } else + result = zero; +} + +template +inline typename boost::enable_if_c::value>::type +eval_fdim(T &result, const T &a, const A &b) { + typedef typename boost::multiprecision::detail::canonical::type + ui_type; + typedef typename boost::multiprecision::detail::canonical::type + arithmetic_type; + static const ui_type zero = 0u; + arithmetic_type canonical_b = b; + switch ((::boost::math::fpclassify)(b)) { + case FP_NAN: + case FP_INFINITE: + result = zero; + return; + } + switch (eval_fpclassify(a)) { + case FP_NAN: + result = zero; + return; + case FP_INFINITE: + result = a; + return; + } + if (eval_gt(a, canonical_b)) { + eval_subtract(result, a, canonical_b); + } else + result = zero; +} + +template +inline typename boost::enable_if_c::value>::type +eval_fdim(T &result, const A &a, const T &b) { + typedef typename boost::multiprecision::detail::canonical::type + ui_type; + typedef typename boost::multiprecision::detail::canonical::type + arithmetic_type; + static const ui_type zero = 0u; + arithmetic_type canonical_a = a; + switch (eval_fpclassify(b)) { + case FP_NAN: + case FP_INFINITE: + result = zero; + return; + } + switch ((::boost::math::fpclassify)(a)) { + case FP_NAN: + result = zero; + return; + case FP_INFINITE: + result = std::numeric_limits>::infinity().backend(); + return; + } + if (eval_gt(canonical_a, b)) { + eval_subtract(result, canonical_a, b); + } else + result = zero; +} + +template inline void eval_trunc(T &result, const T &a) { + BOOST_STATIC_ASSERT_MSG( + number_category::value == number_kind_floating_point, + "The trunc function is only valid for floating point types."); + switch (eval_fpclassify(a)) { + case FP_NAN: + errno = EDOM; + // fallthrough... + case FP_ZERO: + case FP_INFINITE: + result = a; + return; + } + if (eval_get_sign(a) < 0) + eval_ceil(result, a); + else + eval_floor(result, a); +} + +template inline void eval_modf(T &result, T const &arg, T *pipart) { + typedef typename boost::multiprecision::detail::canonical::type + ui_type; + int c = eval_fpclassify(arg); + if (c == (int)FP_NAN) { + if (pipart) + *pipart = arg; + result = arg; + return; + } else if (c == (int)FP_INFINITE) { + if (pipart) + *pipart = arg; + result = ui_type(0u); + return; + } + if (pipart) { + eval_trunc(*pipart, arg); + eval_subtract(result, arg, *pipart); + } else { + T ipart; + eval_trunc(ipart, arg); + eval_subtract(result, arg, ipart); + } +} + +template inline void eval_round(T &result, const T &a) { + BOOST_STATIC_ASSERT_MSG( + number_category::value == number_kind_floating_point, + "The round function is only valid for floating point types."); + typedef + typename boost::multiprecision::detail::canonical::type fp_type; + int c = eval_fpclassify(a); + if (c == (int)FP_NAN) { + result = a; + errno = EDOM; + return; + } + if ((c == FP_ZERO) || (c == (int)FP_INFINITE)) { + result = a; + } else if (eval_get_sign(a) < 0) { + eval_subtract(result, a, fp_type(0.5f)); + eval_ceil(result, result); + } else { + eval_add(result, a, fp_type(0.5f)); + eval_floor(result, result); + } +} + +template void eval_lcm(B &result, const B &a, const B &b); +template void eval_gcd(B &result, const B &a, const B &b); template -inline typename enable_if >::type eval_gcd(T& result, const T& a, const Arithmetic& b) -{ - typedef typename boost::multiprecision::detail::canonical::type si_type; - using default_ops::eval_gcd; - T t; - t = static_cast(b); - eval_gcd(result, a, t); +inline typename enable_if>::type +eval_gcd(T &result, const T &a, const Arithmetic &b) { + typedef typename boost::multiprecision::detail::canonical::type + si_type; + using default_ops::eval_gcd; + T t; + t = static_cast(b); + eval_gcd(result, a, t); } template -inline typename enable_if >::type eval_gcd(T& result, const Arithmetic& a, const T& b) -{ - eval_gcd(result, b, a); +inline typename enable_if>::type +eval_gcd(T &result, const Arithmetic &a, const T &b) { + eval_gcd(result, b, a); } template -inline typename enable_if >::type eval_lcm(T& result, const T& a, const Arithmetic& b) -{ - typedef typename boost::multiprecision::detail::canonical::type si_type; - using default_ops::eval_lcm; - T t; - t = static_cast(b); - eval_lcm(result, a, t); +inline typename enable_if>::type +eval_lcm(T &result, const T &a, const Arithmetic &b) { + typedef typename boost::multiprecision::detail::canonical::type + si_type; + using default_ops::eval_lcm; + T t; + t = static_cast(b); + eval_lcm(result, a, t); } template -inline typename enable_if >::type eval_lcm(T& result, const Arithmetic& a, const T& b) -{ - eval_lcm(result, b, a); -} - -template -inline unsigned eval_lsb(const T& val) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - int c = eval_get_sign(val); - if(c == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - if(c < 0) - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - unsigned result = 0; - T mask, t; - mask = ui_type(1); - do - { - eval_bitwise_and(t, mask, val); - ++result; - eval_left_shift(mask, 1); - } - while(eval_is_zero(t)); - - return --result; -} - -template -inline int eval_msb(const T& val) -{ - int c = eval_get_sign(val); - if(c == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - if(c < 0) - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - // - // This implementation is really really rubbish - it does - // a linear scan for the most-significant-bit. We should really - // do a binary search, but as none of our backends actually needs - // this implementation, we'll leave it for now. In fact for most - // backends it's likely that there will always be a more efficient - // native implementation possible. - // - unsigned result = 0; - T t(val); - while(!eval_is_zero(t)) - { - eval_right_shift(t, 1); - ++result; - } - return --result; -} - -template -inline bool eval_bit_test(const T& val, unsigned index) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - T mask, t; - mask = ui_type(1); - eval_left_shift(mask, index); - eval_bitwise_and(t, mask, val); - return !eval_is_zero(t); -} - -template -inline void eval_bit_set(T& val, unsigned index) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - T mask; - mask = ui_type(1); - eval_left_shift(mask, index); - eval_bitwise_or(val, mask); -} - -template -inline void eval_bit_flip(T& val, unsigned index) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - T mask; - mask = ui_type(1); - eval_left_shift(mask, index); - eval_bitwise_xor(val, mask); -} - -template -inline void eval_bit_unset(T& val, unsigned index) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - T mask, t; - mask = ui_type(1); - eval_left_shift(mask, index); - eval_bitwise_and(t, mask, val); - if(!eval_is_zero(t)) - eval_bitwise_xor(val, mask); -} - -template -void eval_integer_sqrt(B& s, B& r, const B& x) -{ - // - // This is slow bit-by-bit integer square root, see for example - // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29 - // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf - // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented - // at some point. - // - typedef typename boost::multiprecision::detail::canonical::type ui_type; - - s = ui_type(0u); - if(eval_get_sign(x) == 0) - { - r = ui_type(0u); - return; - } - int g = eval_msb(x); - if(g <= 1) - { - s = ui_type(1); - eval_subtract(r, x, s); - return; - } - - B t; - r = x; - g /= 2; - int org_g = g; - eval_bit_set(s, g); - eval_bit_set(t, 2 * g); - eval_subtract(r, x, t); - --g; - if(eval_get_sign(r) == 0) - return; - int msbr = eval_msb(r); - do - { - if(msbr >= org_g + g + 1) - { - t = s; - eval_left_shift(t, g + 1); - eval_bit_set(t, 2 * g); - if(t.compare(r) <= 0) - { - BOOST_ASSERT(g >= 0); - eval_bit_set(s, g); - eval_subtract(r, t); - if(eval_get_sign(r) == 0) - return; - msbr = eval_msb(r); - } +inline typename enable_if>::type +eval_lcm(T &result, const Arithmetic &a, const T &b) { + eval_lcm(result, b, a); +} + +template inline unsigned eval_lsb(const T &val) { + typedef typename boost::multiprecision::detail::canonical::type + ui_type; + int c = eval_get_sign(val); + if (c == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (c < 0) { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + unsigned result = 0; + T mask, t; + mask = ui_type(1); + do { + eval_bitwise_and(t, mask, val); + ++result; + eval_left_shift(mask, 1); + } while (eval_is_zero(t)); + + return --result; +} + +template inline int eval_msb(const T &val) { + int c = eval_get_sign(val); + if (c == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (c < 0) { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + // + // This implementation is really really rubbish - it does + // a linear scan for the most-significant-bit. We should really + // do a binary search, but as none of our backends actually needs + // this implementation, we'll leave it for now. In fact for most + // backends it's likely that there will always be a more efficient + // native implementation possible. + // + unsigned result = 0; + T t(val); + while (!eval_is_zero(t)) { + eval_right_shift(t, 1); + ++result; + } + return --result; +} + +template inline bool eval_bit_test(const T &val, unsigned index) { + typedef typename boost::multiprecision::detail::canonical::type + ui_type; + T mask, t; + mask = ui_type(1); + eval_left_shift(mask, index); + eval_bitwise_and(t, mask, val); + return !eval_is_zero(t); +} + +template inline void eval_bit_set(T &val, unsigned index) { + typedef typename boost::multiprecision::detail::canonical::type + ui_type; + T mask; + mask = ui_type(1); + eval_left_shift(mask, index); + eval_bitwise_or(val, mask); +} + +template inline void eval_bit_flip(T &val, unsigned index) { + typedef typename boost::multiprecision::detail::canonical::type + ui_type; + T mask; + mask = ui_type(1); + eval_left_shift(mask, index); + eval_bitwise_xor(val, mask); +} + +template inline void eval_bit_unset(T &val, unsigned index) { + typedef typename boost::multiprecision::detail::canonical::type + ui_type; + T mask, t; + mask = ui_type(1); + eval_left_shift(mask, index); + eval_bitwise_and(t, mask, val); + if (!eval_is_zero(t)) + eval_bitwise_xor(val, mask); +} + +template void eval_integer_sqrt(B &s, B &r, const B &x) { + // + // This is slow bit-by-bit integer square root, see for example + // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29 + // There are better methods such as + // http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf and + // http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be + // implemented at some point. + // + typedef + typename boost::multiprecision::detail::canonical::type + ui_type; + + s = ui_type(0u); + if (eval_get_sign(x) == 0) { + r = ui_type(0u); + return; + } + int g = eval_msb(x); + if (g <= 1) { + s = ui_type(1); + eval_subtract(r, x, s); + return; + } + + B t; + r = x; + g /= 2; + int org_g = g; + eval_bit_set(s, g); + eval_bit_set(t, 2 * g); + eval_subtract(r, x, t); + --g; + if (eval_get_sign(r) == 0) + return; + int msbr = eval_msb(r); + do { + if (msbr >= org_g + g + 1) { + t = s; + eval_left_shift(t, g + 1); + eval_bit_set(t, 2 * g); + if (t.compare(r) <= 0) { + BOOST_ASSERT(g >= 0); + eval_bit_set(s, g); + eval_subtract(r, t); + if (eval_get_sign(r) == 0) + return; + msbr = eval_msb(r); } - --g; - } - while(g >= 0); + } + --g; + } while (g >= 0); } -template -inline void eval_conj(B& result, const B& val) -{ - result = val; // assume non-complex result. +template inline void eval_conj(B &result, const B &val) { + result = val; // assume non-complex result. } -template -inline void eval_proj(B& result, const B& val) -{ - result = val; // assume non-complex result. +template inline void eval_proj(B &result, const B &val) { + result = val; // assume non-complex result. } // -// These have to implemented by the backend, declared here so that our macro generated code compiles OK. +// These have to implemented by the backend, declared here so that our macro +// generated code compiles OK. // -template -typename enable_if_c::type eval_floor(); -template -typename enable_if_c::type eval_ceil(); -template -typename enable_if_c::type eval_trunc(); -template -typename enable_if_c::type eval_sqrt(); -template -typename enable_if_c::type eval_ldexp(); -template -typename enable_if_c::type eval_frexp(); +template typename enable_if_c::type eval_floor(); +template typename enable_if_c::type eval_ceil(); +template typename enable_if_c::type eval_trunc(); +template typename enable_if_c::type eval_sqrt(); +template typename enable_if_c::type eval_ldexp(); +template typename enable_if_c::type eval_frexp(); // TODO implement default versions of these: -template -typename enable_if_c::type eval_asinh(); -template -typename enable_if_c::type eval_acosh(); -template -typename enable_if_c::type eval_atanh(); +template typename enable_if_c::type eval_asinh(); +template typename enable_if_c::type eval_acosh(); +template typename enable_if_c::type eval_atanh(); // // eval_logb and eval_scalbn simply assume base 2 and forward to // eval_ldexp and eval_frexp: // -template -inline typename B::exponent_type eval_ilogb(const B& val) -{ - BOOST_STATIC_ASSERT_MSG(!std::numeric_limits >::is_specialized || (std::numeric_limits >::radix == 2), "The default implementation of ilogb requires a base 2 number type"); - typename B::exponent_type e; - switch(eval_fpclassify(val)) - { - case FP_NAN: +template inline typename B::exponent_type eval_ilogb(const B &val) { + BOOST_STATIC_ASSERT_MSG( + !std::numeric_limits>::is_specialized || + (std::numeric_limits>::radix == 2), + "The default implementation of ilogb requires a base 2 number type"); + typename B::exponent_type e; + switch (eval_fpclassify(val)) { + case FP_NAN: #ifdef FP_ILOGBNAN - return FP_ILOGBNAN > 0 ? (std::numeric_limits::max)() : (std::numeric_limits::min)(); + return FP_ILOGBNAN > 0 + ? (std::numeric_limits::max)() + : (std::numeric_limits::min)(); #else - return (std::numeric_limits::max)(); + return (std::numeric_limits::max)(); #endif - case FP_INFINITE: - return (std::numeric_limits::max)(); - case FP_ZERO: - return (std::numeric_limits::min)(); - } - B result; - eval_frexp(result, val, &e); - return e - 1; -} - -template -int eval_signbit(const T& val); - -template -inline void eval_logb(B& result, const B& val) -{ - switch(eval_fpclassify(val)) - { - case FP_NAN: - result = val; - errno = EDOM; - return; - case FP_ZERO: - result = std::numeric_limits >::infinity().backend(); + case FP_INFINITE: + return (std::numeric_limits::max)(); + case FP_ZERO: + return (std::numeric_limits::min)(); + } + B result; + eval_frexp(result, val, &e); + return e - 1; +} + +template int eval_signbit(const T &val); + +template inline void eval_logb(B &result, const B &val) { + switch (eval_fpclassify(val)) { + case FP_NAN: + result = val; + errno = EDOM; + return; + case FP_ZERO: + result = std::numeric_limits>::infinity().backend(); + result.negate(); + errno = ERANGE; + return; + case FP_INFINITE: + result = val; + if (eval_signbit(val)) result.negate(); - errno = ERANGE; - return; - case FP_INFINITE: - result = val; - if(eval_signbit(val)) - result.negate(); - return; - } - typedef typename boost::mpl::if_c::value, boost::long_long_type, boost::intmax_t>::type max_t; - result = static_cast(eval_ilogb(val)); + return; + } + typedef + typename boost::mpl::if_c::value, + boost::long_long_type, boost::intmax_t>::type + max_t; + result = static_cast(eval_ilogb(val)); } template -inline void eval_scalbn(B& result, const B& val, A e) -{ - BOOST_STATIC_ASSERT_MSG(!std::numeric_limits >::is_specialized || (std::numeric_limits >::radix == 2), "The default implementation of scalbn requires a base 2 number type"); - eval_ldexp(result, val, static_cast(e)); +inline void eval_scalbn(B &result, const B &val, A e) { + BOOST_STATIC_ASSERT_MSG( + !std::numeric_limits>::is_specialized || + (std::numeric_limits>::radix == 2), + "The default implementation of scalbn requires a base 2 number type"); + eval_ldexp(result, val, static_cast(e)); } template -inline void eval_scalbln(B& result, const B& val, A e) -{ - eval_scalbn(result, val, e); +inline void eval_scalbln(B &result, const B &val, A e) { + eval_scalbn(result, val, e); } template -inline bool is_arg_nan(const T& val, mpl::true_ const&, const mpl::false_&) -{ - return eval_fpclassify(val) == FP_NAN; +inline bool is_arg_nan(const T &val, mpl::true_ const &, const mpl::false_ &) { + return eval_fpclassify(val) == FP_NAN; } template -inline bool is_arg_nan(const T& val, mpl::false_ const&, const mpl::true_&) -{ - return (boost::math::isnan)(val); +inline bool is_arg_nan(const T &val, mpl::false_ const &, const mpl::true_ &) { + return (boost::math::isnan)(val); } template -inline bool is_arg_nan(const T&, mpl::false_ const&, const mpl::false_&) -{ - return false; +inline bool is_arg_nan(const T &, mpl::false_ const &, const mpl::false_ &) { + return false; } -template -inline bool is_arg_nan(const T& val) -{ - return is_arg_nan(val, mpl::bool_::value>(), is_floating_point()); +template inline bool is_arg_nan(const T &val) { + return is_arg_nan( + val, mpl::bool_::value>(), + is_floating_point()); } template -inline void eval_fmax(T& result, const U& a, const V& b) -{ - if(is_arg_nan(a)) - result = number::canonical_value(b); - else if(is_arg_nan(b)) - result = number::canonical_value(a); - else if(eval_lt(number::canonical_value(a), number::canonical_value(b))) - result = number::canonical_value(b); - else - result = number::canonical_value(a); +inline void eval_fmax(T &result, const U &a, const V &b) { + if (is_arg_nan(a)) + result = number::canonical_value(b); + else if (is_arg_nan(b)) + result = number::canonical_value(a); + else if (eval_lt(number::canonical_value(a), + number::canonical_value(b))) + result = number::canonical_value(b); + else + result = number::canonical_value(a); } template -inline void eval_fmin(T& result, const U& a, const V& b) -{ - if(is_arg_nan(a)) - result = number::canonical_value(b); - else if(is_arg_nan(b)) - result = number::canonical_value(a); - else if(eval_lt(number::canonical_value(a), number::canonical_value(b))) - result = number::canonical_value(a); - else - result = number::canonical_value(b); +inline void eval_fmin(T &result, const U &a, const V &b) { + if (is_arg_nan(a)) + result = number::canonical_value(b); + else if (is_arg_nan(b)) + result = number::canonical_value(a); + else if (eval_lt(number::canonical_value(a), + number::canonical_value(b))) + result = number::canonical_value(a); + else + result = number::canonical_value(b); } template -inline void eval_hypot(R& result, const T& a, const U& b) -{ - // - // Normalize x and y, so that both are positive and x >= y: - // - R x, y; - x = number::canonical_value(a); - y = number::canonical_value(b); - if(eval_get_sign(x) < 0) - x.negate(); - if(eval_get_sign(y) < 0) - y.negate(); - - // Special case, see C99 Annex F. - // The order of the if's is important: do not change! - int c1 = eval_fpclassify(x); - int c2 = eval_fpclassify(y); - - if(c1 == FP_ZERO) - { - result = y; - return; - } - if(c2 == FP_ZERO) - { - result = x; - return; - } - if(c1 == FP_INFINITE) - { - result = x; - return; - } - if((c2 == FP_INFINITE) || (c2 == FP_NAN)) - { - result = y; - return; - } - if(c1 == FP_NAN) - { - result = x; - return; - } - - if(eval_gt(y, x)) - x.swap(y); - - eval_multiply(result, x, std::numeric_limits >::epsilon().backend()); - - if(eval_gt(result, y)) - { - result = x; - return; - } - - R rat; - eval_divide(rat, y, x); - eval_multiply(result, rat, rat); - eval_increment(result); - eval_sqrt(rat, result); - eval_multiply(result, rat, x); -} - -template -inline void eval_nearbyint(R& result, const T& a) -{ - eval_round(result, a); -} -template -inline void eval_rint(R& result, const T& a) -{ - eval_nearbyint(result, a); -} - -template -inline int eval_signbit(const T& val) -{ - return eval_get_sign(val) < 0 ? 1 : 0; +inline void eval_hypot(R &result, const T &a, const U &b) { + // + // Normalize x and y, so that both are positive and x >= y: + // + R x, y; + x = number::canonical_value(a); + y = number::canonical_value(b); + if (eval_get_sign(x) < 0) + x.negate(); + if (eval_get_sign(y) < 0) + y.negate(); + + // Special case, see C99 Annex F. + // The order of the if's is important: do not change! + int c1 = eval_fpclassify(x); + int c2 = eval_fpclassify(y); + + if (c1 == FP_ZERO) { + result = y; + return; + } + if (c2 == FP_ZERO) { + result = x; + return; + } + if (c1 == FP_INFINITE) { + result = x; + return; + } + if ((c2 == FP_INFINITE) || (c2 == FP_NAN)) { + result = y; + return; + } + if (c1 == FP_NAN) { + result = x; + return; + } + + if (eval_gt(y, x)) + x.swap(y); + + eval_multiply(result, x, std::numeric_limits>::epsilon().backend()); + + if (eval_gt(result, y)) { + result = x; + return; + } + + R rat; + eval_divide(rat, y, x); + eval_multiply(result, rat, rat); + eval_increment(result); + eval_sqrt(rat, result); + eval_multiply(result, rat, x); +} + +template inline void eval_nearbyint(R &result, const T &a) { + eval_round(result, a); +} +template inline void eval_rint(R &result, const T &a) { + eval_nearbyint(result, a); +} + +template inline int eval_signbit(const T &val) { + return eval_get_sign(val) < 0 ? 1 : 0; } // // Real and imaginary parts: // template -inline void eval_real(To& to, const From& from) -{ - to = from; +inline void eval_real(To &to, const From &from) { + to = from; } -template -inline void eval_imag(To& to, const From& ) -{ - typedef typename mpl::front::type ui_type; - to = ui_type(0); +template inline void eval_imag(To &to, const From &) { + typedef typename mpl::front::type ui_type; + to = ui_type(0); } -} namespace default_ops_adl { +} // namespace default_ops +namespace default_ops_adl { template -inline void eval_set_real_imp(To& to, const From& from) -{ - typedef typename component_type >::type to_component_type; - typename to_component_type::backend_type to_component; - to_component = from; - eval_set_real(to, to_component); +inline void eval_set_real_imp(To &to, const From &from) { + typedef typename component_type>::type to_component_type; + typename to_component_type::backend_type to_component; + to_component = from; + eval_set_real(to, to_component); } template -inline void eval_set_imag_imp(To& to, const From& from) -{ - typedef typename component_type >::type to_component_type; - typename to_component_type::backend_type to_component; - to_component = from; - eval_set_imag(to, to_component); +inline void eval_set_imag_imp(To &to, const From &from) { + typedef typename component_type>::type to_component_type; + typename to_component_type::backend_type to_component; + to_component = from; + eval_set_imag(to, to_component); } -} namespace default_ops{ +} // namespace default_ops_adl +namespace default_ops { template -inline typename enable_if_c::value == number_kind_complex>::type eval_set_real(To& to, const From& from) -{ - default_ops_adl::eval_set_real_imp(to, from); +inline typename enable_if_c::value == + number_kind_complex>::type +eval_set_real(To &to, const From &from) { + default_ops_adl::eval_set_real_imp(to, from); } template -inline typename disable_if_c::value == number_kind_complex>::type eval_set_real(To& to, const From& from) -{ - to = from; +inline typename disable_if_c::value == + number_kind_complex>::type +eval_set_real(To &to, const From &from) { + to = from; } template -inline void eval_set_imag(To& to, const From& from) -{ - default_ops_adl::eval_set_imag_imp(to, from); +inline void eval_set_imag(To &to, const From &from) { + default_ops_adl::eval_set_imag_imp(to, from); } -template -inline void eval_set_real(T& to, const T& from) -{ - to = from; +template inline void eval_set_real(T &to, const T &from) { + to = from; } -template -void eval_set_imag(T&, const T&) -{ - BOOST_STATIC_ASSERT_MSG(sizeof(T) == INT_MAX, "eval_set_imag needs to be specialised for each specific backend"); +template void eval_set_imag(T &, const T &) { + BOOST_STATIC_ASSERT_MSG( + sizeof(T) == INT_MAX, + "eval_set_imag needs to be specialised for each specific backend"); } // @@ -1883,806 +1759,1121 @@ void eval_set_imag(T&, const T&) #include #include -} +} // namespace default_ops // // Default versions of floating point classification routines: // -template -inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) -{ - using multiprecision::default_ops::eval_fpclassify; - return eval_fpclassify(arg.backend()); +template +inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + using multiprecision::default_ops::eval_fpclassify; + return eval_fpclassify(arg.backend()); } template -inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); -} -template -inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) -{ - int v = fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg); - return (v != (int)FP_INFINITE) && (v != (int)FP_NAN); +inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); +} +template +inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + int v = fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg); + return (v != (int)FP_INFINITE) && (v != (int)FP_NAN); } template -inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); -} -template -inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) -{ - return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NAN; +inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); +} +template +inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NAN; } template -inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); -} -template -inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) -{ - return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_INFINITE; +inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); +} +template +inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_INFINITE; } template -inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); -} -template -inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) -{ - return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NORMAL; +inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); +} +template +inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NORMAL; } template -inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); +inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); } -// Default versions of sign manipulation functions, if individual backends can do better than this -// (for example with signed zero), then they should overload these functions further: +// Default versions of sign manipulation functions, if individual backends can +// do better than this (for example with signed zero), then they should overload +// these functions further: -template -inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) -{ - return arg.sign(); +template +inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + return arg.sign(); } template -inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); +inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); } -template -inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) -{ - using default_ops::eval_signbit; - return eval_signbit(arg.backend()); +template +inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + using default_ops::eval_signbit; + return eval_signbit(arg.backend()); } template -inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - return signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); -} -template -inline multiprecision::number changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) -{ - return -arg; +inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + return signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); +} +template +inline multiprecision::number + changesign BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + return -arg; } template -inline typename multiprecision::detail::expression::result_type changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - return changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); -} -template -inline multiprecision::number copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& a, const multiprecision::number& b) -{ - return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? (boost::multiprecision::changesign)(a) : a; -} -template -inline multiprecision::number copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& a, const multiprecision::detail::expression& b) -{ - return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number(b)); -} -template -inline multiprecision::number copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& a, const multiprecision::number& b) -{ - return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number(a), b); -} -template -inline typename multiprecision::detail::expression::result_type copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& a, const multiprecision::detail::expression& b) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b)); +inline typename multiprecision::detail::expression::result_type changesign +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + return changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)); +} +template +inline multiprecision::number + copysign BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &a, + const multiprecision::number &b) { + return (boost::multiprecision::signbit)(a) != + (boost::multiprecision::signbit)(b) + ? (boost::multiprecision::changesign)(a) + : a; +} +template +inline multiprecision::number + copysign BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &a, + const multiprecision::detail::expression &b) { + return copysign BOOST_PREVENT_MACRO_SUBSTITUTION( + a, multiprecision::number(b)); +} +template +inline multiprecision::number + copysign BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &a, + const multiprecision::number &b) { + return copysign BOOST_PREVENT_MACRO_SUBSTITUTION( + multiprecision::number(a), b); +} +template +inline typename multiprecision::detail::expression::result_type copysign +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &a, + const multiprecision::detail::expression &b) { + typedef + typename multiprecision::detail::expression::result_type value_type; + return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), + value_type(b)); } // // real and imag: // -template -inline typename scalar_result_from_possible_complex >::type - real(const multiprecision::number& a) -{ - using default_ops::eval_real; - typedef typename scalar_result_from_possible_complex >::type result_type; - boost::multiprecision::detail::scoped_default_precision precision_guard(a); - result_type result; - eval_real(result.backend(), a.backend()); - return result; -} -template -inline typename scalar_result_from_possible_complex >::type - imag(const multiprecision::number& a) -{ - using default_ops::eval_imag; - typedef typename scalar_result_from_possible_complex >::type result_type; - boost::multiprecision::detail::scoped_default_precision precision_guard(a); - result_type result; - eval_imag(result.backend(), a.backend()); - return result; +template +inline typename scalar_result_from_possible_complex< + multiprecision::number>::type +real(const multiprecision::number &a) { + using default_ops::eval_real; + typedef typename scalar_result_from_possible_complex< + multiprecision::number>::type result_type; + boost::multiprecision::detail::scoped_default_precision + precision_guard(a); + result_type result; + eval_real(result.backend(), a.backend()); + return result; +} +template +inline typename scalar_result_from_possible_complex< + multiprecision::number>::type +imag(const multiprecision::number &a) { + using default_ops::eval_imag; + typedef typename scalar_result_from_possible_complex< + multiprecision::number>::type result_type; + boost::multiprecision::detail::scoped_default_precision + precision_guard(a); + result_type result; + eval_imag(result.backend(), a.backend()); + return result; } template -inline typename scalar_result_from_possible_complex::result_type>::type - real(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return real(value_type(arg)); +inline typename scalar_result_from_possible_complex< + typename multiprecision::detail::expression::result_type>::type +real(const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return real(value_type(arg)); } template -inline typename scalar_result_from_possible_complex::result_type>::type - imag(const multiprecision::detail::expression& arg) -{ - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return imag(value_type(arg)); +inline typename scalar_result_from_possible_complex< + typename multiprecision::detail::expression::result_type>::type +imag(const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return imag(value_type(arg)); } // -// Complex number functions, these are overloaded at the Backend level, we just provide the -// expression template versions here, plus overloads for non-complex types: +// Complex number functions, these are overloaded at the Backend level, we just +// provide the expression template versions here, plus overloads for non-complex +// types: // template -inline typename boost::lazy_enable_if_c::value == number_kind_complex, component_type > >::type - abs(const number& v) -{ - return BOOST_MP_MOVE(boost::math::hypot(real(v), imag(v))); +inline typename boost::lazy_enable_if_c< + number_category::value == number_kind_complex, + component_type>>::type +abs(const number &v) { + return BOOST_MP_MOVE(boost::math::hypot(real(v), imag(v))); } template -inline typename boost::lazy_enable_if_c::result_type>::value == number_kind_complex, component_type::result_type> >::type - abs(const detail::expression& v) -{ - typedef typename detail::expression::result_type number_type; - return BOOST_MP_MOVE(abs(static_cast(v))); +inline typename boost::lazy_enable_if_c< + number_category::result_type>::value == number_kind_complex, + component_type< + typename detail::expression::result_type>>::type +abs(const detail::expression &v) { + typedef + typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(abs(static_cast(v))); } template -inline typename enable_if_c::value == number_kind_complex, typename scalar_result_from_possible_complex >::type>::type -arg(const number& v) -{ - return BOOST_MP_MOVE(atan2(imag(v), real(v))); +inline typename enable_if_c::value == number_kind_complex, + typename scalar_result_from_possible_complex< + number>::type>::type +arg(const number &v) { + return BOOST_MP_MOVE(atan2(imag(v), real(v))); } template -inline typename enable_if_c::value == number_kind_floating_point, typename scalar_result_from_possible_complex >::type>::type -arg(const number&) -{ - return 0; +inline typename enable_if_c::value == + number_kind_floating_point, + typename scalar_result_from_possible_complex< + number>::type>::type +arg(const number &) { + return 0; } template -inline typename enable_if_c::result_type>::value == number_kind_complex || number_category::result_type>::value == number_kind_floating_point, typename scalar_result_from_possible_complex::result_type>::type>::type -arg(const detail::expression& v) -{ - typedef typename detail::expression::result_type number_type; - return BOOST_MP_MOVE(arg(static_cast(v))); +inline typename enable_if_c< + number_category::result_type>::value == number_kind_complex || + number_category:: + result_type>::value == number_kind_floating_point, + typename scalar_result_from_possible_complex::result_type>::type>::type +arg(const detail::expression &v) { + typedef + typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(arg(static_cast(v))); } template -inline typename boost::lazy_enable_if_c::value == number_kind_complex, component_type > >::type -norm(const number& v) -{ - typename component_type >::type a(real(v)), b(imag(v)); - return BOOST_MP_MOVE(a * a + b * b); +inline typename boost::lazy_enable_if_c< + number_category::value == number_kind_complex, + component_type>>::type +norm(const number &v) { + typename component_type>::type a(real(v)), + b(imag(v)); + return BOOST_MP_MOVE(a * a + b * b); } template -inline typename boost::enable_if_c::value != number_kind_complex, typename scalar_result_from_possible_complex >::type >::type -norm(const number& v) -{ - return v * v; +inline + typename boost::enable_if_c::value != + number_kind_complex, + typename scalar_result_from_possible_complex< + number>::type>::type + norm(const number &v) { + return v * v; } template -inline typename scalar_result_from_possible_complex::result_type>::type -norm(const detail::expression& v) -{ - typedef typename detail::expression::result_type number_type; - return BOOST_MP_MOVE(norm(static_cast(v))); +inline typename scalar_result_from_possible_complex< + typename detail::expression::result_type>::type +norm(const detail::expression &v) { + typedef + typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(norm(static_cast(v))); } template -typename complex_result_from_scalar >::type polar(number const& r, number const& theta) -{ - return typename complex_result_from_scalar >::type(number(r * cos(theta)), number(r * sin(theta))); -} - -template -typename enable_if_c::result_type, number >::value, - typename complex_result_from_scalar >::type>::type - polar(detail::expression const& r, number const& theta) -{ - return typename complex_result_from_scalar >::type(number(r * cos(theta)), number(r * sin(theta))); -} - -template -typename enable_if_c::result_type, number >::value, - typename complex_result_from_scalar >::type>::type - polar(number const& r, detail::expression const& theta) -{ - return typename complex_result_from_scalar >::type(number(r * cos(theta)), number(r * sin(theta))); -} - -template -typename enable_if_c::result_type, typename detail::expression::result_type >::value, - typename complex_result_from_scalar::result_type >::type>::type - polar(detail::expression const& r, detail::expression const& theta) -{ - typedef typename detail::expression::result_type scalar_type; - return typename complex_result_from_scalar::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta))); +typename complex_result_from_scalar>::type +polar(number const &r, + number const &theta) { + return typename complex_result_from_scalar< + number>:: + type(number(r * cos(theta)), + number(r * sin(theta))); +} + +template +typename enable_if_c< + boost::is_same< + typename detail::expression::result_type, + number>::value, + typename complex_result_from_scalar< + number>::type>::type +polar(detail::expression const &r, + number const &theta) { + return typename complex_result_from_scalar< + number>:: + type(number(r * cos(theta)), + number(r * sin(theta))); +} + +template +typename enable_if_c< + boost::is_same< + typename detail::expression::result_type, + number>::value, + typename complex_result_from_scalar< + number>::type>::type +polar(number const &r, + detail::expression const &theta) { + return typename complex_result_from_scalar< + number>:: + type(number(r * cos(theta)), + number(r * sin(theta))); +} + +template +typename enable_if_c< + boost::is_same< + typename detail::expression::result_type, + typename detail::expression::result_type>::value, + typename complex_result_from_scalar::result_type>::type>::type +polar(detail::expression const &r, + detail::expression const &theta) { + typedef + typename detail::expression::result_type scalar_type; + return typename complex_result_from_scalar::type( + scalar_type(r * cos(theta)), scalar_type(r * sin(theta))); } // -// We also allow the first argument to polar to be an arithmetic type (probably a literal): +// We also allow the first argument to polar to be an arithmetic type (probably +// a literal): // -template -typename boost::enable_if_c::value, typename complex_result_from_scalar >::type>::type - polar(Scalar const& r, number const& theta) -{ - return typename complex_result_from_scalar >::type(number(r * cos(theta)), number(r * sin(theta))); +template +typename boost::enable_if_c::value, + typename complex_result_from_scalar>::type>::type +polar(Scalar const &r, number const &theta) { + return typename complex_result_from_scalar< + number>:: + type(number(r * cos(theta)), + number(r * sin(theta))); } template -typename enable_if_c::value, - typename complex_result_from_scalar::result_type>::type>::type - polar(Scalar const& r, detail::expression const& theta) -{ - typedef typename detail::expression::result_type scalar_type; - return typename complex_result_from_scalar::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta))); +typename enable_if_c< + boost::is_arithmetic::value, + typename complex_result_from_scalar::result_type>::type>::type +polar(Scalar const &r, detail::expression const &theta) { + typedef + typename detail::expression::result_type scalar_type; + return typename complex_result_from_scalar::type( + scalar_type(r * cos(theta)), scalar_type(r * sin(theta))); } // // Single argument overloads: // template -typename complex_result_from_scalar >::type polar(number const& r) -{ - return typename complex_result_from_scalar >::type(r); +typename complex_result_from_scalar>::type +polar(number const &r) { + return typename complex_result_from_scalar< + number>::type(r); } template -typename complex_result_from_scalar::result_type>::type - polar(detail::expression const& r) -{ - return typename complex_result_from_scalar::result_type>::type(r); +typename complex_result_from_scalar< + typename detail::expression::result_type>::type +polar(detail::expression const &r) { + return typename complex_result_from_scalar< + typename detail::expression::result_type>::type(r); } - - } // namespace multiprecision namespace math { - // - // Import Math functions here, so they can be found by Boost.Math: - // - using boost::multiprecision::signbit; - using boost::multiprecision::sign; - using boost::multiprecision::copysign; - using boost::multiprecision::changesign; - using boost::multiprecision::fpclassify; - using boost::multiprecision::isinf; - using boost::multiprecision::isnan; - using boost::multiprecision::isnormal; - using boost::multiprecision::isfinite; - -} - -namespace multiprecision{ - - typedef ::boost::math::policies::policy< - ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>, - ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>, - ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>, - ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>, - ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error> - > c99_error_policy; - - template - inline typename boost::enable_if_c::value != number_kind_complex, multiprecision::number >::type - asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - return boost::math::asinh(arg, c99_error_policy()); - } - template - inline typename boost::enable_if_c::result_type>::value != number_kind_complex, typename multiprecision::detail::expression::result_type>::type - asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return asinh(value_type(arg)); - } - template - inline typename boost::enable_if_c::value != number_kind_complex, multiprecision::number >::type - acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - return boost::math::acosh(arg, c99_error_policy()); - } - template - inline typename boost::enable_if_c::result_type>::value != number_kind_complex, typename multiprecision::detail::expression::result_type>::type - acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return acosh(value_type(arg)); - } - template - inline typename boost::enable_if_c::value != number_kind_complex, multiprecision::number >::type - atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - return boost::math::atanh(arg, c99_error_policy()); - } - template - inline typename boost::enable_if_c::result_type>::value != number_kind_complex, typename multiprecision::detail::expression::result_type>::type - atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return atanh(value_type(arg)); - } - template - inline multiprecision::number cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - return boost::math::cbrt(arg, c99_error_policy()); - } - template - inline typename multiprecision::detail::expression::result_type cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return cbrt(value_type(arg)); - } - template - inline multiprecision::number erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - return boost::math::erf(arg, c99_error_policy()); - } - template - inline typename multiprecision::detail::expression::result_type erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return erf(value_type(arg)); - } - template - inline multiprecision::number erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - return boost::math::erfc(arg, c99_error_policy()); - } - template - inline typename multiprecision::detail::expression::result_type erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return erfc(value_type(arg)); - } - template - inline multiprecision::number expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - return boost::math::expm1(arg, c99_error_policy()); - } - template - inline typename multiprecision::detail::expression::result_type expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return expm1(value_type(arg)); - } - template - inline multiprecision::number lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - multiprecision::number result; - result = boost::math::lgamma(arg, c99_error_policy()); - if((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg)) - { - result = std::numeric_limits >::infinity(); - errno = ERANGE; - } - return result; - } - template - inline typename multiprecision::detail::expression::result_type lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return lgamma(value_type(arg)); - } - template - inline multiprecision::number tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - if((arg == 0) && std::numeric_limits >::has_infinity) - { - errno = ERANGE; - return 1 / arg; - } - return boost::math::tgamma(arg, c99_error_policy()); - } - template - inline typename multiprecision::detail::expression::result_type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return tgamma(value_type(arg)); - } - - template - inline long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - return lround(arg); - } - template - inline long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - return lround(arg); - } +// +// Import Math functions here, so they can be found by Boost.Math: +// +using boost::multiprecision::changesign; +using boost::multiprecision::copysign; +using boost::multiprecision::fpclassify; +using boost::multiprecision::isfinite; +using boost::multiprecision::isinf; +using boost::multiprecision::isnan; +using boost::multiprecision::isnormal; +using boost::multiprecision::sign; +using boost::multiprecision::signbit; + +} // namespace math + +namespace multiprecision { + +typedef ::boost::math::policies::policy< + ::boost::math::policies::domain_error< + ::boost::math::policies::errno_on_error>, + ::boost::math::policies::pole_error< + ::boost::math::policies::errno_on_error>, + ::boost::math::policies::overflow_error< + ::boost::math::policies::errno_on_error>, + ::boost::math::policies::evaluation_error< + ::boost::math::policies::errno_on_error>, + ::boost::math::policies::rounding_error< + ::boost::math::policies::errno_on_error>> + c99_error_policy; + +template +inline typename boost::enable_if_c< + number_category::value != number_kind_complex, + multiprecision::number>::type asinh +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + return boost::math::asinh(arg, c99_error_policy()); +} +template +inline typename boost::enable_if_c< + number_category::result_type>::value != number_kind_complex, + typename multiprecision::detail::expression::result_type>::type asinh +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return asinh(value_type(arg)); +} +template +inline typename boost::enable_if_c< + number_category::value != number_kind_complex, + multiprecision::number>::type acosh +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + return boost::math::acosh(arg, c99_error_policy()); +} +template +inline typename boost::enable_if_c< + number_category::result_type>::value != number_kind_complex, + typename multiprecision::detail::expression::result_type>::type acosh +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return acosh(value_type(arg)); +} +template +inline typename boost::enable_if_c< + number_category::value != number_kind_complex, + multiprecision::number>::type atanh +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + return boost::math::atanh(arg, c99_error_policy()); +} +template +inline typename boost::enable_if_c< + number_category::result_type>::value != number_kind_complex, + typename multiprecision::detail::expression::result_type>::type atanh +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return atanh(value_type(arg)); +} +template +inline multiprecision::number + cbrt BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + return boost::math::cbrt(arg, c99_error_policy()); +} +template +inline typename multiprecision::detail::expression::result_type cbrt +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return cbrt(value_type(arg)); +} +template +inline multiprecision::number + erf BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + return boost::math::erf(arg, c99_error_policy()); +} +template +inline typename multiprecision::detail::expression::result_type erf +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return erf(value_type(arg)); +} +template +inline multiprecision::number + erfc BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + return boost::math::erfc(arg, c99_error_policy()); +} +template +inline typename multiprecision::detail::expression::result_type erfc +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return erfc(value_type(arg)); +} +template +inline multiprecision::number + expm1 BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + return boost::math::expm1(arg, c99_error_policy()); +} +template +inline typename multiprecision::detail::expression::result_type expm1 +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return expm1(value_type(arg)); +} +template +inline multiprecision::number + lgamma BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + multiprecision::number result; + result = boost::math::lgamma(arg, c99_error_policy()); + if ((boost::multiprecision::isnan)(result) && + !(boost::multiprecision::isnan)(arg)) { + result = std::numeric_limits< + multiprecision::number>::infinity(); + errno = ERANGE; + } + return result; +} +template +inline typename multiprecision::detail::expression::result_type lgamma +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return lgamma(value_type(arg)); +} +template +inline multiprecision::number + tgamma BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + if ((arg == 0) && + std::numeric_limits< + multiprecision::number>::has_infinity) { + errno = ERANGE; + return 1 / arg; + } + return boost::math::tgamma(arg, c99_error_policy()); +} +template +inline typename multiprecision::detail::expression::result_type tgamma +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return tgamma(value_type(arg)); +} + +template +inline long lrint BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + return lround(arg); +} +template +inline long lrint BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + return lround(arg); +} #ifndef BOOST_NO_LONG_LONG - template - inline boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - return llround(arg); - } - template - inline boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - return llround(arg); - } +template +inline boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + return llround(arg); +} +template +inline boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + return llround(arg); +} #endif - template - inline multiprecision::number log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) - { - detail::scoped_default_precision > precision_guard(arg); - return boost::math::log1p(arg, c99_error_policy()); - } - template - inline typename multiprecision::detail::expression::result_type log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(arg); - return log1p(value_type(arg)); - } - - template - inline multiprecision::number nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& a, const multiprecision::number& b) - { - detail::scoped_default_precision > precision_guard(a, b); - return boost::math::nextafter(a, b, c99_error_policy()); - } - template - inline multiprecision::number nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& a, const multiprecision::detail::expression& b) - { - detail::scoped_default_precision > precision_guard(a, b); - return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number(b)); - } - template - inline multiprecision::number nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& a, const multiprecision::number& b) - { - detail::scoped_default_precision > precision_guard(a, b); - return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number(a), b); - } - template - inline typename multiprecision::detail::expression::result_type nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& a, const multiprecision::detail::expression& b) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(a, b); - return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b)); - } - template - inline multiprecision::number nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& a, const multiprecision::number& b) - { - detail::scoped_default_precision > precision_guard(a, b); - return boost::math::nextafter(a, b, c99_error_policy()); - } - template - inline multiprecision::number nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& a, const multiprecision::detail::expression& b) - { - detail::scoped_default_precision > precision_guard(a, b); - return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number(b)); - } - template - inline multiprecision::number nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& a, const multiprecision::number& b) - { - detail::scoped_default_precision > precision_guard(a, b); - return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number(a), b); - } - template - inline typename multiprecision::detail::expression::result_type nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& a, const multiprecision::detail::expression& b) - { - typedef typename multiprecision::detail::expression::result_type value_type; - detail::scoped_default_precision precision_guard(a, b); - return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b)); - } - -template -inline number& add(number& result, const number& a, const number& b) -{ - BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); - BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); - using default_ops::eval_add; - eval_add(result.backend(), a.backend(), b.backend()); - return result; -} - -template -inline number& subtract(number& result, const number& a, const number& b) -{ - BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); - BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); - using default_ops::eval_subtract; - eval_subtract(result.backend(), a.backend(), b.backend()); - return result; -} - -template -inline number& multiply(number& result, const number& a, const number& b) -{ - BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); - BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); - using default_ops::eval_multiply; - eval_multiply(result.backend(), a.backend(), b.backend()); - return result; +template +inline multiprecision::number + log1p BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &arg) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(arg); + return boost::math::log1p(arg, c99_error_policy()); +} +template +inline typename multiprecision::detail::expression::result_type log1p +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &arg) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(arg); + return log1p(value_type(arg)); +} + +template +inline multiprecision::number + nextafter BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &a, + const multiprecision::number &b) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(a, b); + return boost::math::nextafter(a, b, c99_error_policy()); +} +template +inline multiprecision::number + nextafter BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &a, + const multiprecision::detail::expression &b) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(a, b); + return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION( + a, multiprecision::number(b)); +} +template +inline multiprecision::number + nextafter BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &a, + const multiprecision::number &b) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(a, b); + return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION( + multiprecision::number(a), b); +} +template +inline typename multiprecision::detail::expression::result_type nextafter +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &a, + const multiprecision::detail::expression &b) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(a, b); + return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), + value_type(b)); +} +template +inline multiprecision::number + nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &a, + const multiprecision::number &b) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(a, b); + return boost::math::nextafter(a, b, c99_error_policy()); +} +template +inline multiprecision::number + nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::number &a, + const multiprecision::detail::expression &b) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(a, b); + return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION( + a, multiprecision::number(b)); +} +template +inline multiprecision::number + nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &a, + const multiprecision::number &b) { + detail::scoped_default_precision< + multiprecision::number> + precision_guard(a, b); + return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION( + multiprecision::number(a), b); +} +template +inline typename multiprecision::detail::expression::result_type nexttoward +BOOST_PREVENT_MACRO_SUBSTITUTION( + const multiprecision::detail::expression &a, + const multiprecision::detail::expression &b) { + typedef + typename multiprecision::detail::expression::result_type value_type; + detail::scoped_default_precision precision_guard(a, b); + return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), + value_type(b)); +} + +template +inline number &add(number &result, const number &a, + const number &b) { + BOOST_STATIC_ASSERT_MSG( + (is_convertible::value), + "No conversion to the target of a mixed precision addition exists"); + BOOST_STATIC_ASSERT_MSG( + (is_convertible::value), + "No conversion to the target of a mixed precision addition exists"); + using default_ops::eval_add; + eval_add(result.backend(), a.backend(), b.backend()); + return result; +} + +template +inline number &subtract(number &result, + const number &a, + const number &b) { + BOOST_STATIC_ASSERT_MSG( + (is_convertible::value), + "No conversion to the target of a mixed precision addition exists"); + BOOST_STATIC_ASSERT_MSG( + (is_convertible::value), + "No conversion to the target of a mixed precision addition exists"); + using default_ops::eval_subtract; + eval_subtract(result.backend(), a.backend(), b.backend()); + return result; +} + +template +inline number &multiply(number &result, + const number &a, + const number &b) { + BOOST_STATIC_ASSERT_MSG( + (is_convertible::value), + "No conversion to the target of a mixed precision addition exists"); + BOOST_STATIC_ASSERT_MSG( + (is_convertible::value), + "No conversion to the target of a mixed precision addition exists"); + using default_ops::eval_multiply; + eval_multiply(result.backend(), a.backend(), b.backend()); + return result; } template -inline typename enable_if_c::value, number&>::type - add(number& result, const I& a, const I& b) -{ - using default_ops::eval_add; - typedef typename detail::canonical::type canonical_type; - eval_add(result.backend(), static_cast(a), static_cast(b)); - return result; +inline typename enable_if_c::value, number &>::type +add(number &result, const I &a, const I &b) { + using default_ops::eval_add; + typedef typename detail::canonical::type canonical_type; + eval_add(result.backend(), static_cast(a), + static_cast(b)); + return result; } template -inline typename enable_if_c::value, number&>::type - subtract(number& result, const I& a, const I& b) -{ - using default_ops::eval_subtract; - typedef typename detail::canonical::type canonical_type; - eval_subtract(result.backend(), static_cast(a), static_cast(b)); - return result; +inline typename enable_if_c::value, number &>::type +subtract(number &result, const I &a, const I &b) { + using default_ops::eval_subtract; + typedef typename detail::canonical::type canonical_type; + eval_subtract(result.backend(), static_cast(a), + static_cast(b)); + return result; } template -inline typename enable_if_c::value, number&>::type - multiply(number& result, const I& a, const I& b) -{ - using default_ops::eval_multiply; - typedef typename detail::canonical::type canonical_type; - eval_multiply(result.backend(), static_cast(a), static_cast(b)); - return result; +inline typename enable_if_c::value, number &>::type +multiply(number &result, const I &a, const I &b) { + using default_ops::eval_multiply; + typedef typename detail::canonical::type canonical_type; + eval_multiply(result.backend(), static_cast(a), + static_cast(b)); + return result; } template -inline typename detail::expression::result_type trunc(const detail::expression& v, const Policy& pol) -{ - typedef typename detail::expression::result_type number_type; - return BOOST_MP_MOVE(trunc(number_type(v), pol)); -} - -template -inline number trunc(const number& v, const Policy&) -{ - using default_ops::eval_trunc; - detail::scoped_default_precision > precision_guard(v); - number result; - eval_trunc(result.backend(), v.backend()); - return BOOST_MP_MOVE(result); +inline typename detail::expression::result_type +trunc(const detail::expression &v, const Policy &pol) { + typedef + typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(trunc(number_type(v), pol)); +} + +template +inline number +trunc(const number &v, const Policy &) { + using default_ops::eval_trunc; + detail::scoped_default_precision< + multiprecision::number> + precision_guard(v); + number result; + eval_trunc(result.backend(), v.backend()); + return BOOST_MP_MOVE(result); } template -inline int itrunc(const detail::expression& v, const Policy& pol) -{ - typedef typename detail::expression::result_type number_type; - number_type r(trunc(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol); - return r.template convert_to(); +inline int itrunc(const detail::expression &v, + const Policy &pol) { + typedef + typename detail::expression::result_type number_type; + number_type r(trunc(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol); + return r.template convert_to(); } template -inline int itrunc(const detail::expression& v) -{ - return itrunc(v, boost::math::policies::policy<>()); -} -template -inline int itrunc(const number& v, const Policy& pol) -{ - number r(trunc(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol); - return r.template convert_to(); +inline int itrunc(const detail::expression &v) { + return itrunc(v, boost::math::policies::policy<>()); +} +template +inline int itrunc(const number &v, + const Policy &pol) { + number r(trunc(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol); + return r.template convert_to(); } template -inline int itrunc(const number& v) -{ - return itrunc(v, boost::math::policies::policy<>()); +inline int itrunc(const number &v) { + return itrunc(v, boost::math::policies::policy<>()); } template -inline long ltrunc(const detail::expression& v, const Policy& pol) -{ - typedef typename detail::expression::result_type number_type; - number_type r(trunc(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol); - return r.template convert_to(); +inline long ltrunc(const detail::expression &v, + const Policy &pol) { + typedef + typename detail::expression::result_type number_type; + number_type r(trunc(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol); + return r.template convert_to(); } template -inline long ltrunc(const detail::expression& v) -{ - return ltrunc(v, boost::math::policies::policy<>()); +inline long ltrunc(const detail::expression &v) { + return ltrunc(v, boost::math::policies::policy<>()); } template -inline long ltrunc(const number& v, const Policy& pol) -{ - number r(trunc(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol); - return r.template convert_to(); +inline long ltrunc(const number &v, const Policy &pol) { + number r(trunc(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol); + return r.template convert_to(); } template -inline long ltrunc(const number& v) -{ - return ltrunc(v, boost::math::policies::policy<>()); +inline long ltrunc(const number &v) { + return ltrunc(v, boost::math::policies::policy<>()); } #ifndef BOOST_NO_LONG_LONG template -inline boost::long_long_type lltrunc(const detail::expression& v, const Policy& pol) -{ - typedef typename detail::expression::result_type number_type; - number_type r(trunc(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol); - return r.template convert_to(); +inline boost::long_long_type +lltrunc(const detail::expression &v, const Policy &pol) { + typedef + typename detail::expression::result_type number_type; + number_type r(trunc(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || + !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, + pol); + return r.template convert_to(); } template -inline boost::long_long_type lltrunc(const detail::expression& v) -{ - return lltrunc(v, boost::math::policies::policy<>()); +inline boost::long_long_type +lltrunc(const detail::expression &v) { + return lltrunc(v, boost::math::policies::policy<>()); } template -inline boost::long_long_type lltrunc(const number& v, const Policy& pol) -{ - number r(trunc(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol); - return r.template convert_to(); +inline boost::long_long_type lltrunc(const number &v, + const Policy &pol) { + number r(trunc(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || + !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol); + return r.template convert_to(); } template -inline boost::long_long_type lltrunc(const number& v) -{ - return lltrunc(v, boost::math::policies::policy<>()); +inline boost::long_long_type lltrunc(const number &v) { + return lltrunc(v, boost::math::policies::policy<>()); } #endif template -inline typename detail::expression::result_type round(const detail::expression& v, const Policy& pol) -{ - typedef typename detail::expression::result_type number_type; - return BOOST_MP_MOVE(round(static_cast(v), pol)); +inline typename detail::expression::result_type +round(const detail::expression &v, const Policy &pol) { + typedef + typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(round(static_cast(v), pol)); } template -inline number round(const number& v, const Policy&) -{ - using default_ops::eval_round; - detail::scoped_default_precision > precision_guard(v); - number result; - eval_round(result.backend(), v.backend()); - return BOOST_MP_MOVE(result); +inline number +round(const number &v, const Policy &) { + using default_ops::eval_round; + detail::scoped_default_precision< + multiprecision::number> + precision_guard(v); + number result; + eval_round(result.backend(), v.backend()); + return BOOST_MP_MOVE(result); } template -inline int iround(const detail::expression& v, const Policy& pol) -{ - typedef typename detail::expression::result_type number_type; - number_type r(round(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol); - return r.template convert_to(); +inline int iround(const detail::expression &v, + const Policy &pol) { + typedef + typename detail::expression::result_type number_type; + number_type r(round(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol); + return r.template convert_to(); } template -inline int iround(const detail::expression& v) -{ - return iround(v, boost::math::policies::policy<>()); +inline int iround(const detail::expression &v) { + return iround(v, boost::math::policies::policy<>()); } template -inline int iround(const number& v, const Policy& pol) -{ - number r(round(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol); - return r.template convert_to(); +inline int iround(const number &v, const Policy &pol) { + number r(round(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol); + return r.template convert_to(); } template -inline int iround(const number& v) -{ - return iround(v, boost::math::policies::policy<>()); +inline int iround(const number &v) { + return iround(v, boost::math::policies::policy<>()); } template -inline long lround(const detail::expression& v, const Policy& pol) -{ - typedef typename detail::expression::result_type number_type; - number_type r(round(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol); - return r.template convert_to(); +inline long lround(const detail::expression &v, + const Policy &pol) { + typedef + typename detail::expression::result_type number_type; + number_type r(round(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol); + return r.template convert_to(); } template -inline long lround(const detail::expression& v) -{ - return lround(v, boost::math::policies::policy<>()); +inline long lround(const detail::expression &v) { + return lround(v, boost::math::policies::policy<>()); } template -inline long lround(const number& v, const Policy& pol) -{ - number r(round(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol); - return r.template convert_to(); +inline long lround(const number &v, const Policy &pol) { + number r(round(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol); + return r.template convert_to(); } template -inline long lround(const number& v) -{ - return lround(v, boost::math::policies::policy<>()); +inline long lround(const number &v) { + return lround(v, boost::math::policies::policy<>()); } #ifndef BOOST_NO_LONG_LONG template -inline boost::long_long_type llround(const detail::expression& v, const Policy& pol) -{ - typedef typename detail::expression::result_type number_type; - number_type r(round(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol); - return r.template convert_to(); +inline boost::long_long_type +llround(const detail::expression &v, const Policy &pol) { + typedef + typename detail::expression::result_type number_type; + number_type r(round(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || + !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol); + return r.template convert_to(); } template -inline boost::long_long_type llround(const detail::expression& v) -{ - return llround(v, boost::math::policies::policy<>()); +inline boost::long_long_type +llround(const detail::expression &v) { + return llround(v, boost::math::policies::policy<>()); } template -inline boost::long_long_type llround(const number& v, const Policy& pol) -{ - number r(round(v, pol)); - if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !(boost::math::isfinite)(v)) - return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol); - return r.template convert_to(); +inline boost::long_long_type llround(const number &v, + const Policy &pol) { + number r(round(v, pol)); + if ((r > (std::numeric_limits::max)()) || + r < (std::numeric_limits::min)() || + !(boost::math::isfinite)(v)) + return boost::math::policies::raise_rounding_error( + "boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol); + return r.template convert_to(); } template -inline boost::long_long_type llround(const number& v) -{ - return llround(v, boost::math::policies::policy<>()); +inline boost::long_long_type llround(const number &v) { + return llround(v, boost::math::policies::policy<>()); } #endif // @@ -2691,68 +2882,97 @@ inline boost::long_long_type llround(const number& v) // not assigned to anything... // template -inline typename enable_if_c::value == number_kind_floating_point, number >::type frexp(const number& v, short* pint) -{ - using default_ops::eval_frexp; - detail::scoped_default_precision > precision_guard(v); - number result; - eval_frexp(result.backend(), v.backend(), pint); - return BOOST_MP_MOVE(result); +inline typename enable_if_c::value == + number_kind_floating_point, + number>::type +frexp(const number &v, short *pint) { + using default_ops::eval_frexp; + detail::scoped_default_precision< + multiprecision::number> + precision_guard(v); + number result; + eval_frexp(result.backend(), v.backend(), pint); + return BOOST_MP_MOVE(result); } template -inline typename enable_if_c::result_type>::value == number_kind_floating_point, typename detail::expression::result_type>::type - frexp(const detail::expression& v, short* pint) -{ - typedef typename detail::expression::result_type number_type; - return BOOST_MP_MOVE(frexp(static_cast(v), pint)); +inline typename enable_if_c< + number_category::result_type>::value == number_kind_floating_point, + typename detail::expression::result_type>::type +frexp(const detail::expression &v, short *pint) { + typedef + typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(frexp(static_cast(v), pint)); } template -inline typename enable_if_c::value == number_kind_floating_point, number >::type frexp(const number& v, int* pint) -{ - using default_ops::eval_frexp; - detail::scoped_default_precision > precision_guard(v); - number result; - eval_frexp(result.backend(), v.backend(), pint); - return BOOST_MP_MOVE(result); +inline typename enable_if_c::value == + number_kind_floating_point, + number>::type +frexp(const number &v, int *pint) { + using default_ops::eval_frexp; + detail::scoped_default_precision< + multiprecision::number> + precision_guard(v); + number result; + eval_frexp(result.backend(), v.backend(), pint); + return BOOST_MP_MOVE(result); } template -inline typename enable_if_c::result_type>::value == number_kind_floating_point, typename detail::expression::result_type>::type -frexp(const detail::expression& v, int* pint) -{ - typedef typename detail::expression::result_type number_type; - return BOOST_MP_MOVE(frexp(static_cast(v), pint)); +inline typename enable_if_c< + number_category::result_type>::value == number_kind_floating_point, + typename detail::expression::result_type>::type +frexp(const detail::expression &v, int *pint) { + typedef + typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(frexp(static_cast(v), pint)); } template -inline typename enable_if_c::value == number_kind_floating_point, number >::type frexp(const number& v, long* pint) -{ - using default_ops::eval_frexp; - detail::scoped_default_precision > precision_guard(v); - number result; - eval_frexp(result.backend(), v.backend(), pint); - return BOOST_MP_MOVE(result); +inline typename enable_if_c::value == + number_kind_floating_point, + number>::type +frexp(const number &v, long *pint) { + using default_ops::eval_frexp; + detail::scoped_default_precision< + multiprecision::number> + precision_guard(v); + number result; + eval_frexp(result.backend(), v.backend(), pint); + return BOOST_MP_MOVE(result); } template -inline typename enable_if_c::result_type>::value == number_kind_floating_point, typename detail::expression::result_type>::type -frexp(const detail::expression& v, long* pint) -{ - typedef typename detail::expression::result_type number_type; - return BOOST_MP_MOVE(frexp(static_cast(v), pint)); +inline typename enable_if_c< + number_category::result_type>::value == number_kind_floating_point, + typename detail::expression::result_type>::type +frexp(const detail::expression &v, long *pint) { + typedef + typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(frexp(static_cast(v), pint)); } template -inline typename enable_if_c::value == number_kind_floating_point, number >::type frexp(const number& v, boost::long_long_type* pint) -{ - using default_ops::eval_frexp; - detail::scoped_default_precision > precision_guard(v); - number result; - eval_frexp(result.backend(), v.backend(), pint); - return BOOST_MP_MOVE(result); +inline typename enable_if_c::value == + number_kind_floating_point, + number>::type +frexp(const number &v, boost::long_long_type *pint) { + using default_ops::eval_frexp; + detail::scoped_default_precision< + multiprecision::number> + precision_guard(v); + number result; + eval_frexp(result.backend(), v.backend(), pint); + return BOOST_MP_MOVE(result); } template -inline typename enable_if_c::result_type>::value == number_kind_floating_point, typename detail::expression::result_type>::type -frexp(const detail::expression& v, boost::long_long_type* pint) -{ - typedef typename detail::expression::result_type number_type; - return BOOST_MP_MOVE(frexp(static_cast(v), pint)); +inline typename enable_if_c< + number_category::result_type>::value == number_kind_floating_point, + typename detail::expression::result_type>::type +frexp(const detail::expression &v, + boost::long_long_type *pint) { + typedef + typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(frexp(static_cast(v), pint)); } // // modf does not return an expression template since we require the @@ -2760,35 +2980,46 @@ frexp(const detail::expression& v, boost::long_long_type* p // not assigned to anything... // template -inline typename enable_if_c::value == number_kind_floating_point, number >::type modf(const number& v, number* pipart) -{ - using default_ops::eval_modf; - detail::scoped_default_precision > precision_guard(v); - number result; - eval_modf(result.backend(), v.backend(), pipart ? &pipart->backend() : 0); - return BOOST_MP_MOVE(result); -} -template -inline typename enable_if_c::value == number_kind_floating_point, number >::type modf(const detail::expression& v, number* pipart) -{ - using default_ops::eval_modf; - detail::scoped_default_precision > precision_guard(v); - number result, arg(v); - eval_modf(result.backend(), arg.backend(), pipart ? &pipart->backend() : 0); - return BOOST_MP_MOVE(result); +inline typename enable_if_c::value == + number_kind_floating_point, + number>::type +modf(const number &v, + number *pipart) { + using default_ops::eval_modf; + detail::scoped_default_precision< + multiprecision::number> + precision_guard(v); + number result; + eval_modf(result.backend(), v.backend(), pipart ? &pipart->backend() : 0); + return BOOST_MP_MOVE(result); +} +template +inline typename enable_if_c::value == + number_kind_floating_point, + number>::type +modf(const detail::expression &v, + number *pipart) { + using default_ops::eval_modf; + detail::scoped_default_precision< + multiprecision::number> + precision_guard(v); + number result, arg(v); + eval_modf(result.backend(), arg.backend(), pipart ? &pipart->backend() : 0); + return BOOST_MP_MOVE(result); } // // Integer square root: // template -inline typename enable_if_c::value == number_kind_integer, number >::type - sqrt(const number& x) -{ - using default_ops::eval_integer_sqrt; - number s, r; - eval_integer_sqrt(s.backend(), r.backend(), x.backend()); - return s; +inline typename enable_if_c::value == number_kind_integer, + number>::type +sqrt(const number &x) { + using default_ops::eval_integer_sqrt; + number s, r; + eval_integer_sqrt(s.backend(), r.backend(), x.backend()); + return s; } // // fma: @@ -2796,869 +3027,825 @@ inline typename enable_if_c::value == number_kind_integer, nu namespace default_ops { - struct fma_func - { - template - void operator()(B& result, const T& a, const U& b, const V& c)const - { - eval_multiply_add(result, a, b, c); - } - }; - +struct fma_func { + template + void operator()(B &result, const T &a, const U &b, const V &c) const { + eval_multiply_add(result, a, b, c); + } +}; -} +} // namespace default_ops template inline typename enable_if< - mpl::and_< - mpl::bool_ >::value == number_kind_floating_point>, - mpl::or_< - is_number, - is_number_expression, - is_arithmetic - >, - mpl::or_< - is_number, - is_number_expression, - is_arithmetic - > - >, - detail::expression, U, V> ->::type -fma(const number& a, const U& b, const V& c) -{ - return detail::expression, U, V>( + mpl::and_< + mpl::bool_>::value == + number_kind_floating_point>, + mpl::or_, is_number_expression, is_arithmetic>, + mpl::or_, is_number_expression, is_arithmetic>>, + detail::expression, U, V>>::type +fma(const number &a, const U &b, const V &c) { + return detail::expression, U, V>( default_ops::fma_func(), a, b, c); } -template +template inline typename enable_if< - mpl::and_< - mpl::bool_::result_type >::value == number_kind_floating_point>, - mpl::or_< - is_number, - is_number_expression, - is_arithmetic - >, - mpl::or_< - is_number, - is_number_expression, - is_arithmetic - > - >, - detail::expression, U, V> ->::type -fma(const detail::expression& a, const U& b, const V& c) -{ - return detail::expression, U, V>( - default_ops::fma_func(), a, b, c); + mpl::and_< + mpl::bool_::result_type>::value == + number_kind_floating_point>, + mpl::or_, is_number_expression, is_arithmetic>, + mpl::or_, is_number_expression, is_arithmetic>>, + detail::expression, U, + V>>::type +fma(const detail::expression &a, const U &b, + const V &c) { + return detail::expression, U, + V>(default_ops::fma_func(), a, b, c); } template inline typename enable_if< - mpl::and_< - mpl::bool_ >::value == number_kind_floating_point>, - mpl::or_< - is_number, - is_number_expression, - is_arithmetic - >, - mpl::or_< - is_number, - is_number_expression, - is_arithmetic - > - >, - number ->::type -fma(const number& a, const U& b, const V& c) -{ - using default_ops::eval_multiply_add; - detail::scoped_default_precision > precision_guard(a, b, c); - number result; - eval_multiply_add(result.backend(), number::canonical_value(a), number::canonical_value(b), number::canonical_value(c)); - return BOOST_MP_MOVE(result); + mpl::and_< + mpl::bool_>::value == + number_kind_floating_point>, + mpl::or_, is_number_expression, is_arithmetic>, + mpl::or_, is_number_expression, is_arithmetic>>, + number>::type +fma(const number &a, const U &b, const V &c) { + using default_ops::eval_multiply_add; + detail::scoped_default_precision> + precision_guard(a, b, c); + number result; + eval_multiply_add(result.backend(), + number::canonical_value(a), + number::canonical_value(b), + number::canonical_value(c)); + return BOOST_MP_MOVE(result); } template inline typename enable_if< - mpl::and_< - mpl::bool_ >::value == number_kind_floating_point>, - is_arithmetic, - mpl::or_< - is_number, - is_number_expression, - is_arithmetic - > - >, - detail::expression, V> ->::type -fma(const U& a, const number& b, const V& c) -{ - return detail::expression, V>( - default_ops::fma_func(), a, b, c); -} - -template + mpl::and_< + mpl::bool_>::value == + number_kind_floating_point>, + is_arithmetic, + mpl::or_, is_number_expression, is_arithmetic>>, + detail::expression, V>>::type +fma(const U &a, const number &b, const V &c) { + return detail::expression, V>(default_ops::fma_func(), + a, b, c); +} + +template inline typename enable_if< - mpl::and_< - mpl::bool_::result_type >::value == number_kind_floating_point>, - is_arithmetic, - mpl::or_< - is_number, - is_number_expression, - is_arithmetic - > - >, - detail::expression, V> ->::type -fma(const U& a, const detail::expression& b, const V& c) -{ - return detail::expression, V>( + mpl::and_< + mpl::bool_::result_type>::value == + number_kind_floating_point>, + is_arithmetic, + mpl::or_, is_number_expression, is_arithmetic>>, + detail::expression, + V>>::type +fma(const U &a, const detail::expression &b, + const V &c) { + return detail::expression, V>( default_ops::fma_func(), a, b, c); } template inline typename enable_if< - mpl::and_< - mpl::bool_ >::value == number_kind_floating_point>, - is_arithmetic, - mpl::or_< - is_number, - is_number_expression, - is_arithmetic - > - >, - number ->::type -fma(const U& a, const number& b, const V& c) -{ - using default_ops::eval_multiply_add; - detail::scoped_default_precision > precision_guard(a, b, c); - number result; - eval_multiply_add(result.backend(), number::canonical_value(a), number::canonical_value(b), number::canonical_value(c)); - return BOOST_MP_MOVE(result); + mpl::and_< + mpl::bool_>::value == + number_kind_floating_point>, + is_arithmetic, + mpl::or_, is_number_expression, is_arithmetic>>, + number>::type +fma(const U &a, const number &b, const V &c) { + using default_ops::eval_multiply_add; + detail::scoped_default_precision> + precision_guard(a, b, c); + number result; + eval_multiply_add(result.backend(), + number::canonical_value(a), + number::canonical_value(b), + number::canonical_value(c)); + return BOOST_MP_MOVE(result); } template inline typename enable_if< - mpl::and_< - mpl::bool_ >::value == number_kind_floating_point>, - is_arithmetic, - is_arithmetic - >, - detail::expression > ->::type -fma(const U& a, const V& b, const number& c) -{ - return detail::expression >( - default_ops::fma_func(), a, b, c); -} - -template + mpl::and_>::value == + number_kind_floating_point>, + is_arithmetic, is_arithmetic>, + detail::expression>>::type +fma(const U &a, const V &b, const number &c) { + return detail::expression>(default_ops::fma_func(), a, + b, c); +} + +template inline typename enable_if< - mpl::and_< - mpl::bool_::result_type >::value == number_kind_floating_point>, - is_arithmetic, - is_arithmetic - >, - detail::expression > ->::type -fma(const U& a, const V& b, const detail::expression& c) -{ - return detail::expression >( + mpl::and_::result_type>:: + value == number_kind_floating_point>, + is_arithmetic, is_arithmetic>, + detail::expression>>::type +fma(const U &a, const V &b, + const detail::expression &c) { + return detail::expression>( default_ops::fma_func(), a, b, c); } template inline typename enable_if< - mpl::and_< - mpl::bool_ >::value == number_kind_floating_point>, - is_arithmetic, - is_arithmetic - >, - number ->::type -fma(const U& a, const V& b, const number& c) -{ - using default_ops::eval_multiply_add; - detail::scoped_default_precision > precision_guard(a, b, c); - number result; - eval_multiply_add(result.backend(), number::canonical_value(a), number::canonical_value(b), number::canonical_value(c)); - return BOOST_MP_MOVE(result); + mpl::and_>::value == + number_kind_floating_point>, + is_arithmetic, is_arithmetic>, + number>::type +fma(const U &a, const V &b, const number &c) { + using default_ops::eval_multiply_add; + detail::scoped_default_precision> + precision_guard(a, b, c); + number result; + eval_multiply_add(result.backend(), + number::canonical_value(a), + number::canonical_value(b), + number::canonical_value(c)); + return BOOST_MP_MOVE(result); } namespace default_ops { - struct remquo_func - { - template - void operator()(B& result, const T& a, const U& b, int* pi)const - { - eval_remquo(result, a, b, pi); - } - }; +struct remquo_func { + template + void operator()(B &result, const T &a, const U &b, int *pi) const { + eval_remquo(result, a, b, pi); + } +}; -} +} // namespace default_ops template inline typename enable_if_c< - number_category >::value == number_kind_floating_point, - detail::expression, U, int*> ->::type -remquo(const number& a, const U& b, int* pi) -{ - return detail::expression, U, int*>( + number_category>::value == + number_kind_floating_point, + detail::expression, U, int *>>::type +remquo(const number &a, const U &b, int *pi) { + return detail::expression, U, int *>( default_ops::remquo_func(), a, b, pi); } template inline typename enable_if_c< - number_category::result_type >::value == number_kind_floating_point, - detail::expression, U, int*> ->::type -remquo(const detail::expression& a, const U& b, int* pi) -{ - return detail::expression, U, int*>( - default_ops::remquo_func(), a, b, pi); + number_category:: + result_type>::value == number_kind_floating_point, + detail::expression, U, + int *>>::type +remquo(const detail::expression &a, const U &b, + int *pi) { + return detail::expression, U, + int *>(default_ops::remquo_func(), a, b, pi); } template inline typename enable_if_c< - (number_category >::value == number_kind_floating_point) - && !is_number::value && !is_number_expression::value, - detail::expression, int*> ->::type -remquo(const U& a, const number& b, int* pi) -{ - return detail::expression, int*>( + (number_category>::value == + number_kind_floating_point) && + !is_number::value && !is_number_expression::value, + detail::expression, int *>>::type +remquo(const U &a, const number &b, int *pi) { + return detail::expression, int *>( default_ops::remquo_func(), a, b, pi); } template inline typename enable_if_c< - (number_category::result_type >::value == number_kind_floating_point) - && !is_number::value && !is_number_expression::value, - detail::expression, int*> ->::type -remquo(const U& a, const detail::expression& b, int* pi) -{ - return detail::expression, int*>( - default_ops::remquo_func(), a, b, pi); + (number_category:: + result_type>::value == number_kind_floating_point) && + !is_number::value && !is_number_expression::value, + detail::expression, + int *>>::type +remquo(const U &a, const detail::expression &b, + int *pi) { + return detail::expression, + int *>(default_ops::remquo_func(), a, b, pi); } template -inline typename enable_if_c< - number_category >::value == number_kind_floating_point, - number ->::type -remquo(const number& a, const U& b, int* pi) -{ - using default_ops::eval_remquo; - detail::scoped_default_precision > precision_guard(a, b); - number result; - eval_remquo(result.backend(), a.backend(), number::canonical_value(b), pi); - return BOOST_MP_MOVE(result); +inline typename enable_if_c>::value == + number_kind_floating_point, + number>::type +remquo(const number &a, const U &b, int *pi) { + using default_ops::eval_remquo; + detail::scoped_default_precision> + precision_guard(a, b); + number result; + eval_remquo(result.backend(), a.backend(), + number::canonical_value(b), pi); + return BOOST_MP_MOVE(result); } template -inline typename enable_if_c< -(number_category >::value == number_kind_floating_point) -&& !is_number::value && !is_number_expression::value, -number ->::type -remquo(const U& a, const number& b, int* pi) -{ - using default_ops::eval_remquo; - detail::scoped_default_precision > precision_guard(a, b); - number result; - eval_remquo(result.backend(), number::canonical_value(a), b.backend(), pi); - return BOOST_MP_MOVE(result); +inline typename enable_if_c<(number_category>::value == + number_kind_floating_point) && + !is_number::value && + !is_number_expression::value, + number>::type +remquo(const U &a, const number &b, int *pi) { + using default_ops::eval_remquo; + detail::scoped_default_precision> + precision_guard(a, b); + number result; + eval_remquo(result.backend(), number::canonical_value(a), + b.backend(), pi); + return BOOST_MP_MOVE(result); } - template -inline typename enable_if_c::value == number_kind_integer, number >::type - sqrt(const number& x, number& r) -{ - using default_ops::eval_integer_sqrt; - detail::scoped_default_precision > precision_guard(x, r); - number s; - eval_integer_sqrt(s.backend(), r.backend(), x.backend()); - return s; -} - -#define UNARY_OP_FUNCTOR(func, category)\ -namespace detail{\ -template \ -struct BOOST_JOIN(category, BOOST_JOIN(func, _funct))\ -{\ - void operator()(Backend& result, const Backend& arg)const\ - {\ - using default_ops::BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result, arg);\ - }\ - template \ - void operator()(U& result, const Backend& arg)const\ - {\ - using default_ops::BOOST_JOIN(eval_,func);\ - Backend temp;\ - BOOST_JOIN(eval_,func)(temp, arg);\ - result = temp;\ - }\ -};\ -\ -}\ -\ -template \ -inline typename enable_if_c >::value == category,\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , detail::expression > \ ->::type \ -func(const detail::expression& arg)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , detail::expression \ -> (\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type>() \ - , arg \ - );\ -}\ -template \ -inline typename enable_if_c::value == category,\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number > \ ->::type \ -func(const number& arg)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number \ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))() \ - , arg \ - );\ -}\ -template \ -inline typename boost::enable_if_c<\ - boost::multiprecision::number_category::value == category,\ - number >::type \ -func(const number& arg)\ -{\ - detail::scoped_default_precision > precision_guard(arg);\ - number result;\ - using default_ops::BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result.backend(), arg.backend());\ - return BOOST_MP_MOVE(result);\ -} - -#define BINARY_OP_FUNCTOR(func, category)\ -namespace detail{\ -template \ -struct BOOST_JOIN(category, BOOST_JOIN(func, _funct))\ -{\ - void operator()(Backend& result, const Backend& arg, const Backend& a)const\ - {\ - using default_ops:: BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result, arg, a);\ - }\ - template \ - void operator()(Backend& result, const Backend& arg, const Arithmetic& a)const\ - {\ - using default_ops:: BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result, arg, number::canonical_value(a));\ - }\ - template \ - void operator()(Backend& result, const Arithmetic& arg, const Backend& a)const\ - {\ - using default_ops:: BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result, number::canonical_value(arg), a);\ - }\ - template \ - void operator()(U& result, const Backend& arg, const Backend& a)const\ - {\ - using default_ops:: BOOST_JOIN(eval_,func);\ - Backend r;\ - BOOST_JOIN(eval_,func)(r, arg, a);\ - result = r;\ - }\ - template \ - void operator()(U& result, const Backend& arg, const Arithmetic& a)const\ - {\ - using default_ops:: BOOST_JOIN(eval_,func);\ - Backend r;\ - BOOST_JOIN(eval_,func)(r, arg, number::canonical_value(a));\ - result = r;\ - }\ - template \ - void operator()(U& result, const Arithmetic& arg, const Backend& a)const\ - {\ - using default_ops:: BOOST_JOIN(eval_,func);\ - Backend r;\ - BOOST_JOIN(eval_,func)(r, number::canonical_value(arg), a);\ - result = r;\ - }\ -};\ -\ -}\ -template \ -inline typename enable_if_c::value == category,\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number \ - , number > \ ->::type \ -func(const number& arg, const number& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number \ - , number \ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))() \ - , arg,\ - a\ - );\ -}\ -template \ -inline typename enable_if_c<\ - (number_category::value == category) && (boost::is_convertible::result_type, number >::value),\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number \ - , detail::expression > \ ->::type \ -func(const number& arg, const detail::expression& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number \ - , detail::expression \ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))() \ - , arg,\ - a\ - );\ -}\ -template \ -inline typename enable_if_c<\ - (number_category::value == category) && (boost::is_convertible::result_type, number >::value),\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , detail::expression \ - , number > \ ->::type \ -func(const detail::expression& arg, const number& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , detail::expression \ - , number \ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))() \ - , arg,\ - a\ - );\ -}\ -template \ -inline typename enable_if_c<\ - (number_category >::value == category) && (number_category >::value == category),\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , detail::expression \ - , detail::expression > \ ->::type \ -func(const detail::expression& arg, const detail::expression& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , detail::expression \ - , detail::expression \ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type>() \ - , arg,\ - a\ - );\ -}\ -template \ -inline typename enable_if_c<\ - is_compatible_arithmetic_type >::value && (number_category::value == category),\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number \ - , Arithmetic\ - > \ ->::type \ -func(const number& arg, const Arithmetic& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number \ - , Arithmetic\ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))() \ - , arg,\ - a\ - );\ -}\ -template \ -inline typename enable_if_c<\ - is_compatible_arithmetic_type::result_type>::value && (number_category >::value == category),\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , detail::expression \ - , Arithmetic\ - > \ ->::type \ -func(const detail::expression& arg, const Arithmetic& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , detail::expression \ - , Arithmetic\ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type>() \ - , arg,\ - a\ - );\ -}\ -template \ -inline typename enable_if_c<\ - is_compatible_arithmetic_type >::value && (number_category::value == category),\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , Arithmetic \ - , number \ - > \ ->::type \ -func(const Arithmetic& arg, const number& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , Arithmetic \ - , number \ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))() \ - , arg,\ - a\ - );\ -}\ -template \ -inline typename enable_if_c<\ - is_compatible_arithmetic_type::result_type>::value && (number_category >::value == category),\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , Arithmetic \ - , detail::expression \ - > \ ->::type \ -func(const Arithmetic& arg, const detail::expression& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , Arithmetic \ - , detail::expression \ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type>() \ - , arg,\ - a\ - );\ -}\ -template \ -inline typename enable_if_c<(number_category::value == category),\ - number >::type \ -func(const number& arg, const number& a)\ -{\ - detail::scoped_default_precision > precision_guard(arg, a);\ - number result;\ - using default_ops:: BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a.backend());\ - return BOOST_MP_MOVE(result);\ -}\ -template \ -inline typename enable_if_c<\ - is_compatible_arithmetic_type >::value && (number_category::value == category),\ - number \ ->::type \ -func(const number& arg, const Arithmetic& a)\ -{\ - detail::scoped_default_precision > precision_guard(arg);\ - number result;\ - using default_ops:: BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), number::canonical_value(a));\ - return BOOST_MP_MOVE(result);\ -}\ -template \ -inline typename enable_if_c<\ - is_compatible_arithmetic_type >::value && (number_category::value == category),\ - number \ ->::type \ -func(const Arithmetic& a, const number& arg)\ -{\ - detail::scoped_default_precision > precision_guard(arg);\ - number result;\ - using default_ops:: BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result.backend(), number::canonical_value(a), arg.backend());\ - return BOOST_MP_MOVE(result);\ -}\ - - -#define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)\ -template \ -inline typename enable_if_c<\ - (number_category >::value == category),\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , detail::expression \ - , Arg2> \ ->::type \ -func(const detail::expression& arg, Arg2 const& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type> \ - , detail::expression \ - , Arg2\ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) >::type>() \ - , arg, a \ - );\ -}\ -template \ -inline typename enable_if_c<\ - (number_category::value == category),\ - detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number \ - , Arg2> \ ->::type \ -func(const number& arg, Arg2 const& a)\ -{\ - return detail::expression<\ - detail::function\ - , detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \ - , number \ - , Arg2\ - >(\ - detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))() \ - , arg,\ - a\ - );\ -}\ -template \ -inline typename enable_if_c<\ - (number_category::value == category),\ - number >::type \ -func(const number& arg, Arg2 const& a)\ -{\ - detail::scoped_default_precision > precision_guard(arg, a);\ - number result;\ - using default_ops:: BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a);\ - return BOOST_MP_MOVE(result);\ -}\ - -#define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category)\ -namespace detail{\ -template \ -struct BOOST_JOIN(category, BOOST_JOIN(func, _funct))\ -{\ - template \ - void operator()(Backend& result, Backend const& arg, Arg a)const\ - {\ - using default_ops:: BOOST_JOIN(eval_,func);\ - BOOST_JOIN(eval_,func)(result, arg, a);\ - }\ -};\ -\ -}\ -\ -HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) - -namespace detail{ -template -struct abs_funct -{ - void operator()(Backend& result, const Backend& arg)const - { - using default_ops::eval_abs; - eval_abs(result, arg); - } +inline typename enable_if_c::value == number_kind_integer, + number>::type +sqrt(const number &x, + number &r) { + using default_ops::eval_integer_sqrt; + detail::scoped_default_precision< + multiprecision::number> + precision_guard(x, r); + number s; + eval_integer_sqrt(s.backend(), r.backend(), x.backend()); + return s; +} + +#define UNARY_OP_FUNCTOR(func, category) \ + namespace detail { \ + template \ + struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) { \ + void operator()(Backend &result, const Backend &arg) const { \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func)(result, arg); \ + } \ + template void operator()(U &result, const Backend &arg) const { \ + using default_ops::BOOST_JOIN(eval_, func); \ + Backend temp; \ + BOOST_JOIN(eval_, func)(temp, arg); \ + result = temp; \ + } \ + }; \ + } \ + \ + template \ + inline typename enable_if_c< \ + number_category>::value == \ + category, \ + detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + detail::expression>> \ + ::type func(const detail::expression &arg) { \ + return detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + detail::expression> \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type > (), \ + arg); \ + } \ + template \ + inline typename enable_if_c< \ + number_category::value == category, \ + detail::expression, \ + number>> \ + ::type func(const number &arg) { \ + return detail::expression, \ + number> \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + Backend > (), \ + arg); \ + } \ + template \ + inline typename boost::enable_if_c< \ + boost::multiprecision::number_category::value == category, \ + number>::type \ + func(const number &arg) { \ + detail::scoped_default_precision> \ + precision_guard(arg); \ + number result; \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \ + return BOOST_MP_MOVE(result); \ + } + +#define BINARY_OP_FUNCTOR(func, category) \ + namespace detail { \ + template \ + struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) { \ + void operator()(Backend &result, const Backend &arg, \ + const Backend &a) const { \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func)(result, arg, a); \ + } \ + template \ + void operator()(Backend &result, const Backend &arg, \ + const Arithmetic &a) const { \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func) \ + (result, arg, number::canonical_value(a)); \ + } \ + template \ + void operator()(Backend &result, const Arithmetic &arg, \ + const Backend &a) const { \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func) \ + (result, number::canonical_value(arg), a); \ + } \ + template \ + void operator()(U &result, const Backend &arg, const Backend &a) const { \ + using default_ops::BOOST_JOIN(eval_, func); \ + Backend r; \ + BOOST_JOIN(eval_, func)(r, arg, a); \ + result = r; \ + } \ + template \ + void operator()(U &result, const Backend &arg, \ + const Arithmetic &a) const { \ + using default_ops::BOOST_JOIN(eval_, func); \ + Backend r; \ + BOOST_JOIN(eval_, func)(r, arg, number::canonical_value(a)); \ + result = r; \ + } \ + template \ + void operator()(U &result, const Arithmetic &arg, \ + const Backend &a) const { \ + using default_ops::BOOST_JOIN(eval_, func); \ + Backend r; \ + BOOST_JOIN(eval_, func)(r, number::canonical_value(arg), a); \ + result = r; \ + } \ + }; \ + } \ + template \ + inline typename enable_if_c< \ + number_category::value == category, \ + detail::expression, \ + number, number>> \ + ::type func(const number &arg, \ + const number &a) { \ + return detail::expression, \ + number, \ + number> \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + Backend > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c< \ + (number_category::value == category) && \ + (boost::is_convertible::result_type, \ + number>::value), \ + detail::expression, \ + number, detail::expression>> \ + ::type func(const number &arg, \ + const detail::expression &a) { \ + return detail::expression, \ + number, \ + detail::expression> \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + Backend > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c< \ + (number_category::value == category) && \ + (boost::is_convertible::result_type, \ + number>::value), \ + detail::expression, \ + detail::expression, number>> \ + ::type func(const detail::expression &arg, \ + const number &a) { \ + return detail::expression, \ + detail::expression, \ + number> \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + Backend > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c< \ + (number_category>::value == \ + category) && \ + (number_category>::value == category), \ + detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + detail::expression, \ + detail::expression>> \ + ::type func(const detail::expression &arg, \ + const detail::expression &a) { \ + return detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + detail::expression, \ + detail::expression> \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c< \ + is_compatible_arithmetic_type>::value && \ + (number_category::value == category), \ + detail::expression, \ + number, Arithmetic>> \ + ::type func(const number &arg, const Arithmetic &a) { \ + return detail::expression, \ + number, \ + Arithmetic > \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + Backend > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c< \ + is_compatible_arithmetic_type< \ + Arithmetic, typename detail::expression< \ + tag, A1, A2, A3, A4>::result_type>::value && \ + (number_category>::value == category), \ + detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + detail::expression, Arithmetic>> \ + ::type func(const detail::expression &arg, \ + const Arithmetic &a) { \ + return detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + detail::expression, \ + Arithmetic > \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c< \ + is_compatible_arithmetic_type>::value && \ + (number_category::value == category), \ + detail::expression, \ + Arithmetic, number>> \ + ::type func(const Arithmetic &arg, const number &a) { \ + return detail::expression, \ + Arithmetic, \ + number> \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + Backend > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c< \ + is_compatible_arithmetic_type< \ + Arithmetic, typename detail::expression< \ + tag, A1, A2, A3, A4>::result_type>::value && \ + (number_category>::value == category), \ + detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + Arithmetic, detail::expression>> \ + ::type func(const Arithmetic &arg, \ + const detail::expression &a) { \ + return detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + Arithmetic, \ + detail::expression> \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c<(number_category::value == category), \ + number>::type \ + func(const number &arg, const number &a) { \ + detail::scoped_default_precision> \ + precision_guard(arg, a); \ + number result; \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \ + return BOOST_MP_MOVE(result); \ + } \ + template \ + inline \ + typename enable_if_c>::value && \ + (number_category::value == category), \ + number>::type \ + func(const number &arg, const Arithmetic &a) { \ + detail::scoped_default_precision> \ + precision_guard(arg); \ + number result; \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func) \ + (result.backend(), arg.backend(), \ + number::canonical_value(a)); \ + return BOOST_MP_MOVE(result); \ + } \ + template \ + inline \ + typename enable_if_c>::value && \ + (number_category::value == category), \ + number>::type \ + func(const Arithmetic &a, const number &arg) { \ + detail::scoped_default_precision> \ + precision_guard(arg); \ + number result; \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func) \ + (result.backend(), number::canonical_value(a), \ + arg.backend()); \ + return BOOST_MP_MOVE(result); \ + } + +#define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) \ + template \ + inline typename enable_if_c< \ + (number_category>::value == \ + category), \ + detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + detail::expression, Arg2>> \ + ::type func(const detail::expression &arg, \ + Arg2 const &a) { \ + return detail::expression< \ + detail::function, \ + detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type>, \ + detail::expression, \ + Arg2 > \ + (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + typename detail::backend_type< \ + detail::expression>::type > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c< \ + (number_category::value == category), \ + detail::expression, \ + number, Arg2>> \ + ::type func(const number &arg, Arg2 const &a) { \ + return detail::expression, \ + number, \ + Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < \ + Backend > (), \ + arg, a); \ + } \ + template \ + inline typename enable_if_c<(number_category::value == category), \ + number>::type \ + func(const number &arg, Arg2 const &a) { \ + detail::scoped_default_precision> \ + precision_guard(arg, a); \ + number result; \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a); \ + return BOOST_MP_MOVE(result); \ + } + +#define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category) \ + namespace detail { \ + template \ + struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) { \ + template \ + void operator()(Backend &result, Backend const &arg, Arg a) const { \ + using default_ops::BOOST_JOIN(eval_, func); \ + BOOST_JOIN(eval_, func)(result, arg, a); \ + } \ + }; \ + } \ + \ + HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) + +namespace detail { +template struct abs_funct { + void operator()(Backend &result, const Backend &arg) const { + using default_ops::eval_abs; + eval_abs(result, arg); + } }; -template -struct conj_funct -{ - void operator()(Backend& result, const Backend& arg)const - { - using default_ops::eval_conj; - eval_conj(result, arg); - } +template struct conj_funct { + void operator()(Backend &result, const Backend &arg) const { + using default_ops::eval_conj; + eval_conj(result, arg); + } }; -template -struct proj_funct -{ - void operator()(Backend& result, const Backend& arg)const - { - using default_ops::eval_proj; - eval_proj(result, arg); - } +template struct proj_funct { + void operator()(Backend &result, const Backend &arg) const { + using default_ops::eval_proj; + eval_proj(result, arg); + } }; -} +} // namespace detail template -inline typename boost::disable_if_c::result_type>::value == number_kind_complex, - detail::expression< - detail::function - , detail::abs_funct >::type> - , detail::expression > >::type -abs(const detail::expression& arg) -{ - return detail::expression< - detail::function - , detail::abs_funct >::type> - , detail::expression -> ( - detail::abs_funct >::type>() - , arg - ); +inline typename boost::disable_if_c< + number_category::result_type>::value == number_kind_complex, + detail::expression>::type>, + detail::expression>>::type +abs(const detail::expression &arg) { + return detail::expression>::type>, + detail::expression>( + detail::abs_funct>::type>(), + arg); } template -inline typename disable_if_c::value == number_kind_complex, - detail::expression< - detail::function - , detail::abs_funct - , number > >::type -abs(const number& arg) -{ - return detail::expression< - detail::function - , detail::abs_funct - , number - >( - detail::abs_funct() - , arg - ); +inline typename disable_if_c< + number_category::value == number_kind_complex, + detail::expression, + number>>::type +abs(const number &arg) { + return detail::expression, + number>( + detail::abs_funct(), arg); } template -inline typename disable_if_c::value == number_kind_complex, number >::type -abs(const number& arg) -{ - detail::scoped_default_precision > precision_guard(arg); - number result; - using default_ops::eval_abs; - eval_abs(result.backend(), arg.backend()); - return BOOST_MP_MOVE(result); +inline typename disable_if_c::value == + number_kind_complex, + number>::type +abs(const number &arg) { + detail::scoped_default_precision> + precision_guard(arg); + number result; + using default_ops::eval_abs; + eval_abs(result.backend(), arg.backend()); + return BOOST_MP_MOVE(result); } template -inline detail::expression< - detail::function - , detail::conj_funct >::type> - , detail::expression > -conj(const detail::expression& arg) -{ - return detail::expression< - detail::function - , detail::conj_funct >::type> - , detail::expression -> ( - detail::conj_funct >::type>() - , arg - ); +inline detail::expression>::type>, + detail::expression> +conj(const detail::expression &arg) { + return detail::expression>::type>, + detail::expression>( + detail::conj_funct>::type>(), + arg); } template -inline detail::expression< - detail::function - , detail::conj_funct - , number > -conj(const number& arg) -{ - return detail::expression< - detail::function - , detail::conj_funct - , number - >( - detail::conj_funct() - , arg - ); +inline detail::expression, + number> +conj(const number &arg) { + return detail::expression, + number>( + detail::conj_funct(), arg); } template -inline number -conj(const number& arg) -{ - detail::scoped_default_precision > precision_guard(arg); - number result; - using default_ops::eval_conj; - eval_conj(result.backend(), arg.backend()); - return BOOST_MP_MOVE(result); +inline number conj(const number &arg) { + detail::scoped_default_precision> + precision_guard(arg); + number result; + using default_ops::eval_conj; + eval_conj(result.backend(), arg.backend()); + return BOOST_MP_MOVE(result); } template -inline detail::expression< - detail::function - , detail::proj_funct >::type> - , detail::expression > -proj(const detail::expression& arg) -{ - return detail::expression< - detail::function - , detail::proj_funct >::type> - , detail::expression -> ( - detail::proj_funct >::type>() - , arg - ); +inline detail::expression>::type>, + detail::expression> +proj(const detail::expression &arg) { + return detail::expression>::type>, + detail::expression>( + detail::proj_funct>::type>(), + arg); } template -inline detail::expression< - detail::function - , detail::proj_funct - , number > -proj(const number& arg) -{ - return detail::expression< - detail::function - , detail::proj_funct - , number - >( - detail::proj_funct() - , arg - ); +inline detail::expression, + number> +proj(const number &arg) { + return detail::expression, + number>( + detail::proj_funct(), arg); } template -inline number -proj(const number& arg) -{ - detail::scoped_default_precision > precision_guard(arg); - number result; - using default_ops::eval_proj; - eval_proj(result.backend(), arg.backend()); - return BOOST_MP_MOVE(result); +inline number proj(const number &arg) { + detail::scoped_default_precision> + precision_guard(arg); + number result; + using default_ops::eval_proj; + eval_proj(result.backend(), arg.backend()); + return BOOST_MP_MOVE(result); } UNARY_OP_FUNCTOR(fabs, number_kind_floating_point) @@ -3685,13 +3872,15 @@ UNARY_OP_FUNCTOR(nearbyint, number_kind_floating_point) UNARY_OP_FUNCTOR(rint, number_kind_floating_point) HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point) -//HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point) +// HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point) HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point) -//HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point) +// HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point) HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point) -//HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point) -HETERO_BINARY_OP_FUNCTOR_B(ldexp, boost::long_long_type, number_kind_floating_point) -//HETERO_BINARY_OP_FUNCTOR_B(frexp, boost::long_long_type*, number_kind_floating_point) +// HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point) +HETERO_BINARY_OP_FUNCTOR_B(ldexp, boost::long_long_type, + number_kind_floating_point) +// HETERO_BINARY_OP_FUNCTOR_B(frexp, boost::long_long_type*, +// number_kind_floating_point) BINARY_OP_FUNCTOR(pow, number_kind_floating_point) BINARY_OP_FUNCTOR(fmod, number_kind_floating_point) BINARY_OP_FUNCTOR(fmax, number_kind_floating_point) @@ -3708,8 +3897,10 @@ HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point) HETERO_BINARY_OP_FUNCTOR_B(scalbln, int, number_kind_floating_point) HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point) HETERO_BINARY_OP_FUNCTOR_B(scalbln, long, number_kind_floating_point) -HETERO_BINARY_OP_FUNCTOR_B(scalbn, boost::long_long_type, number_kind_floating_point) -HETERO_BINARY_OP_FUNCTOR_B(scalbln, boost::long_long_type, number_kind_floating_point) +HETERO_BINARY_OP_FUNCTOR_B(scalbn, boost::long_long_type, + number_kind_floating_point) +HETERO_BINARY_OP_FUNCTOR_B(scalbln, boost::long_long_type, + number_kind_floating_point) // // Complex functions: @@ -3745,59 +3936,82 @@ HETERO_BINARY_OP_FUNCTOR(pow, unsigned, number_kind_integer) // // ilogb: // -template -inline typename enable_if_c::value == number_kind_floating_point, typename Backend::exponent_type>::type - ilogb(const multiprecision::number& val) -{ - using default_ops::eval_ilogb; - return eval_ilogb(val.backend()); +template +inline typename enable_if_c::value == + number_kind_floating_point, + typename Backend::exponent_type>::type +ilogb(const multiprecision::number &val) { + using default_ops::eval_ilogb; + return eval_ilogb(val.backend()); } template -inline typename enable_if_c >::value == number_kind_floating_point, typename multiprecision::detail::expression::result_type::backend_type::exponent_type>::type -ilogb(const detail::expression& val) -{ - using default_ops::eval_ilogb; - typename multiprecision::detail::expression::result_type arg(val); - return eval_ilogb(arg.backend()); +inline typename enable_if_c< + number_category>::value == + number_kind_floating_point, + typename multiprecision::detail::expression< + tag, A1, A2, A3, A4>::result_type::backend_type::exponent_type>::type +ilogb(const detail::expression &val) { + using default_ops::eval_ilogb; + typename multiprecision::detail::expression::result_type + arg(val); + return eval_ilogb(arg.backend()); } -} //namespace multiprecision +} // namespace multiprecision -namespace math{ +namespace math { // -// Overload of Boost.Math functions that find the wrong overload when used with number: +// Overload of Boost.Math functions that find the wrong overload when used with +// number: // -namespace detail{ - template T sinc_pi_imp(T); - template T sinhc_pi_imp(T); -} -template -inline multiprecision::number sinc_pi(const multiprecision::number& x) -{ - boost::multiprecision::detail::scoped_default_precision > precision_guard(x); - return BOOST_MP_MOVE(detail::sinc_pi_imp(x)); -} - -template -inline multiprecision::number sinc_pi(const multiprecision::number& x, const Policy&) -{ - boost::multiprecision::detail::scoped_default_precision > precision_guard(x); - return BOOST_MP_MOVE(detail::sinc_pi_imp(x)); -} - -template -inline multiprecision::number sinhc_pi(const multiprecision::number& x) -{ - boost::multiprecision::detail::scoped_default_precision > precision_guard(x); - return BOOST_MP_MOVE(detail::sinhc_pi_imp(x)); -} - -template -inline multiprecision::number sinhc_pi(const multiprecision::number& x, const Policy&) -{ - boost::multiprecision::detail::scoped_default_precision > precision_guard(x); - return BOOST_MP_MOVE(boost::math::sinhc_pi(x)); +namespace detail { +template T sinc_pi_imp(T); +template T sinhc_pi_imp(T); +} // namespace detail +template +inline multiprecision::number +sinc_pi(const multiprecision::number &x) { + boost::multiprecision::detail::scoped_default_precision< + multiprecision::number> + precision_guard(x); + return BOOST_MP_MOVE(detail::sinc_pi_imp(x)); +} + +template +inline multiprecision::number +sinc_pi(const multiprecision::number &x, + const Policy &) { + boost::multiprecision::detail::scoped_default_precision< + multiprecision::number> + precision_guard(x); + return BOOST_MP_MOVE(detail::sinc_pi_imp(x)); +} + +template +inline multiprecision::number +sinhc_pi(const multiprecision::number &x) { + boost::multiprecision::detail::scoped_default_precision< + multiprecision::number> + precision_guard(x); + return BOOST_MP_MOVE(detail::sinhc_pi_imp(x)); +} + +template +inline multiprecision::number +sinhc_pi(const multiprecision::number &x, + const Policy &) { + boost::multiprecision::detail::scoped_default_precision< + multiprecision::number> + precision_guard(x); + return BOOST_MP_MOVE(boost::math::sinhc_pi(x)); } using boost::multiprecision::gcd; @@ -3813,19 +4027,18 @@ namespace integer { using boost::multiprecision::gcd; using boost::multiprecision::lcm; -} +} // namespace integer } // namespace boost // // This has to come last of all: // -#include #include +#include // // min/max overloads: // #include #endif - diff --git a/include/boost/multiprecision/detail/dynamic_array.hpp b/include/boost/multiprecision/detail/dynamic_array.hpp index c7a467cfc..c308b7657 100644 --- a/include/boost/multiprecision/detail/dynamic_array.hpp +++ b/include/boost/multiprecision/detail/dynamic_array.hpp @@ -6,24 +6,35 @@ // #ifndef BOOST_MP_DETAIL_DYNAMIC_ARRAY_HPP - #define BOOST_MP_DETAIL_DYNAMIC_ARRAY_HPP +#define BOOST_MP_DETAIL_DYNAMIC_ARRAY_HPP - #include - #include +#include +#include - namespace boost { namespace multiprecision { namespace backends { namespace detail - { - template - struct dynamic_array : public std::vector::type> - { - dynamic_array() : - std::vector::type>(static_cast::type>::size_type>(elem_number), static_cast(0)) - { - } +namespace boost { +namespace multiprecision { +namespace backends { +namespace detail { +template +struct dynamic_array + : public std::vector::type> { + dynamic_array() + : std::vector::type>( + static_cast::type>::size_type>( + elem_number), + static_cast(0)) {} - value_type* data() { return &(*(this->begin())); } - const value_type* data() const { return &(*(this->begin())); } - }; - } } } } // namespace boost::multiprecision::backends::detail + value_type *data() { return &(*(this->begin())); } + const value_type *data() const { return &(*(this->begin())); } +}; +} // namespace detail +} // namespace backends +} // namespace multiprecision +} // namespace boost #endif // BOOST_MP_DETAIL_DYNAMIC_ARRAY_HPP diff --git a/include/boost/multiprecision/detail/et_ops.hpp b/include/boost/multiprecision/detail/et_ops.hpp index 3778e0102..bdbde5359 100644 --- a/include/boost/multiprecision/detail/et_ops.hpp +++ b/include/boost/multiprecision/detail/et_ops.hpp @@ -6,814 +6,1445 @@ #ifndef BOOST_MP_ET_OPS_HPP #define BOOST_MP_ET_OPS_HPP -namespace boost{ namespace multiprecision{ +namespace boost { +namespace multiprecision { // // Non-member operators for number: // // Unary operators first. // Note that these *must* return by value, even though that's somewhat against -// existing practice. The issue is that in C++11 land one could easily and legitimately -// write: +// existing practice. The issue is that in C++11 land one could easily and +// legitimately write: // auto x = +1234_my_user_defined_suffix; -// which would result in a dangling-reference-to-temporary if unary + returned a reference -// to it's argument. While return-by-value is obviously inefficient in other situations -// the reality is that no one ever uses unary operator+ anyway...! +// which would result in a dangling-reference-to-temporary if unary + returned a +// reference to it's argument. While return-by-value is obviously inefficient +// in other situations the reality is that no one ever uses unary operator+ +// anyway...! // template -inline BOOST_CONSTEXPR const number operator + (const number& v) { return v; } +inline BOOST_CONSTEXPR const number +operator+(const number &v) { + return v; +} template -inline BOOST_CONSTEXPR const detail::expression operator + (const detail::expression& v) { return v; } +inline BOOST_CONSTEXPR const detail::expression +operator+(const detail::expression &v) { + return v; +} template -inline detail::expression > operator - (const number& v) -{ - BOOST_STATIC_ASSERT_MSG(is_signed_number::value, "Negating an unsigned type results in ill-defined behavior."); - return detail::expression >(v); +inline detail::expression> +operator-(const number &v) { + BOOST_STATIC_ASSERT_MSG( + is_signed_number::value, + "Negating an unsigned type results in ill-defined behavior."); + return detail::expression>(v); } template -inline detail::expression > operator - (const detail::expression& v) -{ - BOOST_STATIC_ASSERT_MSG((is_signed_number::result_type>::value), "Negating an unsigned type results in ill-defined behavior."); - return detail::expression >(v); +inline detail::expression> +operator-(const detail::expression &v) { + BOOST_STATIC_ASSERT_MSG( + (is_signed_number::result_type>::value), + "Negating an unsigned type results in ill-defined behavior."); + return detail::expression>(v); } template -inline typename enable_if_c::value == number_kind_integer, - detail::expression > >::type - operator ~ (const number& v) { return detail::expression >(v); } +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression>>::type +operator~(const number &v) { + return detail::expression>(v); +} template -inline typename enable_if_c::result_type>::value == number_kind_integer, - detail::expression > >::type - operator ~ (const detail::expression& v) { return detail::expression >(v); } +inline typename enable_if_c< + number_category:: + result_type>::value == number_kind_integer, + detail::expression>>::type +operator~(const detail::expression &v) { + return detail::expression>(v); +} // // Then addition: // template -inline detail::expression, number > - operator + (const number& a, const number& b) -{ - return detail::expression, number >(a, b); +inline detail::expression, + number> +operator+(const number &a, const number &b) { + return detail::expression, + number>(a, b); } template -inline typename enable_if >, detail::expression, V > >::type - operator + (const number& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression, V>>::type +operator+(const number &a, const V &b) { + return detail::expression, V>(a, b); } template -inline typename enable_if >, detail::expression > >::type - operator + (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator + (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator + (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator + (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression>>::type +operator+(const V &a, const number &b) { + return detail::expression>(a, b); +} +template +inline detail::expression, + detail::expression> +operator+(const number &a, + const detail::expression &b) { + return detail::expression, + detail::expression>(a, + b); +} +template +inline detail::expression, + number> +operator+(const detail::expression &a, + const number &b) { + return detail::expression, + number>(a, b); +} +template +inline detail::expression, + detail::expression> +operator+(const detail::expression &a, + const detail::expression &b) { + return detail::expression< + detail::plus, detail::expression, + detail::expression>(a, b); } template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator + (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, + typename detail::expression::result_type>, + detail::expression< + detail::plus, detail::expression, V>>::type +operator+(const detail::expression &a, + const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if::result_type>, detail::expression > >::type - operator + (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, + typename detail::expression::result_type>, + detail::expression>>::type +operator+(const V &a, + const detail::expression &b) { + return detail::expression>(a, + b); } // // Fused multiply add: // template -inline typename enable_if::result_type>, - detail::expression::left_type, typename detail::expression::right_type, V> >::type - operator + (const V& a, const detail::expression& b) -{ - return detail::expression::left_type, typename detail::expression::right_type, V>(b.left(), b.right(), a); +inline typename enable_if< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>, + detail::expression< + detail::multiply_add, + typename detail::expression::left_type, + typename detail::expression::right_type, + V>>::type +operator+(const V &a, const detail::expression &b) { + return detail::expression< + detail::multiply_add, + typename detail::expression::left_type, + typename detail::expression::right_type, + V>(b.left(), b.right(), a); } template -inline typename enable_if::result_type>, - detail::expression::left_type, typename detail::expression::right_type, V> >::type - operator + (const detail::expression& a, const V& b) -{ - return detail::expression::left_type, typename detail::expression::right_type, V>(a.left(), a.right(), b); -} -template -inline detail::expression::left_type, typename detail::expression::right_type, number > - operator + (const number& a, const detail::expression& b) -{ - return detail::expression::left_type, typename detail::expression::right_type, number >(b.left(), b.right(), a); -} -template -inline detail::expression::left_type, typename detail::expression::right_type, number > - operator + (const detail::expression& a, const number& b) -{ - return detail::expression::left_type, typename detail::expression::right_type, number >(a.left(), a.right(), b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>, + detail::expression< + detail::multiply_add, + typename detail::expression::left_type, + typename detail::expression::right_type, + V>>::type +operator+(const detail::expression &a, + const V &b) { + return detail::expression< + detail::multiply_add, + typename detail::expression::left_type, + typename detail::expression::right_type, + V>(a.left(), a.right(), b); +} +template +inline detail::expression< + detail::multiply_add, + typename detail::expression::left_type, + typename detail::expression::right_type, + number> +operator+(const number &a, + const detail::expression &b) { + return detail::expression< + detail::multiply_add, + typename detail::expression::left_type, + typename detail::expression::right_type, + number>(b.left(), b.right(), a); +} +template +inline detail::expression< + detail::multiply_add, + typename detail::expression::left_type, + typename detail::expression::right_type, + number> +operator+(const detail::expression &a, + const number &b) { + return detail::expression< + detail::multiply_add, + typename detail::expression::left_type, + typename detail::expression::right_type, + number>(a.left(), a.right(), b); } // // Fused multiply subtract: // template -inline typename enable_if::result_type>, - detail::expression::left_type, typename detail::expression::right_type, V> > >::type - operator - (const V& a, const detail::expression& b) -{ - return detail::expression::left_type, typename detail::expression::right_type, V> > - (detail::expression::left_type, typename detail::expression::right_type, V>(b.left(), b.right(), a)); +inline typename enable_if< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>, + detail::expression< + detail::negate, + detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + V>>>::type +operator-(const V &a, const detail::expression &b) { + return detail::expression< + detail::negate, + detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + V>>( + detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + V>(b.left(), b.right(), a)); } template -inline typename enable_if::result_type>, - detail::expression::left_type, typename detail::expression::right_type, V> >::type - operator - (const detail::expression& a, const V& b) -{ - return detail::expression::left_type, typename detail::expression::right_type, V>(a.left(), a.right(), b); -} -template -inline detail::expression::left_type, typename detail::expression::right_type, number > > - operator - (const number& a, const detail::expression& b) -{ - return detail::expression::left_type, typename detail::expression::right_type, number > > - (detail::expression::left_type, typename detail::expression::right_type, number >(b.left(), b.right(), a)); -} -template -inline detail::expression::left_type, typename detail::expression::right_type, number > - operator - (const detail::expression& a, const number& b) -{ - return detail::expression::left_type, typename detail::expression::right_type, number >(a.left(), a.right(), b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>, + detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + V>>::type +operator-(const detail::expression &a, + const V &b) { + return detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + V>(a.left(), a.right(), b); +} +template +inline detail::expression< + detail::negate, + detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + number>> +operator-(const number &a, + const detail::expression &b) { + return detail::expression< + detail::negate, + detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + number>>( + detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + number>(b.left(), b.right(), a)); +} +template +inline detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + number> +operator-(const detail::expression &a, + const number &b) { + return detail::expression< + detail::multiply_subtract, + typename detail::expression::left_type, + typename detail::expression::right_type, + number>(a.left(), a.right(), b); } // -// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// Repeat operator for negated arguments: propagate the negation to the top +// level to avoid temporaries: // -template +template inline detail::expression, Arg1> - operator + (const number& a, const detail::expression& b) -{ - return detail::expression, Arg1>(a, b.left_ref()); +operator+(const number &a, + const detail::expression &b) { + return detail::expression, Arg1>(a, + b.left_ref()); } -template +template inline detail::expression, Arg1> - operator + (const detail::expression& a, const number& b) -{ - return detail::expression, Arg1>(b, a.left_ref()); +operator+(const detail::expression &a, + const number &b) { + return detail::expression, Arg1>(b, + a.left_ref()); } template -inline detail::expression, number > - operator + (const number& a, const detail::expression >& b) -{ - return detail::expression, number >(a, b.left_ref()); +inline detail::expression, + number> +operator+(const number &a, + const detail::expression> &b) { + return detail::expression, + number>(a, b.left_ref()); } template -inline detail::expression, number > - operator + (const detail::expression >& a, const number& b) -{ - return detail::expression, number >(b, a.left_ref()); +inline detail::expression, + number> +operator+(const detail::expression> &a, + const number &b) { + return detail::expression, + number>(b, a.left_ref()); } template -inline typename enable_if >, detail::expression > >::type - operator + (const detail::expression >& a, const V& b) -{ - return detail::expression >(b, a.left_ref()); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression>>::type +operator+(const detail::expression> &a, + const V &b) { + return detail::expression>( + b, a.left_ref()); } template -inline typename enable_if, number >, detail::expression, number > >::type - operator + (const detail::expression >& a, const number& b) -{ - return detail::expression, number >(b, a.left_ref()); +inline typename enable_if< + is_compatible_arithmetic_type, number>, + detail::expression, + number>>::type +operator+(const detail::expression> &a, + const number &b) { + return detail::expression, + number>(b, a.left_ref()); } template -inline typename enable_if, number >, detail::expression, number > >::type - operator + (const number& a, const detail::expression >& b) -{ - return detail::expression, number >(a, b.left_ref()); +inline typename enable_if< + is_compatible_arithmetic_type, number>, + detail::expression, + number>>::type +operator+(const number &a, + const detail::expression> &b) { + return detail::expression, + number>(a, b.left_ref()); } template -inline detail::expression, number > > - operator + (const detail::expression >& a, const detail::expression >& b) -{ - return detail::expression, number > >(detail::expression, number >(a.left_ref(), b.left_ref())); +inline detail::expression< + detail::negate, detail::expression, + number>> +operator+(const detail::expression> &a, + const detail::expression> &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(a.left_ref(), b.left_ref())); } // // Subtraction: // template -inline detail::expression, number > - operator - (const number& a, const number& b) -{ - return detail::expression, number >(a, b); +inline detail::expression, + number> +operator-(const number &a, const number &b) { + return detail::expression, + number>(a, b); } template -inline typename enable_if >, detail::expression, V > >::type - operator - (const number& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression, V>>::type +operator-(const number &a, const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if >, detail::expression > >::type - operator - (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator - (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator - (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator - (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression>>::type +operator-(const V &a, const number &b) { + return detail::expression>( + a, b); +} +template +inline detail::expression, + detail::expression> +operator-(const number &a, + const detail::expression &b) { + return detail::expression, + detail::expression>(a, + b); +} +template +inline detail::expression, + number> +operator-(const detail::expression &a, + const number &b) { + return detail::expression, + number>(a, b); +} +template +inline detail::expression, + detail::expression> +operator-(const detail::expression &a, + const detail::expression &b) { + return detail::expression< + detail::minus, detail::expression, + detail::expression>(a, b); } template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator - (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, + typename detail::expression::result_type>, + detail::expression, + V>>::type +operator-(const detail::expression &a, + const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if::result_type>, detail::expression > >::type - operator - (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, + typename detail::expression::result_type>, + detail::expression>>::type +operator-(const V &a, + const detail::expression &b) { + return detail::expression>(a, + b); } // -// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// Repeat operator for negated arguments: propagate the negation to the top +// level to avoid temporaries: // -template +template inline detail::expression, Arg1> - operator - (const number& a, const detail::expression& b) -{ - return detail::expression, Arg1>(a, b.left_ref()); -} -template -inline detail::expression, Arg1> > - operator - (const detail::expression& a, const number& b) -{ - return detail::expression, Arg1> >( +operator-(const number &a, + const detail::expression &b) { + return detail::expression, Arg1>(a, b.left_ref()); +} +template +inline detail::expression, Arg1>> +operator-(const detail::expression &a, + const number &b) { + return detail::expression< + detail::negate, detail::expression, Arg1>>( detail::expression, Arg1>(b, a.left_ref())); } template -inline detail::expression, number > - operator - (const number& a, const detail::expression >& b) -{ - return detail::expression, number >(a, b.left_ref()); +inline detail::expression, + number> +operator-(const number &a, + const detail::expression> &b) { + return detail::expression, + number>(a, b.left_ref()); } template -inline detail::expression, number > > - operator - (const detail::expression >& a, const number& b) -{ - return detail::expression, number > >( - detail::expression, number >(b, a.left_ref())); +inline detail::expression< + detail::negate, detail::expression, + number>> +operator-(const detail::expression> &a, + const number &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(b, a.left_ref())); } template -inline typename enable_if >, detail::expression, V > > >::type - operator - (const detail::expression >& a, const V& b) -{ - return detail::expression, V > >(detail::expression, V >(a.left_ref(), b)); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression< + detail::negate, + detail::expression, V>>>::type +operator-(const detail::expression> &a, + const V &b) { + return detail::expression< + detail::negate, + detail::expression, V>>( + detail::expression, V>( + a.left_ref(), b)); } template -inline typename enable_if, number >, detail::expression, number > > >::type - operator - (const detail::expression >& a, const number& b) -{ - return detail::expression, number > >(detail::expression, number >(a.left_ref(), b)); +inline typename enable_if< + is_compatible_arithmetic_type, number>, + detail::expression, number>>>:: + type + operator-(const detail::expression> &a, + const number &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(a.left_ref(), b)); } template -inline typename enable_if >, detail::expression > >::type - operator - (const V& a, const detail::expression >& b) -{ - return detail::expression >(a, b.left_ref()); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression>>::type +operator-(const V &a, + const detail::expression> &b) { + return detail::expression>( + a, b.left_ref()); } template -inline typename enable_if, number >, detail::expression, number > >::type - operator - (const number& a, const detail::expression >& b) -{ - return detail::expression, number >(a, b.left_ref()); +inline typename enable_if< + is_compatible_arithmetic_type, number>, + detail::expression, + number>>::type +operator-(const number &a, + const detail::expression> &b) { + return detail::expression, + number>(a, b.left_ref()); } // // Multiplication: // template -inline detail::expression, number > - operator * (const number& a, const number& b) -{ - return detail::expression, number >(a, b); +inline detail::expression, + number> +operator*(const number &a, const number &b) { + return detail::expression, + number>(a, b); } template -inline typename enable_if >, detail::expression, V > >::type - operator * (const number& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression, V>>::type +operator*(const number &a, const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if >, detail::expression > >::type - operator * (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator * (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator * (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator * (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression>>::type +operator*(const V &a, const number &b) { + return detail::expression>( + a, b); +} +template +inline detail::expression, + detail::expression> +operator*(const number &a, + const detail::expression &b) { + return detail::expression, + detail::expression>(a, + b); +} +template +inline detail::expression, + number> +operator*(const detail::expression &a, + const number &b) { + return detail::expression, + number>(a, b); +} +template +inline detail::expression, + detail::expression> +operator*(const detail::expression &a, + const detail::expression &b) { + return detail::expression< + detail::multiplies, detail::expression, + detail::expression>(a, b); } template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator * (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, + typename detail::expression::result_type>, + detail::expression, + V>>::type +operator*(const detail::expression &a, + const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if::result_type>, detail::expression > >::type - operator * (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, + typename detail::expression::result_type>, + detail::expression>>::type +operator*(const V &a, + const detail::expression &b) { + return detail::expression>(a, + b); } // -// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// Repeat operator for negated arguments: propagate the negation to the top +// level to avoid temporaries: // -template -inline detail::expression, Arg1> > - operator * (const number& a, const detail::expression& b) -{ - return detail::expression, Arg1> >( - detail::expression, Arg1> (a, b.left_ref())); -} -template -inline detail::expression, Arg1> > - operator * (const detail::expression& a, const number& b) -{ - return detail::expression, Arg1> >( - detail::expression, Arg1>(b, a.left_ref())); +template +inline detail::expression< + detail::negate, detail::expression, Arg1>> +operator*(const number &a, + const detail::expression &b) { + return detail::expression< + detail::negate, + detail::expression, Arg1>>( + detail::expression, Arg1>( + a, b.left_ref())); +} +template +inline detail::expression< + detail::negate, detail::expression, Arg1>> +operator*(const detail::expression &a, + const number &b) { + return detail::expression< + detail::negate, + detail::expression, Arg1>>( + detail::expression, Arg1>( + b, a.left_ref())); } template -inline detail::expression, number > > - operator * (const number& a, const detail::expression >& b) -{ - return detail::expression, number > >( - detail::expression, number >(a, b.left_ref())); +inline detail::expression< + detail::negate, detail::expression, number>> +operator*(const number &a, + const detail::expression> &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(a, b.left_ref())); } template -inline detail::expression, number > > - operator * (const detail::expression >& a, const number& b) -{ - return detail::expression, number > >( - detail::expression, number >(b, a.left_ref())); +inline detail::expression< + detail::negate, detail::expression, number>> +operator*(const detail::expression> &a, + const number &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(b, a.left_ref())); } template -inline typename enable_if >, detail::expression, V > > >::type - operator * (const detail::expression >& a, const V& b) -{ - return detail::expression, V > > ( - detail::expression, V >(a.left_ref(), b)); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression, V>>>::type +operator*(const detail::expression> &a, + const V &b) { + return detail::expression< + detail::negate, + detail::expression, V>>( + detail::expression, V>( + a.left_ref(), b)); } template -inline typename enable_if, number >, detail::expression, number > > >::type - operator * (const detail::expression >& a, const number& b) -{ - return detail::expression, number > > ( - detail::expression, number >(a.left_ref(), b)); +inline typename enable_if< + is_compatible_arithmetic_type, number>, + detail::expression, number>>>:: + type + operator*(const detail::expression> &a, + const number &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(a.left_ref(), b)); } template -inline typename enable_if >, detail::expression, V > > >::type - operator * (const V& a, const detail::expression >& b) -{ - return detail::expression, V > >( - detail::expression, V >(b.left_ref(), a)); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression, V>>>::type +operator*(const V &a, + const detail::expression> &b) { + return detail::expression< + detail::negate, + detail::expression, V>>( + detail::expression, V>( + b.left_ref(), a)); } template -inline typename enable_if, number >, detail::expression, number > > >::type - operator * (const number& a, const detail::expression >& b) -{ - return detail::expression, number > >( - detail::expression, number >(b.left_ref(), a)); +inline typename enable_if< + is_compatible_arithmetic_type, number>, + detail::expression, number>>>:: + type + operator*(const number &a, + const detail::expression> &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(b.left_ref(), a)); } // // Division: // template -inline detail::expression, number > - operator / (const number& a, const number& b) -{ - return detail::expression, number >(a, b); +inline detail::expression, + number> +operator/(const number &a, const number &b) { + return detail::expression, + number>(a, b); } template -inline typename enable_if >, detail::expression, V > >::type - operator / (const number& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression, V>>::type +operator/(const number &a, const V &b) { + return detail::expression, V>(a, + b); } template -inline typename enable_if >, detail::expression > >::type - operator / (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator / (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator / (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator / (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression>>::type +operator/(const V &a, const number &b) { + return detail::expression>(a, + b); +} +template +inline detail::expression, + detail::expression> +operator/(const number &a, + const detail::expression &b) { + return detail::expression, + detail::expression>(a, + b); +} +template +inline detail::expression, + number> +operator/(const detail::expression &a, + const number &b) { + return detail::expression, + number>(a, b); +} +template +inline detail::expression, + detail::expression> +operator/(const detail::expression &a, + const detail::expression &b) { + return detail::expression< + detail::divides, detail::expression, + detail::expression>(a, b); } template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator / (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, + typename detail::expression::result_type>, + detail::expression, + V>>::type +operator/(const detail::expression &a, + const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if::result_type>, detail::expression > >::type - operator / (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); +inline typename enable_if< + is_compatible_arithmetic_type< + V, + typename detail::expression::result_type>, + detail::expression>>::type +operator/(const V &a, + const detail::expression &b) { + return detail::expression>(a, + b); } // -// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// Repeat operator for negated arguments: propagate the negation to the top +// level to avoid temporaries: // -template -inline detail::expression, Arg1> > - operator / (const number& a, const detail::expression& b) -{ - return detail::expression, Arg1> >( - detail::expression, Arg1>(a, b.left_ref())); -} -template -inline detail::expression > > - operator / (const detail::expression& a, const number& b) -{ - return detail::expression > >( - detail::expression >(a.left_ref(), b)); +template +inline detail::expression< + detail::negate, detail::expression, Arg1>> +operator/(const number &a, + const detail::expression &b) { + return detail::expression< + detail::negate, detail::expression, Arg1>>( + detail::expression, Arg1>(a, + b.left_ref())); +} +template +inline detail::expression< + detail::negate, detail::expression>> +operator/(const detail::expression &a, + const number &b) { + return detail::expression< + detail::negate, detail::expression>>( + detail::expression>(a.left_ref(), + b)); } template -inline detail::expression, number > > - operator / (const number& a, const detail::expression >& b) -{ - return detail::expression, number > >( - detail::expression, number >(a, b.left_ref())); +inline detail::expression< + detail::negate, detail::expression, number>> +operator/(const number &a, + const detail::expression> &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(a, b.left_ref())); } template -inline detail::expression, number > > - operator / (const detail::expression >& a, const number& b) -{ - return detail::expression, number > >( - detail::expression, number >(a.left_ref(), b)); +inline detail::expression< + detail::negate, detail::expression, number>> +operator/(const detail::expression> &a, + const number &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(a.left_ref(), b)); } template -inline typename enable_if >, detail::expression, V > > >::type - operator / (const detail::expression >& a, const V& b) -{ - return detail::expression, V > >( - detail::expression, V>(a.left_ref(), b)); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression, V>>>::type +operator/(const detail::expression> &a, + const V &b) { + return detail::expression< + detail::negate, + detail::expression, V>>( + detail::expression, V>( + a.left_ref(), b)); } template -inline typename enable_if, number >, detail::expression, number > > >::type - operator / (const detail::expression >& a, const number& b) -{ - return detail::expression, number > >( - detail::expression, number >(a.left_ref(), b)); +inline typename enable_if< + is_compatible_arithmetic_type, number>, + detail::expression, number>>>:: + type + operator/(const detail::expression> &a, + const number &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(a.left_ref(), b)); } template -inline typename enable_if >, detail::expression > > >::type - operator / (const V& a, const detail::expression >& b) -{ - return detail::expression > >( - detail::expression >(a, b.left_ref())); +inline typename enable_if< + is_compatible_arithmetic_type>, + detail::expression>>>::type +operator/(const V &a, + const detail::expression> &b) { + return detail::expression< + detail::negate, + detail::expression>>( + detail::expression>( + a, b.left_ref())); } template -inline typename enable_if, number >, detail::expression, number > > >::type - operator / (const number& a, const detail::expression >& b) -{ - return detail::expression, number > >( - detail::expression, number >(a, b.left_ref())); +inline typename enable_if< + is_compatible_arithmetic_type, number>, + detail::expression, number>>>:: + type + operator/(const number &a, + const detail::expression> &b) { + return detail::expression< + detail::negate, detail::expression, number>>( + detail::expression, + number>(a, b.left_ref())); } // // Modulus: // template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, number > >::type - operator % (const number& a, const number& b) -{ - return detail::expression, number >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + number>>::type +operator%(const number &a, const number &b) { + return detail::expression, + number>(a, b); } template -inline typename enable_if_c >::value && (number_category::value == number_kind_integer), - detail::expression, V > >::type - operator % (const number& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type>::value && + (number_category::value == number_kind_integer), + detail::expression, V>>::type +operator%(const number &a, const V &b) { + return detail::expression, V>(a, + b); } template -inline typename enable_if_c >::value && (number_category::value == number_kind_integer), - detail::expression > >::type - operator % (const V& a, const number& b) -{ - return detail::expression >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type>::value && + (number_category::value == number_kind_integer), + detail::expression>>::type +operator%(const V &a, const number &b) { + return detail::expression>(a, + b); } template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, detail::expression > >::type - operator % (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + detail::expression>>::type +operator%(const number &a, + const detail::expression &b) { + return detail::expression, + detail::expression>(a, + b); } template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, number > >::type - operator % (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if_c::result_type>::value == number_kind_integer, - detail::expression, detail::expression > >::type - operator % (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + number>>::type +operator%(const detail::expression &a, + const number &b) { + return detail::expression, + number>(a, b); +} +template +inline typename enable_if_c< + number_category:: + result_type>::value == number_kind_integer, + detail::expression< + detail::modulus, detail::expression, + detail::expression>>::type +operator%(const detail::expression &a, + const detail::expression &b) { + return detail::expression< + detail::modulus, detail::expression, + detail::expression>(a, b); } template -inline typename enable_if_c::result_type>::value - && (number_category::result_type>::value == number_kind_integer), - detail::expression, V > >::type - operator % (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression, + V>>::type +operator%(const detail::expression &a, + const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if_c::result_type>::value - && (number_category::result_type>::value == number_kind_integer), - detail::expression > >::type - operator % (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression>>::type +operator%(const V &a, + const detail::expression &b) { + return detail::expression>(a, + b); } // // Left shift: // template -inline typename enable_if_c::value && (number_category::value == number_kind_integer), detail::expression, I > >::type - operator << (const number& a, const I& b) -{ - return detail::expression, I>(a, b); +inline typename enable_if_c< + is_integral::value && (number_category::value == number_kind_integer), + detail::expression, I>>::type +operator<<(const number &a, const I &b) { + return detail::expression, I>(a, b); } template -inline typename enable_if_c::value && (number_category::result_type>::value == number_kind_integer), - detail::expression, I> >::type - operator << (const detail::expression& a, const I& b) -{ - return detail::expression, I>(a, b); +inline typename enable_if_c< + is_integral::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression, + I>>::type +operator<<(const detail::expression &a, + const I &b) { + return detail::expression, I>( + a, b); } // // Right shift: // template -inline typename enable_if_c::value && (number_category::value == number_kind_integer), - detail::expression, I > >::type - operator >> (const number& a, const I& b) -{ - return detail::expression, I>(a, b); +inline typename enable_if_c< + is_integral::value && (number_category::value == number_kind_integer), + detail::expression, I>>::type +operator>>(const number &a, const I &b) { + return detail::expression, I>(a, b); } template -inline typename enable_if_c::value - && (number_category::result_type>::value == number_kind_integer), - detail::expression, I> >::type - operator >> (const detail::expression& a, const I& b) -{ - return detail::expression, I>(a, b); +inline typename enable_if_c< + is_integral::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression, + I>>::type +operator>>(const detail::expression &a, + const I &b) { + return detail::expression, I>( + a, b); } // // Bitwise AND: // template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, number > >::type - operator & (const number& a, const number& b) -{ - return detail::expression, number >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + number>>::type +operator&(const number &a, const number &b) { + return detail::expression, + number>(a, b); } template -inline typename enable_if_c >::value - && (number_category::value == number_kind_integer), - detail::expression, V > >::type - operator & (const number& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type>::value && + (number_category::value == number_kind_integer), + detail::expression, + V>>::type +operator&(const number &a, const V &b) { + return detail::expression, + V>(a, b); } template -inline typename enable_if_c >::value - && (number_category::value == number_kind_integer), - detail::expression > >::type - operator & (const V& a, const number& b) -{ - return detail::expression >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type>::value && + (number_category::value == number_kind_integer), + detail::expression>>::type +operator&(const V &a, const number &b) { + return detail::expression>(a, b); } template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, detail::expression > >::type - operator & (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + detail::expression>>::type +operator&(const number &a, + const detail::expression &b) { + return detail::expression, + detail::expression>(a, + b); } template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, number > >::type - operator & (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if_c::result_type>::value == number_kind_integer, - detail::expression, detail::expression > >::type - operator & (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + number>>::type +operator&(const detail::expression &a, + const number &b) { + return detail::expression, + number>(a, b); +} +template +inline typename enable_if_c< + number_category:: + result_type>::value == number_kind_integer, + detail::expression< + detail::bitwise_and, detail::expression, + detail::expression>>::type +operator&(const detail::expression &a, + const detail::expression &b) { + return detail::expression< + detail::bitwise_and, detail::expression, + detail::expression>(a, b); } template -inline typename enable_if_c::result_type>::value - && (number_category::result_type>::value == number_kind_integer), - detail::expression, V > >::type - operator & (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression, + V>>::type +operator&(const detail::expression &a, + const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if_c::result_type>::value - && (number_category::result_type>::value == number_kind_integer), - detail::expression > >::type - operator & (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression>>::type +operator&(const V &a, + const detail::expression &b) { + return detail::expression>(a, + b); } // // Bitwise OR: // template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, number > >::type - operator| (const number& a, const number& b) -{ - return detail::expression, number >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + number>>::type +operator|(const number &a, const number &b) { + return detail::expression, + number>(a, b); } template -inline typename enable_if_c >::value - && (number_category::value == number_kind_integer), - detail::expression, V > >::type - operator| (const number& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type>::value && + (number_category::value == number_kind_integer), + detail::expression, + V>>::type +operator|(const number &a, const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if_c >::value - && (number_category::value == number_kind_integer), - detail::expression > >::type - operator| (const V& a, const number& b) -{ - return detail::expression >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type>::value && + (number_category::value == number_kind_integer), + detail::expression>>::type +operator|(const V &a, const number &b) { + return detail::expression>( + a, b); } template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, detail::expression > >::type - operator| (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + detail::expression>>::type +operator|(const number &a, + const detail::expression &b) { + return detail::expression, + detail::expression>(a, + b); } template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, number > >::type - operator| (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if_c::result_type>::value == number_kind_integer, - detail::expression, detail::expression > >::type - operator| (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + number>>::type +operator|(const detail::expression &a, + const number &b) { + return detail::expression, + number>(a, b); +} +template +inline typename enable_if_c< + number_category:: + result_type>::value == number_kind_integer, + detail::expression< + detail::bitwise_or, detail::expression, + detail::expression>>::type +operator|(const detail::expression &a, + const detail::expression &b) { + return detail::expression< + detail::bitwise_or, detail::expression, + detail::expression>(a, b); } template -inline typename enable_if_c::result_type>::value - && (number_category::result_type>::value == number_kind_integer), - detail::expression, V > >::type - operator| (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression, + V>>::type +operator|(const detail::expression &a, + const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if_c::result_type>::value - && (number_category::result_type>::value == number_kind_integer), - detail::expression > >::type - operator| (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression>>::type +operator|(const V &a, + const detail::expression &b) { + return detail::expression>(a, + b); } // // Bitwise XOR: // template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, number > >::type - operator^ (const number& a, const number& b) -{ - return detail::expression, number >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + number>>::type +operator^(const number &a, const number &b) { + return detail::expression, + number>(a, b); } template -inline typename enable_if_c >::value - && (number_category::value == number_kind_integer), - detail::expression, V > >::type - operator^ (const number& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type>::value && + (number_category::value == number_kind_integer), + detail::expression, + V>>::type +operator^(const number &a, const V &b) { + return detail::expression, + V>(a, b); } template -inline typename enable_if_c >::value - && (number_category::value == number_kind_integer), - detail::expression > >::type - operator^ (const V& a, const number& b) -{ - return detail::expression >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type>::value && + (number_category::value == number_kind_integer), + detail::expression>>::type +operator^(const V &a, const number &b) { + return detail::expression>(a, b); } template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, detail::expression > >::type - operator^ (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + detail::expression>>::type +operator^(const number &a, + const detail::expression &b) { + return detail::expression, + detail::expression>(a, + b); } template -inline typename enable_if_c::value == number_kind_integer, - detail::expression, number > >::type - operator^ (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if_c::result_type>::value == number_kind_integer, - detail::expression, detail::expression > >::type - operator^ (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); +inline typename enable_if_c< + number_category::value == number_kind_integer, + detail::expression, + number>>::type +operator^(const detail::expression &a, + const number &b) { + return detail::expression, + number>(a, b); +} +template +inline typename enable_if_c< + number_category:: + result_type>::value == number_kind_integer, + detail::expression< + detail::bitwise_xor, detail::expression, + detail::expression>>::type +operator^(const detail::expression &a, + const detail::expression &b) { + return detail::expression< + detail::bitwise_xor, detail::expression, + detail::expression>(a, b); } template -inline typename enable_if_c::result_type>::value - && (number_category::result_type>::value == number_kind_integer), - detail::expression, V > >::type - operator^ (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression, + V>>::type +operator^(const detail::expression &a, + const V &b) { + return detail::expression, V>( + a, b); } template -inline typename enable_if_c::result_type>::value - && (number_category::result_type>::value == number_kind_integer), detail::expression > >::type - operator^ (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); +inline typename enable_if_c< + is_compatible_arithmetic_type< + V, typename detail::expression::result_type>::value && + (number_category::result_type>::value == + number_kind_integer), + detail::expression>>::type +operator^(const V &a, + const detail::expression &b) { + return detail::expression>(a, + b); } -}} // namespaces +} // namespace multiprecision +} // namespace boost #endif diff --git a/include/boost/multiprecision/detail/functions/constants.hpp b/include/boost/multiprecision/detail/functions/constants.hpp index a9c83f984..12b1e8430 100644 --- a/include/boost/multiprecision/detail/functions/constants.hpp +++ b/include/boost/multiprecision/detail/functions/constants.hpp @@ -3,331 +3,343 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // -// This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp -// +// This file has no include guards or namespaces - it's expanded inline inside +// default_ops.hpp +// -template -void calc_log2(T& num, unsigned digits) -{ - typedef typename boost::multiprecision::detail::canonical::type ui_type; - typedef typename mpl::front::type si_type; +template void calc_log2(T &num, unsigned digits) { + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename mpl::front::type si_type; - // - // String value with 1100 digits: - // - static const char* string_val = "0." - "6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875" - "4200148102057068573368552023575813055703267075163507596193072757082837143519030703862389167347112335" - "0115364497955239120475172681574932065155524734139525882950453007095326366642654104239157814952043740" - "4303855008019441706416715186447128399681717845469570262716310645461502572074024816377733896385506952" - "6066834113727387372292895649354702576265209885969320196505855476470330679365443254763274495125040606" - "9438147104689946506220167720424524529612687946546193165174681392672504103802546259656869144192871608" - "2938031727143677826548775664850856740776484514644399404614226031930967354025744460703080960850474866" - "3852313818167675143866747664789088143714198549423151997354880375165861275352916610007105355824987941" - "4729509293113897155998205654392871700072180857610252368892132449713893203784393530887748259701715591" - "0708823683627589842589185353024363421436706118923678919237231467232172053401649256872747782344535347" - "6481149418642386776774406069562657379600867076257199184734022651462837904883062033061144630073719489"; - // - // Check if we can just construct from string: - // - if(digits < 3640) // 3640 binary digits ~ 1100 decimal digits - { - num = string_val; - return; - } - // - // We calculate log2 from using the formula: - // - // ln(2) = 3/4 SUM[n>=0] ((-1)^n * N!^2 / (2^n(2n+1)!)) - // - // Numerator and denominator are calculated separately and then - // divided at the end, we also precalculate the terms up to n = 5 - // since these fit in a 32-bit integer anyway. - // - // See Gourdon, X., and Sebah, P. The logarithmic constant: log 2, Jan. 2004. - // Also http://www.mpfr.org/algorithms.pdf. - // - num = static_cast(1180509120uL); - T denom, next_term, temp; - denom = static_cast(1277337600uL); - next_term = static_cast(120uL); - si_type sign = -1; + // + // String value with 1100 digits: + // + static const char *string_val = + "0." + "693147180559945309417232121458176568075500134360255254120680009493393621" + "9696947156058633269964186875" + "420014810205706857336855202357581305570326707516350759619307275708283714" + "3519030703862389167347112335" + "011536449795523912047517268157493206515552473413952588295045300709532636" + "6642654104239157814952043740" + "430385500801944170641671518644712839968171784546957026271631064546150257" + "2074024816377733896385506952" + "606683411372738737229289564935470257626520988596932019650585547647033067" + "9365443254763274495125040606" + "943814710468994650622016772042452452961268794654619316517468139267250410" + "3802546259656869144192871608" + "293803172714367782654877566485085674077648451464439940461422603193096735" + "4025744460703080960850474866" + "385231381816767514386674766478908814371419854942315199735488037516586127" + "5352916610007105355824987941" + "472950929311389715599820565439287170007218085761025236889213244971389320" + "3784393530887748259701715591" + "070882368362758984258918535302436342143670611892367891923723146723217205" + "3401649256872747782344535347" + "648114941864238677677440606956265737960086707625719918473402265146283790" + "4883062033061144630073719489"; + // + // Check if we can just construct from string: + // + if (digits < 3640) // 3640 binary digits ~ 1100 decimal digits + { + num = string_val; + return; + } + // + // We calculate log2 from using the formula: + // + // ln(2) = 3/4 SUM[n>=0] ((-1)^n * N!^2 / (2^n(2n+1)!)) + // + // Numerator and denominator are calculated separately and then + // divided at the end, we also precalculate the terms up to n = 5 + // since these fit in a 32-bit integer anyway. + // + // See Gourdon, X., and Sebah, P. The logarithmic constant: log 2, Jan. 2004. + // Also http://www.mpfr.org/algorithms.pdf. + // + num = static_cast(1180509120uL); + T denom, next_term, temp; + denom = static_cast(1277337600uL); + next_term = static_cast(120uL); + si_type sign = -1; - ui_type limit = digits / 3 + 1; + ui_type limit = digits / 3 + 1; - for(ui_type n = 6; n < limit; ++n) - { - temp = static_cast(2); - eval_multiply(temp, ui_type(2 * n)); - eval_multiply(temp, ui_type(2 * n + 1)); - eval_multiply(num, temp); - eval_multiply(denom, temp); - sign = -sign; - eval_multiply(next_term, n); - eval_multiply(temp, next_term, next_term); - if(sign < 0) - temp.negate(); - eval_add(num, temp); - } - eval_multiply(denom, ui_type(4)); - eval_multiply(num, ui_type(3)); - INSTRUMENT_BACKEND(denom); - INSTRUMENT_BACKEND(num); - eval_divide(num, denom); - INSTRUMENT_BACKEND(num); + for (ui_type n = 6; n < limit; ++n) { + temp = static_cast(2); + eval_multiply(temp, ui_type(2 * n)); + eval_multiply(temp, ui_type(2 * n + 1)); + eval_multiply(num, temp); + eval_multiply(denom, temp); + sign = -sign; + eval_multiply(next_term, n); + eval_multiply(temp, next_term, next_term); + if (sign < 0) + temp.negate(); + eval_add(num, temp); + } + eval_multiply(denom, ui_type(4)); + eval_multiply(num, ui_type(3)); + INSTRUMENT_BACKEND(denom); + INSTRUMENT_BACKEND(num); + eval_divide(num, denom); + INSTRUMENT_BACKEND(num); } -template -void calc_e(T& result, unsigned digits) -{ - typedef typename mpl::front::type ui_type; - // - // 1100 digits in string form: - // - const char* string_val = "2." - "7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274" - "2746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901" - "1573834187930702154089149934884167509244761460668082264800168477411853742345442437107539077744992069" - "5517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416" - "9283681902551510865746377211125238978442505695369677078544996996794686445490598793163688923009879312" - "7736178215424999229576351482208269895193668033182528869398496465105820939239829488793320362509443117" - "3012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509" - "9618188159304169035159888851934580727386673858942287922849989208680582574927961048419844436346324496" - "8487560233624827041978623209002160990235304369941849146314093431738143640546253152096183690888707016" - "7683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354" - "0212340784981933432106817012100562788023519303322474501585390473041995777709350366041699732972508869"; - // - // Check if we can just construct from string: - // - if(digits < 3640) // 3640 binary digits ~ 1100 decimal digits - { - result = string_val; - return; - } +template void calc_e(T &result, unsigned digits) { + typedef typename mpl::front::type ui_type; + // + // 1100 digits in string form: + // + const char *string_val = "2." + "718281828459045235360287471352662497757247093699959" + "5749669676277240766303535475945713821785251664274" + "274663919320030599218174135966290435729003342952605" + "9563073813232862794349076323382988075319525101901" + "157383418793070215408914993488416750924476146066808" + "2264800168477411853742345442437107539077744992069" + "551702761838606261331384583000752044933826560297606" + "7371132007093287091274437470472306969772093101416" + "928368190255151086574637721112523897844250569536967" + "7078544996996794686445490598793163688923009879312" + "773617821542499922957635148220826989519366803318252" + "8869398496465105820939239829488793320362509443117" + "301238197068416140397019837679320683282376464804295" + "3118023287825098194558153017567173613320698112509" + "961818815930416903515988885193458072738667385894228" + "7922849989208680582574927961048419844436346324496" + "848756023362482704197862320900216099023530436994184" + "9146314093431738143640546253152096183690888707016" + "768396424378140592714563549061303107208510383750510" + "1157477041718986106873969655212671546889570350354" + "021234078498193343210681701210056278802351930332247" + "4501585390473041995777709350366041699732972508869"; + // + // Check if we can just construct from string: + // + if (digits < 3640) // 3640 binary digits ~ 1100 decimal digits + { + result = string_val; + return; + } - T lim; - lim = ui_type(1); - eval_ldexp(lim, lim, digits); + T lim; + lim = ui_type(1); + eval_ldexp(lim, lim, digits); - // - // Standard evaluation from the definition of e: http://functions.wolfram.com/Constants/E/02/ - // - result = ui_type(2); - T denom; - denom = ui_type(1); - ui_type i = 2; - do{ - eval_multiply(denom, i); - eval_multiply(result, i); - eval_add(result, ui_type(1)); - ++i; - }while(denom.compare(lim) <= 0); - eval_divide(result, denom); + // + // Standard evaluation from the definition of e: + // http://functions.wolfram.com/Constants/E/02/ + // + result = ui_type(2); + T denom; + denom = ui_type(1); + ui_type i = 2; + do { + eval_multiply(denom, i); + eval_multiply(result, i); + eval_add(result, ui_type(1)); + ++i; + } while (denom.compare(lim) <= 0); + eval_divide(result, denom); } -template -void calc_pi(T& result, unsigned digits) -{ - typedef typename mpl::front::type ui_type; - typedef typename mpl::front::type real_type; - // - // 1100 digits in string form: - // - const char* string_val = "3." - "1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679" - "8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196" - "4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273" - "7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094" - "3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912" - "9833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132" - "0005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235" - "4201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859" - "5024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303" - "5982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989" - "3809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913152"; - // - // Check if we can just construct from string: - // - if(digits < 3640) // 3640 binary digits ~ 1100 decimal digits - { - result = string_val; - return; - } +template void calc_pi(T &result, unsigned digits) { + typedef typename mpl::front::type ui_type; + typedef typename mpl::front::type real_type; + // + // 1100 digits in string form: + // + const char *string_val = "3." + "141592653589793238462643383279502884197169399375105" + "8209749445923078164062862089986280348253421170679" + "821480865132823066470938446095505822317253594081284" + "8111745028410270193852110555964462294895493038196" + "442881097566593344612847564823378678316527120190914" + "5648566923460348610454326648213393607260249141273" + "724587006606315588174881520920962829254091715364367" + "8925903600113305305488204665213841469519415116094" + "330572703657595919530921861173819326117931051185480" + "7446237996274956735188575272489122793818301194912" + "983367336244065664308602139494639522473719070217986" + "0943702770539217176293176752384674818467669405132" + "000568127145263560827785771342757789609173637178721" + "4684409012249534301465495853710507922796892589235" + "420199561121290219608640344181598136297747713099605" + "1870721134999999837297804995105973173281609631859" + "502445945534690830264252230825334468503526193118817" + "1010003137838752886587533208381420617177669147303" + "598253490428755468731159562863882353787593751957781" + "8577805321712268066130019278766111959092164201989" + "380952572010654858632788659361533818279682303019520" + "3530185296899577362259941389124972177528347913152"; + // + // Check if we can just construct from string: + // + if (digits < 3640) // 3640 binary digits ~ 1100 decimal digits + { + result = string_val; + return; + } - T a; - a = ui_type(1); - T b; - T A(a); - T B; - B = real_type(0.5f); - T D; - D = real_type(0.25f); + T a; + a = ui_type(1); + T b; + T A(a); + T B; + B = real_type(0.5f); + T D; + D = real_type(0.25f); - T lim; - lim = ui_type(1); - eval_ldexp(lim, lim, -(int)digits); + T lim; + lim = ui_type(1); + eval_ldexp(lim, lim, -(int)digits); - // - // This algorithm is from: - // Schonhage, A., Grotefeld, A. F. W., and Vetter, E. Fast Algorithms: A Multitape Turing - // Machine Implementation. BI Wissenschaftverlag, 1994. - // Also described in MPFR's algorithm guide: http://www.mpfr.org/algorithms.pdf. - // - // Let: - // a[0] = A[0] = 1 - // B[0] = 1/2 - // D[0] = 1/4 - // Then: - // S[k+1] = (A[k]+B[k]) / 4 - // b[k] = sqrt(B[k]) - // a[k+1] = a[k]^2 - // B[k+1] = 2(A[k+1]-S[k+1]) - // D[k+1] = D[k] - 2^k(A[k+1]-B[k+1]) - // Stop when |A[k]-B[k]| <= 2^(k-p) - // and PI = B[k]/D[k] + // + // This algorithm is from: + // Schonhage, A., Grotefeld, A. F. W., and Vetter, E. Fast Algorithms: A + // Multitape Turing Machine Implementation. BI Wissenschaftverlag, 1994. Also + // described in MPFR's algorithm guide: http://www.mpfr.org/algorithms.pdf. + // + // Let: + // a[0] = A[0] = 1 + // B[0] = 1/2 + // D[0] = 1/4 + // Then: + // S[k+1] = (A[k]+B[k]) / 4 + // b[k] = sqrt(B[k]) + // a[k+1] = a[k]^2 + // B[k+1] = 2(A[k+1]-S[k+1]) + // D[k+1] = D[k] - 2^k(A[k+1]-B[k+1]) + // Stop when |A[k]-B[k]| <= 2^(k-p) + // and PI = B[k]/D[k] - unsigned k = 1; + unsigned k = 1; - do - { - eval_add(result, A, B); - eval_ldexp(result, result, -2); - eval_sqrt(b, B); - eval_add(a, b); - eval_ldexp(a, a, -1); - eval_multiply(A, a, a); - eval_subtract(B, A, result); - eval_ldexp(B, B, 1); - eval_subtract(result, A, B); - bool neg = eval_get_sign(result) < 0; - if(neg) - result.negate(); - if(result.compare(lim) <= 0) - break; - if(neg) - result.negate(); - eval_ldexp(result, result, k - 1); - eval_subtract(D, result); - ++k; - eval_ldexp(lim, lim, 1); - } - while(true); + do { + eval_add(result, A, B); + eval_ldexp(result, result, -2); + eval_sqrt(b, B); + eval_add(a, b); + eval_ldexp(a, a, -1); + eval_multiply(A, a, a); + eval_subtract(B, A, result); + eval_ldexp(B, B, 1); + eval_subtract(result, A, B); + bool neg = eval_get_sign(result) < 0; + if (neg) + result.negate(); + if (result.compare(lim) <= 0) + break; + if (neg) + result.negate(); + eval_ldexp(result, result, k - 1); + eval_subtract(D, result); + ++k; + eval_ldexp(lim, lim, 1); + } while (true); - eval_divide(result, B, D); + eval_divide(result, B, D); } -template -struct constant_initializer -{ - static void do_nothing() - { - init.do_nothing(); - } +template struct constant_initializer { + static void do_nothing() { init.do_nothing(); } + private: - struct initializer - { - initializer() - { - F(); - } - void do_nothing()const{} - }; - static const initializer init; + struct initializer { + initializer() { F(); } + void do_nothing() const {} + }; + static const initializer init; }; -template -typename constant_initializer::initializer const constant_initializer::init; +template +typename constant_initializer::initializer const + constant_initializer::init; -template -const T& get_constant_ln2() -{ - static BOOST_MP_THREAD_LOCAL T result; - static BOOST_MP_THREAD_LOCAL long digits = 0; +template const T &get_constant_ln2() { + static BOOST_MP_THREAD_LOCAL T result; + static BOOST_MP_THREAD_LOCAL long digits = 0; #ifndef BOOST_MP_USING_THREAD_LOCAL - static BOOST_MP_THREAD_LOCAL bool b = false; - constant_initializer >::do_nothing(); + static BOOST_MP_THREAD_LOCAL bool b = false; + constant_initializer>::do_nothing(); - if(!b || (digits != boost::multiprecision::detail::digits2 >::value())) - { - b = true; + if (!b || + (digits != boost::multiprecision::detail::digits2>::value())) { + b = true; #else - if ((digits != boost::multiprecision::detail::digits2 >::value())) - { + if ((digits != boost::multiprecision::detail::digits2>::value())) { #endif - calc_log2(result, boost::multiprecision::detail::digits2 >::value()); - digits = boost::multiprecision::detail::digits2 >::value(); - } + calc_log2( + result, + boost::multiprecision::detail::digits2>::value()); + digits = boost::multiprecision::detail::digits2>::value(); + } - return result; + return result; } -template -const T& get_constant_e() -{ - static BOOST_MP_THREAD_LOCAL T result; - static BOOST_MP_THREAD_LOCAL long digits = 0; +template const T &get_constant_e() { + static BOOST_MP_THREAD_LOCAL T result; + static BOOST_MP_THREAD_LOCAL long digits = 0; #ifndef BOOST_MP_USING_THREAD_LOCAL - static BOOST_MP_THREAD_LOCAL bool b = false; - constant_initializer >::do_nothing(); + static BOOST_MP_THREAD_LOCAL bool b = false; + constant_initializer>::do_nothing(); - if (!b || (digits != boost::multiprecision::detail::digits2 >::value())) - { - b = true; + if (!b || + (digits != boost::multiprecision::detail::digits2>::value())) { + b = true; #else - if ((digits != boost::multiprecision::detail::digits2 >::value())) - { + if ((digits != boost::multiprecision::detail::digits2>::value())) { #endif - calc_e(result, boost::multiprecision::detail::digits2 >::value()); - digits = boost::multiprecision::detail::digits2 >::value(); - } + calc_e(result, + boost::multiprecision::detail::digits2>::value()); + digits = boost::multiprecision::detail::digits2>::value(); + } - return result; + return result; } -template -const T& get_constant_pi() -{ - static BOOST_MP_THREAD_LOCAL T result; - static BOOST_MP_THREAD_LOCAL long digits = 0; +template const T &get_constant_pi() { + static BOOST_MP_THREAD_LOCAL T result; + static BOOST_MP_THREAD_LOCAL long digits = 0; #ifndef BOOST_MP_USING_THREAD_LOCAL - static BOOST_MP_THREAD_LOCAL bool b = false; - constant_initializer >::do_nothing(); + static BOOST_MP_THREAD_LOCAL bool b = false; + constant_initializer>::do_nothing(); - if (!b || (digits != boost::multiprecision::detail::digits2 >::value())) - { - b = true; + if (!b || + (digits != boost::multiprecision::detail::digits2>::value())) { + b = true; #else - if ((digits != boost::multiprecision::detail::digits2 >::value())) - { + if ((digits != boost::multiprecision::detail::digits2>::value())) { #endif - calc_pi(result, boost::multiprecision::detail::digits2 >::value()); - digits = boost::multiprecision::detail::digits2 >::value(); - } + calc_pi(result, + boost::multiprecision::detail::digits2>::value()); + digits = boost::multiprecision::detail::digits2>::value(); + } - return result; + return result; } -template -const T& get_constant_one_over_epsilon() -{ - static BOOST_MP_THREAD_LOCAL T result; - static BOOST_MP_THREAD_LOCAL long digits = 0; +template const T &get_constant_one_over_epsilon() { + static BOOST_MP_THREAD_LOCAL T result; + static BOOST_MP_THREAD_LOCAL long digits = 0; #ifndef BOOST_MP_USING_THREAD_LOCAL - static BOOST_MP_THREAD_LOCAL bool b = false; - constant_initializer >::do_nothing(); + static BOOST_MP_THREAD_LOCAL bool b = false; + constant_initializer>::do_nothing(); - if (!b || (digits != boost::multiprecision::detail::digits2 >::value())) - { - b = true; + if (!b || + (digits != boost::multiprecision::detail::digits2>::value())) { + b = true; #else - if ((digits != boost::multiprecision::detail::digits2 >::value())) - { + if ((digits != boost::multiprecision::detail::digits2>::value())) { #endif - typedef typename mpl::front::type ui_type; - result = static_cast(1u); - eval_divide(result, std::numeric_limits >::epsilon().backend()); - } + typedef typename mpl::front::type ui_type; + result = static_cast(1u); + eval_divide(result, std::numeric_limits>::epsilon().backend()); + } - return result; + return result; } - diff --git a/include/boost/multiprecision/detail/functions/trig.hpp b/include/boost/multiprecision/detail/functions/trig.hpp index c001f955c..66f6bc7d1 100644 --- a/include/boost/multiprecision/detail/functions/trig.hpp +++ b/include/boost/multiprecision/detail/functions/trig.hpp @@ -10,17 +10,17 @@ // in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 // // This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp -// +// #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:6326) // comparison of two constants +#pragma warning(disable : 6326) // comparison of two constants #endif template -void hyp0F1(T& result, const T& b, const T& x) +void hyp0F1(T &result, const T &b, const T &x) { - typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type si_type; typedef typename boost::multiprecision::detail::canonical::type ui_type; // Compute the series representation of Hypergeometric0F1 taken from @@ -28,8 +28,8 @@ void hyp0F1(T& result, const T& b, const T& x) // There are no checks on input range or parameter boundaries. T x_pow_n_div_n_fact(x); - T pochham_b (b); - T bp (b); + T pochham_b(b); + T bp(b); eval_divide(result, x_pow_n_div_n_fact, pochham_b); eval_add(result, ui_type(1)); @@ -40,15 +40,16 @@ void hyp0F1(T& result, const T& b, const T& x) tol = ui_type(1); eval_ldexp(tol, tol, 1 - boost::multiprecision::detail::digits2 >::value()); eval_multiply(tol, result); - if(eval_get_sign(tol) < 0) + if (eval_get_sign(tol) < 0) tol.negate(); T term; - const int series_limit = - boost::multiprecision::detail::digits2 >::value() < 100 - ? 100 : boost::multiprecision::detail::digits2 >::value(); + const int series_limit = + boost::multiprecision::detail::digits2 >::value() < 100 + ? 100 + : boost::multiprecision::detail::digits2 >::value(); // Series expansion of hyperg_0f1(; b; x). - for(n = 2; n < series_limit; ++n) + for (n = 2; n < series_limit; ++n) { eval_multiply(x_pow_n_div_n_fact, x); eval_divide(x_pow_n_div_n_fact, n); @@ -59,22 +60,21 @@ void hyp0F1(T& result, const T& b, const T& x) eval_add(result, term); bool neg_term = eval_get_sign(term) < 0; - if(neg_term) + if (neg_term) term.negate(); - if(term.compare(tol) <= 0) + if (term.compare(tol) <= 0) break; } - if(n >= series_limit) + if (n >= series_limit) BOOST_THROW_EXCEPTION(std::runtime_error("H0F1 Failed to Converge")); } - template -void eval_sin(T& result, const T& x) +void eval_sin(T &result, const T &x) { BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The sin function is only valid for floating point types."); - if(&result == &x) + if (&result == &x) { T temp; eval_sin(temp, x); @@ -82,18 +82,18 @@ void eval_sin(T& result, const T& x) return; } - typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type si_type; typedef typename boost::multiprecision::detail::canonical::type ui_type; - typedef typename mpl::front::type fp_type; + typedef typename mpl::front::type fp_type; - switch(eval_fpclassify(x)) + switch (eval_fpclassify(x)) { case FP_INFINITE: case FP_NAN: - if(std::numeric_limits >::has_quiet_NaN) + if (std::numeric_limits >::has_quiet_NaN) { result = std::numeric_limits >::quiet_NaN().backend(); - errno = EDOM; + errno = EDOM; } else BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type.")); @@ -101,7 +101,7 @@ void eval_sin(T& result, const T& x) case FP_ZERO: result = x; return; - default: ; + default:; } // Local copy of the argument @@ -112,7 +112,7 @@ void eval_sin(T& result, const T& x) // The argument xx will be reduced to 0 <= xx <= pi/2. bool b_negate_sin = false; - if(eval_get_sign(x) < 0) + if (eval_get_sign(x) < 0) { xx.negate(); b_negate_sin = !b_negate_sin; @@ -120,7 +120,7 @@ void eval_sin(T& result, const T& x) T n_pi, t; // Remove even multiples of pi. - if(xx.compare(get_constant_pi()) > 0) + if (xx.compare(get_constant_pi()) > 0) { eval_divide(n_pi, xx, get_constant_pi()); eval_trunc(n_pi, n_pi); @@ -140,7 +140,7 @@ void eval_sin(T& result, const T& x) BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific)); // Adjust signs if the multiple of pi is not even. - if(!b_n_pi_is_even) + if (!b_n_pi_is_even) { b_negate_sin = !b_negate_sin; } @@ -148,7 +148,7 @@ void eval_sin(T& result, const T& x) // Reduce the argument to 0 <= xx <= pi/2. eval_ldexp(t, get_constant_pi(), -1); - if(xx.compare(t) > 0) + if (xx.compare(t) > 0) { eval_subtract(xx, get_constant_pi(), xx); BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific)); @@ -159,18 +159,19 @@ void eval_sin(T& result, const T& x) const bool b_pi_half = eval_get_sign(t) == 0; // Check if the reduced argument is very close to 0 or pi/2. - const bool b_near_zero = xx.compare(fp_type(1e-1)) < 0; - const bool b_near_pi_half = t.compare(fp_type(1e-1)) < 0;; + const bool b_near_zero = xx.compare(fp_type(1e-1)) < 0; + const bool b_near_pi_half = t.compare(fp_type(1e-1)) < 0; + ; - if(b_zero) + if (b_zero) { result = ui_type(0); } - else if(b_pi_half) + else if (b_pi_half) { result = ui_type(1); } - else if(b_near_zero) + else if (b_near_zero) { eval_multiply(t, xx, xx); eval_divide(t, si_type(-4)); @@ -180,7 +181,7 @@ void eval_sin(T& result, const T& x) BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific)); eval_multiply(result, xx); } - else if(b_near_pi_half) + else if (b_near_pi_half) { eval_multiply(t, t); eval_divide(t, si_type(-4)); @@ -196,7 +197,7 @@ void eval_sin(T& result, const T& x) // divide by three identity a certain number of times. // Here we use division by 3^9 --> (19683 = 3^9). - static const si_type n_scale = 9; + static const si_type n_scale = 9; static const si_type n_three_pow_scale = static_cast(19683L); eval_divide(xx, n_three_pow_scale); @@ -211,7 +212,7 @@ void eval_sin(T& result, const T& x) eval_multiply(result, xx); // Convert back using multiple angle identity. - for(boost::int32_t k = static_cast(0); k < n_scale; k++) + for (boost::int32_t k = static_cast(0); k < n_scale; k++) { // Rescale the cosine value using the multiple angle identity. eval_multiply(t2, result, ui_type(3)); @@ -222,15 +223,15 @@ void eval_sin(T& result, const T& x) } } - if(b_negate_sin) + if (b_negate_sin) result.negate(); } template -void eval_cos(T& result, const T& x) +void eval_cos(T &result, const T &x) { BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The cos function is only valid for floating point types."); - if(&result == &x) + if (&result == &x) { T temp; eval_cos(temp, x); @@ -238,18 +239,18 @@ void eval_cos(T& result, const T& x) return; } - typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type si_type; typedef typename boost::multiprecision::detail::canonical::type ui_type; - typedef typename mpl::front::type fp_type; + typedef typename mpl::front::type fp_type; - switch(eval_fpclassify(x)) + switch (eval_fpclassify(x)) { case FP_INFINITE: case FP_NAN: - if(std::numeric_limits >::has_quiet_NaN) + if (std::numeric_limits >::has_quiet_NaN) { result = std::numeric_limits >::quiet_NaN().backend(); - errno = EDOM; + errno = EDOM; } else BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type.")); @@ -257,7 +258,7 @@ void eval_cos(T& result, const T& x) case FP_ZERO: result = ui_type(1); return; - default: ; + default:; } // Local copy of the argument @@ -268,14 +269,14 @@ void eval_cos(T& result, const T& x) // The argument xx will be reduced to 0 <= xx <= pi/2. bool b_negate_cos = false; - if(eval_get_sign(x) < 0) + if (eval_get_sign(x) < 0) { xx.negate(); } T n_pi, t; // Remove even multiples of pi. - if(xx.compare(get_constant_pi()) > 0) + if (xx.compare(get_constant_pi()) > 0) { eval_divide(t, xx, get_constant_pi()); eval_trunc(n_pi, t); @@ -303,7 +304,7 @@ void eval_cos(T& result, const T& x) eval_fmod(t, n_pi, t); const bool b_n_pi_is_even = eval_get_sign(t) == 0; - if(!b_n_pi_is_even) + if (!b_n_pi_is_even) { b_negate_cos = !b_negate_cos; } @@ -312,7 +313,7 @@ void eval_cos(T& result, const T& x) // Reduce the argument to 0 <= xx <= pi/2. eval_ldexp(t, get_constant_pi(), -1); int com = xx.compare(t); - if(com > 0) + if (com > 0) { eval_subtract(xx, get_constant_pi(), xx); b_negate_cos = !b_negate_cos; @@ -323,17 +324,17 @@ void eval_cos(T& result, const T& x) const bool b_pi_half = com == 0; // Check if the reduced argument is very close to 0. - const bool b_near_zero = xx.compare(fp_type(1e-1)) < 0; + const bool b_near_zero = xx.compare(fp_type(1e-1)) < 0; - if(b_zero) + if (b_zero) { result = si_type(1); } - else if(b_pi_half) + else if (b_pi_half) { result = si_type(0); } - else if(b_near_zero) + else if (b_near_zero) { eval_multiply(t, xx, xx); eval_divide(t, si_type(-4)); @@ -346,15 +347,15 @@ void eval_cos(T& result, const T& x) eval_subtract(t, xx); eval_sin(result, t); } - if(b_negate_cos) + if (b_negate_cos) result.negate(); } template -void eval_tan(T& result, const T& x) +void eval_tan(T &result, const T &x) { BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The tan function is only valid for floating point types."); - if(&result == &x) + if (&result == &x) { T temp; eval_tan(temp, x); @@ -368,21 +369,21 @@ void eval_tan(T& result, const T& x) } template -void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x) +void hyp2F1(T &result, const T &a, const T &b, const T &c, const T &x) { - // Compute the series representation of hyperg_2f1 taken from - // Abramowitz and Stegun 15.1.1. - // There are no checks on input range or parameter boundaries. + // Compute the series representation of hyperg_2f1 taken from + // Abramowitz and Stegun 15.1.1. + // There are no checks on input range or parameter boundaries. typedef typename boost::multiprecision::detail::canonical::type ui_type; T x_pow_n_div_n_fact(x); - T pochham_a (a); - T pochham_b (b); - T pochham_c (c); - T ap (a); - T bp (b); - T cp (c); + T pochham_a(a); + T pochham_b(b); + T pochham_c(c); + T ap(a); + T bp(b); + T cp(c); eval_multiply(result, pochham_a, pochham_b); eval_divide(result, pochham_c); @@ -392,17 +393,18 @@ void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x) T lim; eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2 >::value()); - if(eval_get_sign(lim) < 0) + if (eval_get_sign(lim) < 0) lim.negate(); ui_type n; - T term; + T term; - const unsigned series_limit = - boost::multiprecision::detail::digits2 >::value() < 100 - ? 100 : boost::multiprecision::detail::digits2 >::value(); + const unsigned series_limit = + boost::multiprecision::detail::digits2 >::value() < 100 + ? 100 + : boost::multiprecision::detail::digits2 >::value(); // Series expansion of hyperg_2f1(a, b; c; x). - for(n = 2; n < series_limit; ++n) + for (n = 2; n < series_limit; ++n) { eval_multiply(x_pow_n_div_n_fact, x); eval_divide(x_pow_n_div_n_fact, n); @@ -419,37 +421,37 @@ void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x) eval_multiply(term, x_pow_n_div_n_fact); eval_add(result, term); - if(eval_get_sign(term) < 0) + if (eval_get_sign(term) < 0) term.negate(); - if(lim.compare(term) >= 0) + if (lim.compare(term) >= 0) break; } - if(n > series_limit) + if (n > series_limit) BOOST_THROW_EXCEPTION(std::runtime_error("H2F1 failed to converge.")); } template -void eval_asin(T& result, const T& x) +void eval_asin(T &result, const T &x) { BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The asin function is only valid for floating point types."); typedef typename boost::multiprecision::detail::canonical::type ui_type; - typedef typename mpl::front::type fp_type; + typedef typename mpl::front::type fp_type; - if(&result == &x) + if (&result == &x) { T t(x); eval_asin(result, t); return; } - switch(eval_fpclassify(x)) + switch (eval_fpclassify(x)) { case FP_NAN: case FP_INFINITE: - if(std::numeric_limits >::has_quiet_NaN) + if (std::numeric_limits >::has_quiet_NaN) { result = std::numeric_limits >::quiet_NaN().backend(); - errno = EDOM; + errno = EDOM; } else BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type.")); @@ -457,37 +459,37 @@ void eval_asin(T& result, const T& x) case FP_ZERO: result = x; return; - default: ; + default:; } const bool b_neg = eval_get_sign(x) < 0; T xx(x); - if(b_neg) + if (b_neg) xx.negate(); int c = xx.compare(ui_type(1)); - if(c > 0) + if (c > 0) { - if(std::numeric_limits >::has_quiet_NaN) + if (std::numeric_limits >::has_quiet_NaN) { result = std::numeric_limits >::quiet_NaN().backend(); - errno = EDOM; + errno = EDOM; } else BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type.")); return; } - else if(c == 0) + else if (c == 0) { result = get_constant_pi(); eval_ldexp(result, result, -1); - if(b_neg) + if (b_neg) result.negate(); return; } - if(xx.compare(fp_type(1e-4)) < 0) + if (xx.compare(fp_type(1e-4)) < 0) { // http://functions.wolfram.com/ElementaryFunctions/ArcSin/26/01/01/ eval_multiply(xx, xx); @@ -498,7 +500,7 @@ void eval_asin(T& result, const T& x) eval_multiply(result, x); return; } - else if(xx.compare(fp_type(1 - 1e-4f)) > 0) + else if (xx.compare(fp_type(1 - 1e-4f)) > 0) { T dx1; T t1, t2; @@ -513,7 +515,7 @@ void eval_asin(T& result, const T& x) eval_ldexp(t1, get_constant_pi(), -1); result.negate(); eval_add(result, t1); - if(b_neg) + if (b_neg) result.negate(); return; } @@ -528,16 +530,16 @@ void eval_asin(T& result, const T& x) result = (guess_type)(std::asin(dd)); - // Newton-Raphson iteration, we should double our precision with each iteration, + // Newton-Raphson iteration, we should double our precision with each iteration, // in practice this seems to not quite work in all cases... so terminate when we - // have at least 2/3 of the digits correct on the assumption that the correction + // have at least 2/3 of the digits correct on the assumption that the correction // we've just added will finish the job... boost::intmax_t current_precision = eval_ilogb(result); - boost::intmax_t target_precision = current_precision - 1 - (std::numeric_limits >::digits * 2) / 3; + boost::intmax_t target_precision = current_precision - 1 - (std::numeric_limits >::digits * 2) / 3; // Newton-Raphson iteration - while(current_precision > target_precision) + while (current_precision > target_precision) { T sine, cosine; eval_sin(sine, result); @@ -546,27 +548,27 @@ void eval_asin(T& result, const T& x) eval_divide(sine, cosine); eval_subtract(result, sine); current_precision = eval_ilogb(sine); - if(current_precision <= (std::numeric_limits::min)() + 1) + if (current_precision <= (std::numeric_limits::min)() + 1) break; } - if(b_neg) + if (b_neg) result.negate(); } template -inline void eval_acos(T& result, const T& x) +inline void eval_acos(T &result, const T &x) { BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The acos function is only valid for floating point types."); typedef typename boost::multiprecision::detail::canonical::type ui_type; - switch(eval_fpclassify(x)) + switch (eval_fpclassify(x)) { case FP_NAN: case FP_INFINITE: - if(std::numeric_limits >::has_quiet_NaN) + if (std::numeric_limits >::has_quiet_NaN) { result = std::numeric_limits >::quiet_NaN().backend(); - errno = EDOM; + errno = EDOM; } else BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type.")); @@ -580,20 +582,20 @@ inline void eval_acos(T& result, const T& x) eval_abs(result, x); int c = result.compare(ui_type(1)); - if(c > 0) + if (c > 0) { - if(std::numeric_limits >::has_quiet_NaN) + if (std::numeric_limits >::has_quiet_NaN) { result = std::numeric_limits >::quiet_NaN().backend(); - errno = EDOM; + errno = EDOM; } else BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type.")); return; } - else if(c == 0) + else if (c == 0) { - if(eval_get_sign(x) < 0) + if (eval_get_sign(x) < 0) result = get_constant_pi(); else result = ui_type(0); @@ -608,24 +610,24 @@ inline void eval_acos(T& result, const T& x) } template -void eval_atan(T& result, const T& x) +void eval_atan(T &result, const T &x) { BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The atan function is only valid for floating point types."); - typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type si_type; typedef typename boost::multiprecision::detail::canonical::type ui_type; - typedef typename mpl::front::type fp_type; + typedef typename mpl::front::type fp_type; - switch(eval_fpclassify(x)) + switch (eval_fpclassify(x)) { case FP_NAN: result = x; - errno = EDOM; + errno = EDOM; return; case FP_ZERO: result = x; return; case FP_INFINITE: - if(eval_get_sign(x) < 0) + if (eval_get_sign(x) < 0) { eval_ldexp(result, get_constant_pi(), -1); result.negate(); @@ -633,16 +635,16 @@ void eval_atan(T& result, const T& x) else eval_ldexp(result, get_constant_pi(), -1); return; - default: ; + default:; } const bool b_neg = eval_get_sign(x) < 0; T xx(x); - if(b_neg) + if (b_neg) xx.negate(); - if(xx.compare(fp_type(0.1)) < 0) + if (xx.compare(fp_type(0.1)) < 0) { T t1, t2, t3; t1 = ui_type(1); @@ -655,7 +657,7 @@ void eval_atan(T& result, const T& x) return; } - if(xx.compare(fp_type(10)) > 0) + if (xx.compare(fp_type(10)) > 0) { T t1, t2, t3; t1 = fp_type(0.5f); @@ -665,31 +667,30 @@ void eval_atan(T& result, const T& x) eval_divide(xx, si_type(-1), xx); hyp2F1(result, t1, t2, t3, xx); eval_divide(result, x); - if(!b_neg) + if (!b_neg) result.negate(); eval_ldexp(t1, get_constant_pi(), -1); eval_add(result, t1); - if(b_neg) + if (b_neg) result.negate(); return; } - // Get initial estimate using standard math function atan. fp_type d; eval_convert_to(&d, xx); result = fp_type(std::atan(d)); - // Newton-Raphson iteration, we should double our precision with each iteration, + // Newton-Raphson iteration, we should double our precision with each iteration, // in practice this seems to not quite work in all cases... so terminate when we - // have at least 2/3 of the digits correct on the assumption that the correction + // have at least 2/3 of the digits correct on the assumption that the correction // we've just added will finish the job... boost::intmax_t current_precision = eval_ilogb(result); - boost::intmax_t target_precision = current_precision - 1 - (std::numeric_limits >::digits * 2) / 3; + boost::intmax_t target_precision = current_precision - 1 - (std::numeric_limits >::digits * 2) / 3; T s, c, t; - while(current_precision > target_precision) + while (current_precision > target_precision) { eval_sin(s, result); eval_cos(c, result); @@ -698,24 +699,24 @@ void eval_atan(T& result, const T& x) eval_multiply(s, t, c); eval_add(result, s); current_precision = eval_ilogb(s); - if(current_precision <= (std::numeric_limits::min)() + 1) + if (current_precision <= (std::numeric_limits::min)() + 1) break; } - if(b_neg) + if (b_neg) result.negate(); } template -void eval_atan2(T& result, const T& y, const T& x) +void eval_atan2(T &result, const T &y, const T &x) { BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The atan2 function is only valid for floating point types."); - if(&result == &y) + if (&result == &y) { T temp(y); eval_atan2(result, temp, x); return; } - else if(&result == &x) + else if (&result == &x) { T temp(x); eval_atan2(result, y, temp); @@ -724,82 +725,82 @@ void eval_atan2(T& result, const T& y, const T& x) typedef typename boost::multiprecision::detail::canonical::type ui_type; - switch(eval_fpclassify(y)) + switch (eval_fpclassify(y)) { case FP_NAN: result = y; - errno = EDOM; + errno = EDOM; return; case FP_ZERO: + { + if (eval_signbit(x)) { - if(eval_signbit(x)) - { - result = get_constant_pi(); - if(eval_signbit(y)) - result.negate(); - } - else - { - result = y; // Note we allow atan2(0,0) to be +-zero, even though it's mathematically undefined - } - return; + result = get_constant_pi(); + if (eval_signbit(y)) + result.negate(); } + else + { + result = y; // Note we allow atan2(0,0) to be +-zero, even though it's mathematically undefined + } + return; + } case FP_INFINITE: + { + if (eval_fpclassify(x) == FP_INFINITE) { - if(eval_fpclassify(x) == FP_INFINITE) + if (eval_signbit(x)) { - if(eval_signbit(x)) - { - // 3Pi/4 - eval_ldexp(result, get_constant_pi(), -2); - eval_subtract(result, get_constant_pi()); - if(eval_get_sign(y) >= 0) - result.negate(); - } - else - { - // Pi/4 - eval_ldexp(result, get_constant_pi(), -2); - if(eval_get_sign(y) < 0) - result.negate(); - } + // 3Pi/4 + eval_ldexp(result, get_constant_pi(), -2); + eval_subtract(result, get_constant_pi()); + if (eval_get_sign(y) >= 0) + result.negate(); } else { - eval_ldexp(result, get_constant_pi(), -1); - if(eval_get_sign(y) < 0) + // Pi/4 + eval_ldexp(result, get_constant_pi(), -2); + if (eval_get_sign(y) < 0) result.negate(); } - return; } + else + { + eval_ldexp(result, get_constant_pi(), -1); + if (eval_get_sign(y) < 0) + result.negate(); + } + return; + } } - switch(eval_fpclassify(x)) + switch (eval_fpclassify(x)) { case FP_NAN: result = x; - errno = EDOM; + errno = EDOM; return; case FP_ZERO: - { - eval_ldexp(result, get_constant_pi(), -1); - if(eval_get_sign(y) < 0) - result.negate(); - return; - } + { + eval_ldexp(result, get_constant_pi(), -1); + if (eval_get_sign(y) < 0) + result.negate(); + return; + } case FP_INFINITE: - if(eval_get_sign(x) > 0) + if (eval_get_sign(x) > 0) result = ui_type(0); else result = get_constant_pi(); - if(eval_get_sign(y) < 0) + if (eval_get_sign(y) < 0) result.negate(); return; } T xx; eval_divide(xx, y, x); - if(eval_get_sign(xx) < 0) + if (eval_get_sign(xx) < 0) xx.negate(); eval_atan(result, xx); @@ -808,33 +809,33 @@ void eval_atan2(T& result, const T& y, const T& x) const bool y_neg = eval_get_sign(y) < 0; const bool x_neg = eval_get_sign(x) < 0; - if(y_neg != x_neg) + if (y_neg != x_neg) result.negate(); - if(x_neg) + if (x_neg) { - if(y_neg) + if (y_neg) eval_subtract(result, get_constant_pi()); else eval_add(result, get_constant_pi()); } } -template -inline typename enable_if, void>::type eval_atan2(T& result, const T& x, const A& a) +template +inline typename enable_if, void>::type eval_atan2(T &result, const T &x, const A &a) { - typedef typename boost::multiprecision::detail::canonical::type canonical_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_type; typedef typename mpl::if_, T, canonical_type>::type cast_type; - cast_type c; + cast_type c; c = a; eval_atan2(result, x, c); } -template -inline typename enable_if, void>::type eval_atan2(T& result, const A& x, const T& a) +template +inline typename enable_if, void>::type eval_atan2(T &result, const A &x, const T &a) { - typedef typename boost::multiprecision::detail::canonical::type canonical_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_type; typedef typename mpl::if_, T, canonical_type>::type cast_type; - cast_type c; + cast_type c; c = x; eval_atan2(result, c, a); } diff --git a/include/boost/multiprecision/detail/integer_ops.hpp b/include/boost/multiprecision/detail/integer_ops.hpp index a789681c9..061648ecb 100644 --- a/include/boost/multiprecision/detail/integer_ops.hpp +++ b/include/boost/multiprecision/detail/integer_ops.hpp @@ -8,488 +8,498 @@ #include -namespace boost{ namespace multiprecision{ +namespace boost { +namespace multiprecision { -namespace default_ops -{ +namespace default_ops { template -inline void eval_qr(const Backend& x, const Backend& y, Backend& q, Backend& r) -{ - eval_divide(q, x, y); - eval_modulus(r, x, y); +inline void eval_qr(const Backend &x, const Backend &y, Backend &q, + Backend &r) { + eval_divide(q, x, y); + eval_modulus(r, x, y); } template -inline Integer eval_integer_modulus(const Backend& x, Integer val) -{ - BOOST_MP_USING_ABS - using default_ops::eval_modulus; - using default_ops::eval_convert_to; - typedef typename boost::multiprecision::detail::canonical::type int_type; - Backend t; - eval_modulus(t, x, static_cast(val)); - Integer result; - eval_convert_to(&result, t); - return abs(result); +inline Integer eval_integer_modulus(const Backend &x, Integer val) { + BOOST_MP_USING_ABS + using default_ops::eval_convert_to; + using default_ops::eval_modulus; + typedef + typename boost::multiprecision::detail::canonical::type + int_type; + Backend t; + eval_modulus(t, x, static_cast(val)); + Integer result; + eval_convert_to(&result, t); + return abs(result); } #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:4127) +#pragma warning(disable : 4127) #endif -template -inline void eval_gcd(B& result, const B& a, const B& b) -{ - using default_ops::eval_lsb; - using default_ops::eval_is_zero; - using default_ops::eval_get_sign; - - int shift; - - B u(a), v(b); - - int s = eval_get_sign(u); - - /* GCD(0,x) := x */ - if(s < 0) - { - u.negate(); - } - else if(s == 0) - { - result = v; - return; - } - s = eval_get_sign(v); - if(s < 0) - { - v.negate(); - } - else if(s == 0) - { - result = u; - return; - } - - /* Let shift := lg K, where K is the greatest power of 2 - dividing both u and v. */ - - unsigned us = eval_lsb(u); - unsigned vs = eval_lsb(v); - shift = (std::min)(us, vs); - eval_right_shift(u, us); - eval_right_shift(v, vs); - - do - { - /* Now u and v are both odd, so diff(u, v) is even. - Let u = min(u, v), v = diff(u, v)/2. */ - s = u.compare(v); - if(s > 0) - u.swap(v); - if(s == 0) - break; - eval_subtract(v, u); - vs = eval_lsb(v); - eval_right_shift(v, vs); - } - while(true); - - result = u; - eval_left_shift(result, shift); +template inline void eval_gcd(B &result, const B &a, const B &b) { + using default_ops::eval_get_sign; + using default_ops::eval_is_zero; + using default_ops::eval_lsb; + + int shift; + + B u(a), v(b); + + int s = eval_get_sign(u); + + /* GCD(0,x) := x */ + if (s < 0) { + u.negate(); + } else if (s == 0) { + result = v; + return; + } + s = eval_get_sign(v); + if (s < 0) { + v.negate(); + } else if (s == 0) { + result = u; + return; + } + + /* Let shift := lg K, where K is the greatest power of 2 + dividing both u and v. */ + + unsigned us = eval_lsb(u); + unsigned vs = eval_lsb(v); + shift = (std::min)(us, vs); + eval_right_shift(u, us); + eval_right_shift(v, vs); + + do { + /* Now u and v are both odd, so diff(u, v) is even. + Let u = min(u, v), v = diff(u, v)/2. */ + s = u.compare(v); + if (s > 0) + u.swap(v); + if (s == 0) + break; + eval_subtract(v, u); + vs = eval_lsb(v); + eval_right_shift(v, vs); + } while (true); + + result = u; + eval_left_shift(result, shift); } #ifdef BOOST_MSVC #pragma warning(pop) #endif -template -inline void eval_lcm(B& result, const B& a, const B& b) -{ - typedef typename mpl::front::type ui_type; - B t; - eval_gcd(t, a, b); - - if(eval_is_zero(t)) - { - result = static_cast(0); - } - else - { - eval_divide(result, a, t); - eval_multiply(result, b); - } - if(eval_get_sign(result) < 0) - result.negate(); +template inline void eval_lcm(B &result, const B &a, const B &b) { + typedef typename mpl::front::type ui_type; + B t; + eval_gcd(t, a, b); + + if (eval_is_zero(t)) { + result = static_cast(0); + } else { + eval_divide(result, a, t); + eval_multiply(result, b); + } + if (eval_get_sign(result) < 0) + result.negate(); } -} +} // namespace default_ops template -inline typename enable_if_c::value == number_kind_integer>::type - divide_qr(const number& x, const number& y, - number& q, number& r) -{ - using default_ops::eval_qr; - eval_qr(x.backend(), y.backend(), q.backend(), r.backend()); +inline typename enable_if_c::value == + number_kind_integer>::type +divide_qr(const number &x, + const number &y, + number &q, + number &r) { + using default_ops::eval_qr; + eval_qr(x.backend(), y.backend(), q.backend(), r.backend()); } -template -inline typename enable_if_c::value == number_kind_integer>::type - divide_qr(const number& x, const multiprecision::detail::expression& y, - number& q, number& r) -{ - divide_qr(x, number(y), q, r); +template +inline typename enable_if_c::value == + number_kind_integer>::type +divide_qr(const number &x, + const multiprecision::detail::expression &y, + number &q, + number &r) { + divide_qr(x, number(y), q, r); } -template -inline typename enable_if_c::value == number_kind_integer>::type - divide_qr(const multiprecision::detail::expression& x, const number& y, - number& q, number& r) -{ - divide_qr(number(x), y, q, r); +template +inline typename enable_if_c::value == + number_kind_integer>::type +divide_qr(const multiprecision::detail::expression &x, + const number &y, + number &q, + number &r) { + divide_qr(number(x), y, q, r); } -template -inline typename enable_if_c::value == number_kind_integer>::type - divide_qr(const multiprecision::detail::expression& x, const multiprecision::detail::expression& y, - number& q, number& r) -{ - divide_qr(number(x), number(y), q, r); +template +inline typename enable_if_c::value == + number_kind_integer>::type +divide_qr(const multiprecision::detail::expression &x, + const multiprecision::detail::expression &y, + number &q, + number &r) { + divide_qr(number(x), + number(y), q, r); } -template -inline typename enable_if, mpl::bool_::value == number_kind_integer> >, Integer>::type - integer_modulus(const number& x, Integer val) -{ - using default_ops::eval_integer_modulus; - return eval_integer_modulus(x.backend(), val); +template +inline + typename enable_if, + mpl::bool_::value == + number_kind_integer>>, + Integer>::type + integer_modulus(const number &x, + Integer val) { + using default_ops::eval_integer_modulus; + return eval_integer_modulus(x.backend(), val); } template -inline typename enable_if, mpl::bool_::result_type>::value == number_kind_integer> >, Integer>::type - integer_modulus(const multiprecision::detail::expression& x, Integer val) -{ - typedef typename multiprecision::detail::expression::result_type result_type; - return integer_modulus(result_type(x), val); +inline typename enable_if< + mpl::and_< + is_integral, + mpl::bool_::result_type>::value == + number_kind_integer>>, + Integer>::type +integer_modulus( + const multiprecision::detail::expression &x, + Integer val) { + typedef + typename multiprecision::detail::expression::result_type result_type; + return integer_modulus(result_type(x), val); } template -inline typename enable_if_c::value == number_kind_integer, unsigned>::type - lsb(const number& x) -{ - using default_ops::eval_lsb; - return eval_lsb(x.backend()); +inline + typename enable_if_c::value == number_kind_integer, + unsigned>::type + lsb(const number &x) { + using default_ops::eval_lsb; + return eval_lsb(x.backend()); } template -inline typename enable_if_c::result_type>::value == number_kind_integer, unsigned>::type - lsb(const multiprecision::detail::expression& x) -{ - typedef typename multiprecision::detail::expression::result_type number_type; - number_type n(x); - using default_ops::eval_lsb; - return eval_lsb(n.backend()); +inline typename enable_if_c< + number_category::result_type>::value == number_kind_integer, + unsigned>::type +lsb(const multiprecision::detail::expression &x) { + typedef + typename multiprecision::detail::expression::result_type number_type; + number_type n(x); + using default_ops::eval_lsb; + return eval_lsb(n.backend()); } template -inline typename enable_if_c::value == number_kind_integer, unsigned>::type - msb(const number& x) -{ - using default_ops::eval_msb; - return eval_msb(x.backend()); +inline + typename enable_if_c::value == number_kind_integer, + unsigned>::type + msb(const number &x) { + using default_ops::eval_msb; + return eval_msb(x.backend()); } template -inline typename enable_if_c::result_type>::value == number_kind_integer, unsigned>::type - msb(const multiprecision::detail::expression& x) -{ - typedef typename multiprecision::detail::expression::result_type number_type; - number_type n(x); - using default_ops::eval_msb; - return eval_msb(n.backend()); +inline typename enable_if_c< + number_category::result_type>::value == number_kind_integer, + unsigned>::type +msb(const multiprecision::detail::expression &x) { + typedef + typename multiprecision::detail::expression::result_type number_type; + number_type n(x); + using default_ops::eval_msb; + return eval_msb(n.backend()); } template -inline typename enable_if_c::value == number_kind_integer, bool>::type - bit_test(const number& x, unsigned index) -{ - using default_ops::eval_bit_test; - return eval_bit_test(x.backend(), index); +inline + typename enable_if_c::value == number_kind_integer, + bool>::type + bit_test(const number &x, unsigned index) { + using default_ops::eval_bit_test; + return eval_bit_test(x.backend(), index); } template -inline typename enable_if_c::result_type>::value == number_kind_integer, bool>::type - bit_test(const multiprecision::detail::expression& x, unsigned index) -{ - typedef typename multiprecision::detail::expression::result_type number_type; - number_type n(x); - using default_ops::eval_bit_test; - return eval_bit_test(n.backend(), index); +inline typename enable_if_c< + number_category::result_type>::value == number_kind_integer, + bool>::type +bit_test(const multiprecision::detail::expression &x, + unsigned index) { + typedef + typename multiprecision::detail::expression::result_type number_type; + number_type n(x); + using default_ops::eval_bit_test; + return eval_bit_test(n.backend(), index); } template -inline typename enable_if_c::value == number_kind_integer, number&>::type - bit_set(number& x, unsigned index) -{ - using default_ops::eval_bit_set; - eval_bit_set(x.backend(), index); - return x; +inline + typename enable_if_c::value == number_kind_integer, + number &>::type + bit_set(number &x, unsigned index) { + using default_ops::eval_bit_set; + eval_bit_set(x.backend(), index); + return x; } template -inline typename enable_if_c::value == number_kind_integer, number&>::type - bit_unset(number& x, unsigned index) -{ - using default_ops::eval_bit_unset; - eval_bit_unset(x.backend(), index); - return x; +inline + typename enable_if_c::value == number_kind_integer, + number &>::type + bit_unset(number &x, unsigned index) { + using default_ops::eval_bit_unset; + eval_bit_unset(x.backend(), index); + return x; } template -inline typename enable_if_c::value == number_kind_integer, number&>::type - bit_flip(number& x, unsigned index) -{ - using default_ops::eval_bit_flip; - eval_bit_flip(x.backend(), index); - return x; +inline + typename enable_if_c::value == number_kind_integer, + number &>::type + bit_flip(number &x, unsigned index) { + using default_ops::eval_bit_flip; + eval_bit_flip(x.backend(), index); + return x; } -namespace default_ops{ +namespace default_ops { // -// Within powm, we need a type with twice as many digits as the argument type, define -// a traits class to obtain that type: +// Within powm, we need a type with twice as many digits as the argument type, +// define a traits class to obtain that type: // -template -struct double_precision_type -{ - typedef Backend type; -}; +template struct double_precision_type { typedef Backend type; }; // // If the exponent is a signed integer type, then we need to // check the value is positive: // template -inline void check_sign_of_backend(const Backend& v, const mpl::true_) -{ - if(eval_get_sign(v) < 0) - { - BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); - } +inline void check_sign_of_backend(const Backend &v, const mpl::true_) { + if (eval_get_sign(v) < 0) { + BOOST_THROW_EXCEPTION( + std::runtime_error("powm requires a positive exponent.")); + } } template -inline void check_sign_of_backend(const Backend&, const mpl::false_){} +inline void check_sign_of_backend(const Backend &, const mpl::false_) {} // // Calculate (a^p)%c: // template -void eval_powm(Backend& result, const Backend& a, const Backend& p, const Backend& c) -{ - using default_ops::eval_bit_test; - using default_ops::eval_get_sign; - using default_ops::eval_multiply; - using default_ops::eval_modulus; - using default_ops::eval_right_shift; - - typedef typename double_precision_type::type double_type; - typedef typename boost::multiprecision::detail::canonical::type ui_type; - - check_sign_of_backend(p, mpl::bool_ >::is_signed>()); - - double_type x, y(a), b(p), t; - x = ui_type(1u); - - while(eval_get_sign(b) > 0) - { - if(eval_bit_test(b, 0)) - { - eval_multiply(t, x, y); - eval_modulus(x, t, c); - } - eval_multiply(t, y, y); - eval_modulus(y, t, c); - eval_right_shift(b, ui_type(1)); - } - Backend x2(x); - eval_modulus(result, x2, c); +void eval_powm(Backend &result, const Backend &a, const Backend &p, + const Backend &c) { + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_modulus; + using default_ops::eval_multiply; + using default_ops::eval_right_shift; + + typedef typename double_precision_type::type double_type; + typedef typename boost::multiprecision::detail::canonical< + unsigned char, double_type>::type ui_type; + + check_sign_of_backend( + p, mpl::bool_>::is_signed>()); + + double_type x, y(a), b(p), t; + x = ui_type(1u); + + while (eval_get_sign(b) > 0) { + if (eval_bit_test(b, 0)) { + eval_multiply(t, x, y); + eval_modulus(x, t, c); + } + eval_multiply(t, y, y); + eval_modulus(y, t, c); + eval_right_shift(b, ui_type(1)); + } + Backend x2(x); + eval_modulus(result, x2, c); } template -void eval_powm(Backend& result, const Backend& a, const Backend& p, Integer c) -{ - typedef typename double_precision_type::type double_type; - typedef typename boost::multiprecision::detail::canonical::type ui_type; - typedef typename boost::multiprecision::detail::canonical::type i1_type; - typedef typename boost::multiprecision::detail::canonical::type i2_type; - - using default_ops::eval_bit_test; - using default_ops::eval_get_sign; - using default_ops::eval_multiply; - using default_ops::eval_modulus; - using default_ops::eval_right_shift; - - check_sign_of_backend(p, mpl::bool_ >::is_signed>()); - - if(eval_get_sign(p) < 0) - { - BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); - } - - double_type x, y(a), b(p), t; - x = ui_type(1u); - - while(eval_get_sign(b) > 0) - { - if(eval_bit_test(b, 0)) - { - eval_multiply(t, x, y); - eval_modulus(x, t, static_cast(c)); - } - eval_multiply(t, y, y); - eval_modulus(y, t, static_cast(c)); - eval_right_shift(b, ui_type(1)); - } - Backend x2(x); - eval_modulus(result, x2, static_cast(c)); +void eval_powm(Backend &result, const Backend &a, const Backend &p, Integer c) { + typedef typename double_precision_type::type double_type; + typedef typename boost::multiprecision::detail::canonical< + unsigned char, double_type>::type ui_type; + typedef typename boost::multiprecision::detail::canonical< + Integer, double_type>::type i1_type; + typedef + typename boost::multiprecision::detail::canonical::type + i2_type; + + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_modulus; + using default_ops::eval_multiply; + using default_ops::eval_right_shift; + + check_sign_of_backend( + p, mpl::bool_>::is_signed>()); + + if (eval_get_sign(p) < 0) { + BOOST_THROW_EXCEPTION( + std::runtime_error("powm requires a positive exponent.")); + } + + double_type x, y(a), b(p), t; + x = ui_type(1u); + + while (eval_get_sign(b) > 0) { + if (eval_bit_test(b, 0)) { + eval_multiply(t, x, y); + eval_modulus(x, t, static_cast(c)); + } + eval_multiply(t, y, y); + eval_modulus(y, t, static_cast(c)); + eval_right_shift(b, ui_type(1)); + } + Backend x2(x); + eval_modulus(result, x2, static_cast(c)); } template -typename enable_if >::type eval_powm(Backend& result, const Backend& a, Integer b, const Backend& c) -{ - typedef typename double_precision_type::type double_type; - typedef typename boost::multiprecision::detail::canonical::type ui_type; - - using default_ops::eval_bit_test; - using default_ops::eval_get_sign; - using default_ops::eval_multiply; - using default_ops::eval_modulus; - using default_ops::eval_right_shift; - - double_type x, y(a), t; - x = ui_type(1u); - - while(b > 0) - { - if(b & 1) - { - eval_multiply(t, x, y); - eval_modulus(x, t, c); - } - eval_multiply(t, y, y); - eval_modulus(y, t, c); - b >>= 1; - } - Backend x2(x); - eval_modulus(result, x2, c); +typename enable_if>::type +eval_powm(Backend &result, const Backend &a, Integer b, const Backend &c) { + typedef typename double_precision_type::type double_type; + typedef typename boost::multiprecision::detail::canonical< + unsigned char, double_type>::type ui_type; + + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_modulus; + using default_ops::eval_multiply; + using default_ops::eval_right_shift; + + double_type x, y(a), t; + x = ui_type(1u); + + while (b > 0) { + if (b & 1) { + eval_multiply(t, x, y); + eval_modulus(x, t, c); + } + eval_multiply(t, y, y); + eval_modulus(y, t, c); + b >>= 1; + } + Backend x2(x); + eval_modulus(result, x2, c); } template -typename enable_if >::type eval_powm(Backend& result, const Backend& a, Integer b, const Backend& c) -{ - if(b < 0) - { - BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); - } - eval_powm(result, a, static_cast::type>(b), c); +typename enable_if>::type +eval_powm(Backend &result, const Backend &a, Integer b, const Backend &c) { + if (b < 0) { + BOOST_THROW_EXCEPTION( + std::runtime_error("powm requires a positive exponent.")); + } + eval_powm(result, a, static_cast::type>(b), + c); } template -typename enable_if >::type eval_powm(Backend& result, const Backend& a, Integer1 b, Integer2 c) -{ - typedef typename double_precision_type::type double_type; - typedef typename boost::multiprecision::detail::canonical::type ui_type; - typedef typename boost::multiprecision::detail::canonical::type i1_type; - typedef typename boost::multiprecision::detail::canonical::type i2_type; - - using default_ops::eval_bit_test; - using default_ops::eval_get_sign; - using default_ops::eval_multiply; - using default_ops::eval_modulus; - using default_ops::eval_right_shift; - - double_type x, y(a), t; - x = ui_type(1u); - - while(b > 0) - { - if(b & 1) - { - eval_multiply(t, x, y); - eval_modulus(x, t, static_cast(c)); - } - eval_multiply(t, y, y); - eval_modulus(y, t, static_cast(c)); - b >>= 1; - } - Backend x2(x); - eval_modulus(result, x2, static_cast(c)); +typename enable_if>::type +eval_powm(Backend &result, const Backend &a, Integer1 b, Integer2 c) { + typedef typename double_precision_type::type double_type; + typedef typename boost::multiprecision::detail::canonical< + unsigned char, double_type>::type ui_type; + typedef typename boost::multiprecision::detail::canonical< + Integer1, double_type>::type i1_type; + typedef + typename boost::multiprecision::detail::canonical::type + i2_type; + + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_modulus; + using default_ops::eval_multiply; + using default_ops::eval_right_shift; + + double_type x, y(a), t; + x = ui_type(1u); + + while (b > 0) { + if (b & 1) { + eval_multiply(t, x, y); + eval_modulus(x, t, static_cast(c)); + } + eval_multiply(t, y, y); + eval_modulus(y, t, static_cast(c)); + b >>= 1; + } + Backend x2(x); + eval_modulus(result, x2, static_cast(c)); } template -typename enable_if >::type eval_powm(Backend& result, const Backend& a, Integer1 b, Integer2 c) -{ - if(b < 0) - { - BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); - } - eval_powm(result, a, static_cast::type>(b), c); +typename enable_if>::type +eval_powm(Backend &result, const Backend &a, Integer1 b, Integer2 c) { + if (b < 0) { + BOOST_THROW_EXCEPTION( + std::runtime_error("powm requires a positive exponent.")); + } + eval_powm(result, a, static_cast::type>(b), + c); } -struct powm_func -{ - template - void operator()(T& result, const T& b, const U& p, const V& m)const - { - eval_powm(result, b, p, m); - } +struct powm_func { + template + void operator()(T &result, const T &b, const U &p, const V &m) const { + eval_powm(result, b, p, m); + } }; -} +} // namespace default_ops template inline typename enable_if< - mpl::and_< - mpl::bool_::value == number_kind_integer>, - mpl::or_< - is_number, - is_number_expression - >, - mpl::or_< - is_number, - is_number_expression, - is_integral - >, - mpl::or_< - is_number, - is_number_expression, - is_integral - > - >, - typename mpl::if_< - is_no_et_number, - T, - typename mpl::if_< - is_no_et_number, - U, - typename mpl::if_< - is_no_et_number, - V, - detail::expression >::type - >::type - >::type - >::type - powm(const T& b, const U& p, const V& mod) -{ - return detail::expression( + mpl::and_::value == number_kind_integer>, + mpl::or_, is_number_expression>, + mpl::or_, is_number_expression, is_integral>, + mpl::or_, is_number_expression, is_integral>>, + typename mpl::if_< + is_no_et_number, T, + typename mpl::if_< + is_no_et_number, U, + typename mpl::if_< + is_no_et_number, V, + detail::expression>::type>::type>::type>::type +powm(const T &b, const U &p, const V &mod) { + return detail::expression( default_ops::powm_func(), b, p, mod); } -}} //namespaces +} // namespace multiprecision +} // namespace boost #endif - - diff --git a/include/boost/multiprecision/detail/number_base.hpp b/include/boost/multiprecision/detail/number_base.hpp index 685e0fe9c..9e2f79d3e 100644 --- a/include/boost/multiprecision/detail/number_base.hpp +++ b/include/boost/multiprecision/detail/number_base.hpp @@ -6,33 +6,37 @@ #ifndef BOOST_MATH_BIG_NUM_BASE_HPP #define BOOST_MATH_BIG_NUM_BASE_HPP -#include -#include -#include -#include #include +#include +#include +#include +#include #ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable:4307) +#pragma warning(push) +#pragma warning(disable : 4307) #endif #include #ifdef BOOST_MSVC -# pragma warning(pop) +#pragma warning(pop) #endif #if defined(NDEBUG) && !defined(_DEBUG) -# define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE +#define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE #else -# define BOOST_MP_FORCEINLINE inline +#define BOOST_MP_FORCEINLINE inline #endif -#if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140) || (defined(__clang_major__) && (__clang_major__ == 3) && (__clang_minor__ < 5)) -# define BOOST_MP_NOEXCEPT_IF(x) +#if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || \ + BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140) || \ + (defined(__clang_major__) && (__clang_major__ == 3) && \ + (__clang_minor__ < 5)) +#define BOOST_MP_NOEXCEPT_IF(x) #else -# define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x) +#define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x) #endif -#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140) +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || \ + BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140) #define BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS #endif @@ -40,1612 +44,1811 @@ // Thread local storage: // Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/ // -#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && !defined(__MINGW32__) -# define BOOST_MP_THREAD_LOCAL thread_local -# define BOOST_MP_USING_THREAD_LOCAL +#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && \ + !defined(__MINGW32__) +#define BOOST_MP_THREAD_LOCAL thread_local +#define BOOST_MP_USING_THREAD_LOCAL #else -# define BOOST_MP_THREAD_LOCAL +#define BOOST_MP_THREAD_LOCAL #endif #ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable:6326) +#pragma warning(push) +#pragma warning(disable : 6326) #endif -namespace boost{ - - namespace serialization - { - template - struct nvp; - template - const nvp< T > make_nvp(const char * name, T & t); - } - - namespace multiprecision{ - -enum expression_template_option -{ - et_off = 0, - et_on = 1 -}; +namespace boost { -template -struct expression_template_default -{ - static const expression_template_option value = et_on; +namespace serialization { +template struct nvp; +template const nvp make_nvp(const char *name, T &t); +} // namespace serialization + +namespace multiprecision { + +enum expression_template_option { et_off = 0, et_on = 1 }; + +template struct expression_template_default { + static const expression_template_option value = et_on; }; -template ::value> +template ::value> class number; -template -struct is_number : public mpl::false_ {}; +template struct is_number : public mpl::false_ {}; template -struct is_number > : public mpl::true_ {}; +struct is_number> : public mpl::true_ {}; -template -struct is_et_number : public mpl::false_ {}; +template struct is_et_number : public mpl::false_ {}; template -struct is_et_number > : public mpl::true_ {}; +struct is_et_number> : public mpl::true_ {}; -template -struct is_no_et_number : public mpl::false_ {}; +template struct is_no_et_number : public mpl::false_ {}; template -struct is_no_et_number > : public mpl::true_ {}; +struct is_no_et_number> : public mpl::true_ {}; -namespace detail{ +namespace detail { // Forward-declare an expression wrapper -template +template struct expression; } // namespace detail -template -struct is_number_expression : public mpl::false_ {}; +template struct is_number_expression : public mpl::false_ {}; -template -struct is_number_expression > : public mpl::true_ {}; +template +struct is_number_expression> + : public mpl::true_ {}; template struct is_compatible_arithmetic_type - : public mpl::bool_< - is_convertible::value - && !is_same::value - && !is_number_expression::value> -{}; + : public mpl::bool_::value && + !is_same::value && + !is_number_expression::value> {}; -namespace detail{ +namespace detail { // -// Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers: +// Workaround for missing abs(boost::long_long_type) and abs(__int128) on some +// compilers: // template -BOOST_CONSTEXPR typename enable_if_c<(is_signed::value || is_floating_point::value), T>::type abs(T t) BOOST_NOEXCEPT -{ - // This strange expression avoids a hardware trap in the corner case - // that val is the most negative value permitted in boost::long_long_type. - // See https://svn.boost.org/trac/boost/ticket/9740. - return t < 0 ? T(1u) + T(-(t + 1)) : t; +BOOST_CONSTEXPR + typename enable_if_c<(is_signed::value || is_floating_point::value), + T>::type + abs(T t) BOOST_NOEXCEPT { + // This strange expression avoids a hardware trap in the corner case + // that val is the most negative value permitted in boost::long_long_type. + // See https://svn.boost.org/trac/boost/ticket/9740. + return t < 0 ? T(1u) + T(-(t + 1)) : t; } template -BOOST_CONSTEXPR typename enable_if_c<(is_unsigned::value), T>::type abs(T t) BOOST_NOEXCEPT -{ - return t; +BOOST_CONSTEXPR typename enable_if_c<(is_unsigned::value), T>::type +abs(T t) BOOST_NOEXCEPT { + return t; } #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs; template -BOOST_CONSTEXPR typename enable_if_c<(is_signed::value || is_floating_point::value), typename make_unsigned::type>::type unsigned_abs(T t) BOOST_NOEXCEPT -{ - // This strange expression avoids a hardware trap in the corner case - // that val is the most negative value permitted in boost::long_long_type. - // See https://svn.boost.org/trac/boost/ticket/9740. - return t < 0 ? static_cast::type>(1u) + static_cast::type>(-(t + 1)) : static_cast::type>(t); +BOOST_CONSTEXPR + typename enable_if_c<(is_signed::value || is_floating_point::value), + typename make_unsigned::type>::type + unsigned_abs(T t) BOOST_NOEXCEPT { + // This strange expression avoids a hardware trap in the corner case + // that val is the most negative value permitted in boost::long_long_type. + // See https://svn.boost.org/trac/boost/ticket/9740. + return t < 0 ? static_cast::type>(1u) + + static_cast::type>(-(t + 1)) + : static_cast::type>(t); } template -BOOST_CONSTEXPR typename enable_if_c<(is_unsigned::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT -{ - return t; +BOOST_CONSTEXPR typename enable_if_c<(is_unsigned::value), T>::type +unsigned_abs(T t) BOOST_NOEXCEPT { + return t; } // // Move support: // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -# define BOOST_MP_MOVE(x) std::move(x) +#define BOOST_MP_MOVE(x) std::move(x) #else -# define BOOST_MP_MOVE(x) x +#define BOOST_MP_MOVE(x) x #endif -template -struct bits_of -{ - BOOST_STATIC_ASSERT(is_integral::value || is_enum::value || std::numeric_limits::is_specialized); - static const unsigned value = - std::numeric_limits::is_specialized ? - std::numeric_limits::digits - : sizeof(T) * CHAR_BIT - (is_signed::value ? 1 : 0); +template struct bits_of { + BOOST_STATIC_ASSERT(is_integral::value || is_enum::value || + std::numeric_limits::is_specialized); + static const unsigned value = + std::numeric_limits::is_specialized + ? std::numeric_limits::digits + : sizeof(T) * CHAR_BIT - (is_signed::value ? 1 : 0); }; -#if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__) -template<> struct bits_of<__float128> { static const unsigned value = 113; }; +#if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && \ + !defined(__STRICT_ANSI__) +template <> struct bits_of<__float128> { static const unsigned value = 113; }; #endif -template -struct has_enough_bits -{ - template - struct type : public mpl::bool_::value>= b>{}; +template struct has_enough_bits { + template struct type : public mpl::bool_::value >= b> {}; }; -template -struct canonical_imp -{ - typedef typename remove_cv::type>::type type; +template struct canonical_imp { + typedef typename remove_cv::type>::type type; }; template -struct canonical_imp, Backend, Tag> -{ - typedef B type; +struct canonical_imp, Backend, Tag> { + typedef B type; }; template -struct canonical_imp, Backend, Tag> -{ - typedef B type; +struct canonical_imp, Backend, Tag> { + typedef B type; }; #ifdef __SUNPRO_CC template -struct canonical_imp, Backend, mpl::int_<3> > -{ - typedef B type; +struct canonical_imp, Backend, mpl::int_<3>> { + typedef B type; }; template -struct canonical_imp, Backend, mpl::int_<3> > -{ - typedef B type; +struct canonical_imp, Backend, mpl::int_<3>> { + typedef B type; }; #endif template -struct canonical_imp > -{ - typedef typename has_enough_bits::value>::template type pred_type; - typedef typename mpl::find_if< - typename Backend::signed_types, - pred_type - >::type iter_type; - typedef typename mpl::end::type end_type; - typedef typename mpl::eval_if, mpl::identity, mpl::deref >::type type; +struct canonical_imp> { + typedef typename has_enough_bits::value>::template type + pred_type; + typedef typename mpl::find_if::type + iter_type; + typedef typename mpl::end::type end_type; + typedef typename mpl::eval_if, + mpl::identity, mpl::deref>::type + type; }; template -struct canonical_imp > -{ - typedef typename has_enough_bits::value>::template type pred_type; - typedef typename mpl::find_if< - typename Backend::unsigned_types, - pred_type - >::type iter_type; - typedef typename mpl::end::type end_type; - typedef typename mpl::eval_if, mpl::identity, mpl::deref >::type type; +struct canonical_imp> { + typedef typename has_enough_bits::value>::template type + pred_type; + typedef + typename mpl::find_if::type + iter_type; + typedef typename mpl::end::type end_type; + typedef typename mpl::eval_if, + mpl::identity, mpl::deref>::type + type; }; template -struct canonical_imp > -{ - typedef typename has_enough_bits::value>::template type pred_type; - typedef typename mpl::find_if< - typename Backend::float_types, - pred_type - >::type iter_type; - typedef typename mpl::end::type end_type; - typedef typename mpl::eval_if, mpl::identity, mpl::deref >::type type; +struct canonical_imp> { + typedef typename has_enough_bits::value>::template type + pred_type; + typedef typename mpl::find_if::type + iter_type; + typedef typename mpl::end::type end_type; + typedef typename mpl::eval_if, + mpl::identity, mpl::deref>::type + type; }; template -struct canonical_imp > -{ - typedef const char* type; +struct canonical_imp> { + typedef const char *type; }; -template -struct canonical -{ - typedef typename mpl::if_< - is_signed, - mpl::int_<0>, +template struct canonical { + typedef typename mpl::if_< + is_signed, mpl::int_<0>, typename mpl::if_< - is_unsigned, - mpl::int_<1>, - typename mpl::if_< - is_floating_point, - mpl::int_<2>, - typename mpl::if_< - mpl::or_< - is_convertible, - is_same - >, - mpl::int_<3>, - mpl::int_<4> - >::type - >::type - >::type - >::type tag_type; - - typedef typename canonical_imp::type type; + is_unsigned, mpl::int_<1>, + typename mpl::if_< + is_floating_point, mpl::int_<2>, + typename mpl::if_, + is_same>, + mpl::int_<3>, mpl::int_<4>>::type>::type>:: + type>::type tag_type; + + typedef typename canonical_imp::type type; }; -struct terminal{}; -struct negate{}; -struct plus{}; -struct minus{}; -struct multiplies{}; -struct divides{}; -struct modulus{}; -struct shift_left{}; -struct shift_right{}; -struct bitwise_and{}; -struct bitwise_or{}; -struct bitwise_xor{}; -struct bitwise_complement{}; -struct add_immediates{}; -struct subtract_immediates{}; -struct multiply_immediates{}; -struct divide_immediates{}; -struct modulus_immediates{}; -struct bitwise_and_immediates{}; -struct bitwise_or_immediates{}; -struct bitwise_xor_immediates{}; -struct complement_immediates{}; -struct function{}; -struct multiply_add{}; -struct multiply_subtract{}; - -template -struct backend_type; +struct terminal {}; +struct negate {}; +struct plus {}; +struct minus {}; +struct multiplies {}; +struct divides {}; +struct modulus {}; +struct shift_left {}; +struct shift_right {}; +struct bitwise_and {}; +struct bitwise_or {}; +struct bitwise_xor {}; +struct bitwise_complement {}; +struct add_immediates {}; +struct subtract_immediates {}; +struct multiply_immediates {}; +struct divide_immediates {}; +struct modulus_immediates {}; +struct bitwise_and_immediates {}; +struct bitwise_or_immediates {}; +struct bitwise_xor_immediates {}; +struct complement_immediates {}; +struct function {}; +struct multiply_add {}; +struct multiply_subtract {}; + +template struct backend_type; template -struct backend_type > -{ - typedef T type; +struct backend_type> { + typedef T type; }; template -struct backend_type > -{ - typedef typename backend_type::result_type>::type type; +struct backend_type> { + typedef typename backend_type< + typename expression::result_type>::type type; }; - -template -struct combine_expression -{ +template struct combine_expression { #ifdef BOOST_NO_CXX11_DECLTYPE - typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type; + typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type + type; #else - typedef decltype(T1() + T2()) type; + typedef decltype(T1() + T2()) type; #endif }; template -struct combine_expression, T2> -{ - typedef number type; +struct combine_expression, T2> { + typedef number type; }; template -struct combine_expression > -{ - typedef number type; +struct combine_expression> { + typedef number type; }; template -struct combine_expression, number > -{ - typedef number type; +struct combine_expression, + number> { + typedef number type; }; -template -struct combine_expression, number > -{ - typedef typename mpl::if_c< - is_convertible, number >::value, - number, - number - >::type type; +template +struct combine_expression, + number> { + typedef typename mpl::if_c< + is_convertible, + number>::value, + number, number>::type + type; }; -template -struct arg_type -{ - typedef expression type; -}; +template struct arg_type { typedef expression type; }; template -struct arg_type > -{ - typedef expression type; +struct arg_type> { + typedef expression type; }; -struct unmentionable -{ - unmentionable* proc(){ return 0; } +struct unmentionable { + unmentionable *proc() { return 0; } }; -typedef unmentionable* (unmentionable::*unmentionable_type)(); +typedef unmentionable *(unmentionable::*unmentionable_type)(); -template -struct expression_storage_base -{ - typedef const T& type; +template struct expression_storage_base { + typedef const T &type; }; -template -struct expression_storage_base -{ - typedef T type; -}; +template struct expression_storage_base { typedef T type; }; template -struct expression_storage : public expression_storage_base::value> {}; +struct expression_storage + : public expression_storage_base::value> {}; -template -struct expression_storage -{ - typedef T* type; -}; +template struct expression_storage { typedef T *type; }; -template -struct expression_storage -{ - typedef const T* type; +template struct expression_storage { + typedef const T *type; }; template -struct expression_storage > -{ - typedef expression type; +struct expression_storage> { + typedef expression type; }; -template -struct expression -{ - typedef mpl::int_<1> arity; - typedef typename arg_type::type left_type; - typedef typename left_type::result_type left_result_type; - typedef typename left_type::result_type result_type; - typedef tag tag_type; +template +struct expression { + typedef mpl::int_<1> arity; + typedef typename arg_type::type left_type; + typedef typename left_type::result_type left_result_type; + typedef typename left_type::result_type result_type; + typedef tag tag_type; - explicit expression(const Arg1& a) : arg(a) {} + explicit expression(const Arg1 &a) : arg(a) {} #ifndef BOOST_NO_CXX11_STATIC_ASSERT - // - // If we have static_assert we can give a more useful error message - // than if we simply have no operator defined at all: - // - template - expression& operator=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator+=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator-=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator*=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator/=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator%=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator|=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator&=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator^=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator<<=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator>>=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } + // + // If we have static_assert we can give a more useful error message + // than if we simply have no operator defined at all: + // + template expression &operator=(const Other &) { + // This should always fail: + static_assert(sizeof(Other) == INT_MAX, + "You can not assign to a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + template expression &operator+=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator+= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator-=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator-= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator*=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator*= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator/=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator/= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator%=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator%= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator|=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator|= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator&=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator&= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator^=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator^= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator<<=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator<<= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator>>=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator>>= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } #endif - left_type left()const { return left_type(arg); } + left_type left() const { return left_type(arg); } - const Arg1& left_ref()const BOOST_NOEXCEPT { return arg; } + const Arg1 &left_ref() const BOOST_NOEXCEPT { return arg; } - static const unsigned depth = left_type::depth + 1; + static const unsigned depth = left_type::depth + 1; #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS -# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500)) - // - // Horrible workaround for gcc-4.6.x which always prefers the template - // operator bool() rather than the non-template operator when converting to - // an arithmetic type: - // - template , int>::type = 0> - explicit operator T ()const - { - result_type r(*this); - return static_cast(r); - } - template ::value || is_void::value || is_number::value, int>::type = 0> - explicit operator T ()const - { - return static_cast(static_cast(*this)); - } -# else - template , int>::type = 0> + explicit operator T() const { + result_type r(*this); + return static_cast(r); + } + template ::value || + is_void::value || + is_number::value, + int>::type = 0> + explicit operator T() const { + return static_cast(static_cast(*this)); + } +#else + template ::value || is_constructible::value, int>::type = 0 + , + typename boost::disable_if_c< + is_number::value || + is_constructible::value, + int>::type = 0 #endif -> - explicit operator T()const - { - return static_cast(static_cast(*this)); - } - BOOST_MP_FORCEINLINE explicit operator bool()const - { - result_type r(*this); - return static_cast(r); - } + > + explicit operator T() const { + return static_cast(static_cast(*this)); + } + BOOST_MP_FORCEINLINE explicit operator bool() const { + result_type r(*this); + return static_cast(r); + } #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800) - BOOST_MP_FORCEINLINE explicit operator void()const {} + BOOST_MP_FORCEINLINE explicit operator void() const {} +#endif #endif -# endif #else - operator unmentionable_type()const - { - result_type r(*this); - return r ? &unmentionable::proc : 0; - } + operator unmentionable_type() const { + result_type r(*this); + return r ? &unmentionable::proc : 0; + } #endif - template - T convert_to() - { - result_type r(*this); - return r.template convert_to(); - } + template T convert_to() { + result_type r(*this); + return r.template convert_to(); + } private: - typename expression_storage::type arg; - expression& operator=(const expression&); + typename expression_storage::type arg; + expression &operator=(const expression &); }; -template -struct expression -{ - typedef mpl::int_<0> arity; - typedef Arg1 result_type; - typedef terminal tag_type; +template struct expression { + typedef mpl::int_<0> arity; + typedef Arg1 result_type; + typedef terminal tag_type; - explicit expression(const Arg1& a) : arg(a) {} + explicit expression(const Arg1 &a) : arg(a) {} #ifndef BOOST_NO_CXX11_STATIC_ASSERT - // - // If we have static_assert we can give a more useful error message - // than if we simply have no operator defined at all: - // - template - expression& operator=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator+=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator-=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator*=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator/=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator%=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator|=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator&=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator^=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator<<=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator>>=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } + // + // If we have static_assert we can give a more useful error message + // than if we simply have no operator defined at all: + // + template expression &operator=(const Other &) { + // This should always fail: + static_assert(sizeof(Other) == INT_MAX, + "You can not assign to a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + template expression &operator+=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator+= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator-=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator-= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator*=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator*= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator/=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator/= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator%=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator%= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator|=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator|= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator&=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator&= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator^=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator^= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator<<=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator<<= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator>>=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator>>= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } #endif - const Arg1& value()const BOOST_NOEXCEPT { return arg; } + const Arg1 &value() const BOOST_NOEXCEPT { return arg; } - static const unsigned depth = 0; + static const unsigned depth = 0; #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS -# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500)) - // - // Horrible workaround for gcc-4.6.x which always prefers the template - // operator bool() rather than the non-template operator when converting to - // an arithmetic type: - // - template , int>::type = 0> - explicit operator T ()const - { - result_type r(*this); - return static_cast(r); -} - template ::value || is_void::value || is_number::value, int>::type = 0> - explicit operator T ()const - { - return static_cast(static_cast(*this)); - } -# else - template , int>::type = 0> + explicit operator T() const { + result_type r(*this); + return static_cast(r); + } + template ::value || + is_void::value || + is_number::value, + int>::type = 0> + explicit operator T() const { + return static_cast(static_cast(*this)); + } +#else + template ::value || is_constructible::value, int>::type = 0 + , + typename boost::disable_if_c< + is_number::value || + is_constructible::value, + int>::type = 0 #endif -> - explicit operator T()const - { - return static_cast(static_cast(*this)); - } - BOOST_MP_FORCEINLINE explicit operator bool()const - { - result_type r(*this); - return static_cast(r); - } + > + explicit operator T() const { + return static_cast(static_cast(*this)); + } + BOOST_MP_FORCEINLINE explicit operator bool() const { + result_type r(*this); + return static_cast(r); + } #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800) - BOOST_MP_FORCEINLINE explicit operator void()const {} + BOOST_MP_FORCEINLINE explicit operator void() const {} +#endif #endif -# endif #else - operator unmentionable_type()const - { - return arg ? &unmentionable::proc : 0; - } + operator unmentionable_type() const { return arg ? &unmentionable::proc : 0; } #endif - template - T convert_to() - { - result_type r(*this); - return r.template convert_to(); - } + template T convert_to() { + result_type r(*this); + return r.template convert_to(); + } private: - typename expression_storage::type arg; - expression& operator=(const expression&); + typename expression_storage::type arg; + expression &operator=(const expression &); }; template -struct expression -{ - typedef mpl::int_<2> arity; - typedef typename arg_type::type left_type; - typedef typename arg_type::type right_type; - typedef typename left_type::result_type left_result_type; - typedef typename right_type::result_type right_result_type; - typedef typename combine_expression::type result_type; - typedef tag tag_type; - - expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {} +struct expression { + typedef mpl::int_<2> arity; + typedef typename arg_type::type left_type; + typedef typename arg_type::type right_type; + typedef typename left_type::result_type left_result_type; + typedef typename right_type::result_type right_result_type; + typedef typename combine_expression::type + result_type; + typedef tag tag_type; + + expression(const Arg1 &a1, const Arg2 &a2) : arg1(a1), arg2(a2) {} #ifndef BOOST_NO_CXX11_STATIC_ASSERT - // - // If we have static_assert we can give a more useful error message - // than if we simply have no operator defined at all: - // - template - expression& operator=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator+=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator-=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator*=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator/=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator%=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator|=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator&=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator^=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator<<=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator>>=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } + // + // If we have static_assert we can give a more useful error message + // than if we simply have no operator defined at all: + // + template expression &operator=(const Other &) { + // This should always fail: + static_assert(sizeof(Other) == INT_MAX, + "You can not assign to a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + template expression &operator+=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator+= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator-=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator-= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator*=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator*= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator/=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator/= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator%=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator%= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator|=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator|= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator&=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator&= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator^=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator^= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator<<=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator<<= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator>>=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator>>= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } #endif - left_type left()const { return left_type(arg1); } - right_type right()const { return right_type(arg2); } - const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; } - const Arg2& right_ref()const BOOST_NOEXCEPT { return arg2; } + left_type left() const { return left_type(arg1); } + right_type right() const { return right_type(arg2); } + const Arg1 &left_ref() const BOOST_NOEXCEPT { return arg1; } + const Arg2 &right_ref() const BOOST_NOEXCEPT { return arg2; } #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS -# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500)) - // - // Horrible workaround for gcc-4.6.x which always prefers the template - // operator bool() rather than the non-template operator when converting to - // an arithmetic type: - // - template , int>::type = 0> - explicit operator T ()const - { - result_type r(*this); - return static_cast(r); -} - template ::value || is_void::value || is_number::value, int>::type = 0> - explicit operator T ()const - { - return static_cast(static_cast(*this)); - } -# else - template , int>::type = 0> + explicit operator T() const { + result_type r(*this); + return static_cast(r); + } + template ::value || + is_void::value || + is_number::value, + int>::type = 0> + explicit operator T() const { + return static_cast(static_cast(*this)); + } +#else + template ::value || is_constructible::value, int>::type = 0 + , + typename boost::disable_if_c< + is_number::value || + is_constructible::value, + int>::type = 0 #endif -> - explicit operator T()const - { - return static_cast(static_cast(*this)); - } - BOOST_MP_FORCEINLINE explicit operator bool()const - { - result_type r(*this); - return static_cast(r); - } + > + explicit operator T() const { + return static_cast(static_cast(*this)); + } + BOOST_MP_FORCEINLINE explicit operator bool() const { + result_type r(*this); + return static_cast(r); + } #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800) - BOOST_MP_FORCEINLINE explicit operator void()const {} + BOOST_MP_FORCEINLINE explicit operator void() const {} +#endif #endif -# endif #else - operator unmentionable_type()const - { - result_type r(*this); - return r ? &unmentionable::proc : 0; - } + operator unmentionable_type() const { + result_type r(*this); + return r ? &unmentionable::proc : 0; + } #endif - template - T convert_to() - { - result_type r(*this); - return r.template convert_to(); - } - - static const unsigned left_depth = left_type::depth + 1; - static const unsigned right_depth = right_type::depth + 1; - static const unsigned depth = left_depth > right_depth ? left_depth : right_depth; + template T convert_to() { + result_type r(*this); + return r.template convert_to(); + } + + static const unsigned left_depth = left_type::depth + 1; + static const unsigned right_depth = right_type::depth + 1; + static const unsigned depth = + left_depth > right_depth ? left_depth : right_depth; + private: - typename expression_storage::type arg1; - typename expression_storage::type arg2; - expression& operator=(const expression&); + typename expression_storage::type arg1; + typename expression_storage::type arg2; + expression &operator=(const expression &); }; template -struct expression -{ - typedef mpl::int_<3> arity; - typedef typename arg_type::type left_type; - typedef typename arg_type::type middle_type; - typedef typename arg_type::type right_type; - typedef typename left_type::result_type left_result_type; - typedef typename middle_type::result_type middle_result_type; - typedef typename right_type::result_type right_result_type; - typedef typename combine_expression< +struct expression { + typedef mpl::int_<3> arity; + typedef typename arg_type::type left_type; + typedef typename arg_type::type middle_type; + typedef typename arg_type::type right_type; + typedef typename left_type::result_type left_result_type; + typedef typename middle_type::result_type middle_result_type; + typedef typename right_type::result_type right_result_type; + typedef typename combine_expression< left_result_type, - typename combine_expression::type - >::type result_type; - typedef tag tag_type; + typename combine_expression::type>::type result_type; + typedef tag tag_type; - expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {} + expression(const Arg1 &a1, const Arg2 &a2, const Arg3 &a3) + : arg1(a1), arg2(a2), arg3(a3) {} #ifndef BOOST_NO_CXX11_STATIC_ASSERT - // - // If we have static_assert we can give a more useful error message - // than if we simply have no operator defined at all: - // - template - expression& operator=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator+=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator-=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator*=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator/=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator%=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator|=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator&=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator^=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator<<=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator>>=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } + // + // If we have static_assert we can give a more useful error message + // than if we simply have no operator defined at all: + // + template expression &operator=(const Other &) { + // This should always fail: + static_assert(sizeof(Other) == INT_MAX, + "You can not assign to a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + template expression &operator+=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator+= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator-=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator-= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator*=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator*= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator/=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator/= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator%=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator%= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator|=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator|= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator&=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator&= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator^=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator^= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator<<=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator<<= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator>>=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator>>= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } #endif - left_type left()const { return left_type(arg1); } - middle_type middle()const { return middle_type(arg2); } - right_type right()const { return right_type(arg3); } - const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; } - const Arg2& middle_ref()const BOOST_NOEXCEPT { return arg2; } - const Arg3& right_ref()const BOOST_NOEXCEPT { return arg3; } + left_type left() const { return left_type(arg1); } + middle_type middle() const { return middle_type(arg2); } + right_type right() const { return right_type(arg3); } + const Arg1 &left_ref() const BOOST_NOEXCEPT { return arg1; } + const Arg2 &middle_ref() const BOOST_NOEXCEPT { return arg2; } + const Arg3 &right_ref() const BOOST_NOEXCEPT { return arg3; } #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS -# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500)) - // - // Horrible workaround for gcc-4.6.x which always prefers the template - // operator bool() rather than the non-template operator when converting to - // an arithmetic type: - // - template , int>::type = 0> - explicit operator T ()const - { - result_type r(*this); - return static_cast(r); -} - template ::value || is_void::value || is_number::value, int>::type = 0> - explicit operator T ()const - { - return static_cast(static_cast(*this)); - } -# else - template , int>::type = 0> + explicit operator T() const { + result_type r(*this); + return static_cast(r); + } + template ::value || + is_void::value || + is_number::value, + int>::type = 0> + explicit operator T() const { + return static_cast(static_cast(*this)); + } +#else + template ::value || is_constructible::value, int>::type = 0 + , + typename boost::disable_if_c< + is_number::value || + is_constructible::value, + int>::type = 0 #endif -> - explicit operator T()const - { - return static_cast(static_cast(*this)); - } - BOOST_MP_FORCEINLINE explicit operator bool()const - { - result_type r(*this); - return static_cast(r); - } + > + explicit operator T() const { + return static_cast(static_cast(*this)); + } + BOOST_MP_FORCEINLINE explicit operator bool() const { + result_type r(*this); + return static_cast(r); + } #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800) - BOOST_MP_FORCEINLINE explicit operator void()const {} + BOOST_MP_FORCEINLINE explicit operator void() const {} +#endif #endif -# endif #else - operator unmentionable_type()const - { - result_type r(*this); - return r ? &unmentionable::proc : 0; - } + operator unmentionable_type() const { + result_type r(*this); + return r ? &unmentionable::proc : 0; + } #endif - template - T convert_to() - { - result_type r(*this); - return r.template convert_to(); - } - - static const unsigned left_depth = left_type::depth + 1; - static const unsigned middle_depth = middle_type::depth + 1; - static const unsigned right_depth = right_type::depth + 1; - static const unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth); + template T convert_to() { + result_type r(*this); + return r.template convert_to(); + } + + static const unsigned left_depth = left_type::depth + 1; + static const unsigned middle_depth = middle_type::depth + 1; + static const unsigned right_depth = right_type::depth + 1; + static const unsigned + depth = left_depth > right_depth + ? (left_depth > middle_depth ? left_depth : middle_depth) + : (right_depth > middle_depth ? right_depth : middle_depth); + private: - typename expression_storage::type arg1; - typename expression_storage::type arg2; - typename expression_storage::type arg3; - expression& operator=(const expression&); + typename expression_storage::type arg1; + typename expression_storage::type arg2; + typename expression_storage::type arg3; + expression &operator=(const expression &); }; template -struct expression -{ - typedef mpl::int_<4> arity; - typedef typename arg_type::type left_type; - typedef typename arg_type::type left_middle_type; - typedef typename arg_type::type right_middle_type; - typedef typename arg_type::type right_type; - typedef typename left_type::result_type left_result_type; - typedef typename left_middle_type::result_type left_middle_result_type; - typedef typename right_middle_type::result_type right_middle_result_type; - typedef typename right_type::result_type right_result_type; - typedef typename combine_expression< +struct expression { + typedef mpl::int_<4> arity; + typedef typename arg_type::type left_type; + typedef typename arg_type::type left_middle_type; + typedef typename arg_type::type right_middle_type; + typedef typename arg_type::type right_type; + typedef typename left_type::result_type left_result_type; + typedef typename left_middle_type::result_type left_middle_result_type; + typedef typename right_middle_type::result_type right_middle_result_type; + typedef typename right_type::result_type right_result_type; + typedef typename combine_expression< left_result_type, typename combine_expression< - left_middle_result_type, - typename combine_expression::type - >::type - >::type result_type; - typedef tag tag_type; + left_middle_result_type, + typename combine_expression::type>::type>::type + result_type; + typedef tag tag_type; - expression(const Arg1& a1, const Arg2& a2, const Arg3& a3, const Arg4& a4) : arg1(a1), arg2(a2), arg3(a3), arg4(a4) {} + expression(const Arg1 &a1, const Arg2 &a2, const Arg3 &a3, const Arg4 &a4) + : arg1(a1), arg2(a2), arg3(a3), arg4(a4) {} #ifndef BOOST_NO_CXX11_STATIC_ASSERT - // - // If we have static_assert we can give a more useful error message - // than if we simply have no operator defined at all: - // - template - expression& operator=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator++(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--() - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - expression& operator--(int) - { - // This should always fail: - static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator+=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator-=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator*=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator/=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator%=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator|=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator&=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator^=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator<<=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } - template - expression& operator>>=(const Other&) - { - // This should always fail: - static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?"); - return *this; - } + // + // If we have static_assert we can give a more useful error message + // than if we simply have no operator defined at all: + // + template expression &operator=(const Other &) { + // This should always fail: + static_assert(sizeof(Other) == INT_MAX, + "You can not assign to a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator++(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not increment a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--() { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + expression &operator--(int) { + // This should always fail: + static_assert(sizeof(*this) == INT_MAX, + "You can not decrement a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression " + "template in a \"auto\" variable? Or pass an expression to " + "a template function with deduced temnplate arguments?"); + return *this; + } + template expression &operator+=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator+= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator-=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator-= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator*=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator*= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator/=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator/= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator%=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator%= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator|=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator|= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator&=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator&= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator^=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator^= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator<<=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator<<= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } + template expression &operator>>=(const Other &) { + // This should always fail: + static_assert( + sizeof(Other) == INT_MAX, + "You can not use operator>>= on a Boost.Multiprecision expression " + "template: did you inadvertantly store an expression template in a " + "\"auto\" variable? Or pass an expression to a template function with " + "deduced temnplate arguments?"); + return *this; + } #endif - left_type left()const { return left_type(arg1); } - left_middle_type left_middle()const { return left_middle_type(arg2); } - right_middle_type right_middle()const { return right_middle_type(arg3); } - right_type right()const { return right_type(arg4); } - const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; } - const Arg2& left_middle_ref()const BOOST_NOEXCEPT { return arg2; } - const Arg3& right_middle_ref()const BOOST_NOEXCEPT { return arg3; } - const Arg4& right_ref()const BOOST_NOEXCEPT { return arg4; } + left_type left() const { return left_type(arg1); } + left_middle_type left_middle() const { return left_middle_type(arg2); } + right_middle_type right_middle() const { return right_middle_type(arg3); } + right_type right() const { return right_type(arg4); } + const Arg1 &left_ref() const BOOST_NOEXCEPT { return arg1; } + const Arg2 &left_middle_ref() const BOOST_NOEXCEPT { return arg2; } + const Arg3 &right_middle_ref() const BOOST_NOEXCEPT { return arg3; } + const Arg4 &right_ref() const BOOST_NOEXCEPT { return arg4; } #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS -# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500)) - // - // Horrible workaround for gcc-4.6.x which always prefers the template - // operator bool() rather than the non-template operator when converting to - // an arithmetic type: - // - template , int>::type = 0> - explicit operator T ()const - { - result_type r(*this); - return static_cast(r); -} - template ::value || is_void::value || is_number::value, int>::type = 0> - explicit operator T ()const - { - return static_cast(static_cast(*this)); - } -# else - template , int>::type = 0> + explicit operator T() const { + result_type r(*this); + return static_cast(r); + } + template ::value || + is_void::value || + is_number::value, + int>::type = 0> + explicit operator T() const { + return static_cast(static_cast(*this)); + } +#else + template ::value || is_constructible::value, int>::type = 0 + , + typename boost::disable_if_c< + is_number::value || + is_constructible::value, + int>::type = 0 #endif -> - explicit operator T()const - { - return static_cast(static_cast(*this)); - } - BOOST_MP_FORCEINLINE explicit operator bool()const - { - result_type r(*this); - return static_cast(r); - } + > + explicit operator T() const { + return static_cast(static_cast(*this)); + } + BOOST_MP_FORCEINLINE explicit operator bool() const { + result_type r(*this); + return static_cast(r); + } #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800) - BOOST_MP_FORCEINLINE explicit operator void()const {} + BOOST_MP_FORCEINLINE explicit operator void() const {} +#endif #endif -# endif #else - operator unmentionable_type()const - { - result_type r(*this); - return r ? &unmentionable::proc : 0; - } + operator unmentionable_type() const { + result_type r(*this); + return r ? &unmentionable::proc : 0; + } #endif - template - T convert_to() - { - result_type r(*this); - return r.template convert_to(); - } - - static const unsigned left_depth = left_type::depth + 1; - static const unsigned left_middle_depth = left_middle_type::depth + 1; - static const unsigned right_middle_depth = right_middle_type::depth + 1; - static const unsigned right_depth = right_type::depth + 1; - - static const unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth; - static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth; - - static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth; + template T convert_to() { + result_type r(*this); + return r.template convert_to(); + } + + static const unsigned left_depth = left_type::depth + 1; + static const unsigned left_middle_depth = left_middle_type::depth + 1; + static const unsigned right_middle_depth = right_middle_type::depth + 1; + static const unsigned right_depth = right_type::depth + 1; + + static const unsigned left_max_depth = + left_depth > left_middle_depth ? left_depth : left_middle_depth; + static const unsigned right_max_depth = + right_depth > right_middle_depth ? right_depth : right_middle_depth; + + static const unsigned depth = + left_max_depth > right_max_depth ? left_max_depth : right_max_depth; + private: - typename expression_storage::type arg1; - typename expression_storage::type arg2; - typename expression_storage::type arg3; - typename expression_storage::type arg4; - expression& operator=(const expression&); + typename expression_storage::type arg1; + typename expression_storage::type arg2; + typename expression_storage::type arg3; + typename expression_storage::type arg4; + expression &operator=(const expression &); }; -template -struct digits2 -{ - BOOST_STATIC_ASSERT(std::numeric_limits::is_specialized); - BOOST_STATIC_ASSERT((std::numeric_limits::radix == 2) || (std::numeric_limits::radix == 10)); - // If we really have so many digits that this fails, then we're probably going to hit other problems anyway: - BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits::digits + 1)); - static const long m_value = std::numeric_limits::radix == 10 ? (((std::numeric_limits::digits + 1) * 1000L) / 301L) : std::numeric_limits::digits; - static inline BOOST_CONSTEXPR long value()BOOST_NOEXCEPT { return m_value; } +template struct digits2 { + BOOST_STATIC_ASSERT(std::numeric_limits::is_specialized); + BOOST_STATIC_ASSERT((std::numeric_limits::radix == 2) || + (std::numeric_limits::radix == 10)); + // If we really have so many digits that this fails, then we're probably going + // to hit other problems anyway: + BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits::digits + 1)); + static const long m_value = + std::numeric_limits::radix == 10 + ? (((std::numeric_limits::digits + 1) * 1000L) / 301L) + : std::numeric_limits::digits; + static inline BOOST_CONSTEXPR long value() BOOST_NOEXCEPT { return m_value; } }; #ifndef BOOST_MP_MIN_EXPONENT_DIGITS #ifdef _MSC_VER -# define BOOST_MP_MIN_EXPONENT_DIGITS 2 +#define BOOST_MP_MIN_EXPONENT_DIGITS 2 #else -# define BOOST_MP_MIN_EXPONENT_DIGITS 2 +#define BOOST_MP_MIN_EXPONENT_DIGITS 2 #endif #endif template -void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero) -{ - typedef typename S::size_type size_type; - bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; - bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; - bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint; - bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos; - - bool neg = str.size() && (str[0] == '-'); - - if(neg) - str.erase(0, 1); - - if(digits == 0) - { - digits = (std::max)(str.size(), size_type(16)); - } - - if(iszero || str.empty() || (str.find_first_not_of('0') == S::npos)) - { - // We will be printing zero, even though the value might not - // actually be zero (it just may have been rounded to zero). - str = "0"; - if(scientific || fixed) - { - str.append(1, '.'); - str.append(size_type(digits), '0'); - if(scientific) - str.append("e+00"); - } - else - { - if(showpoint) - { - str.append(1, '.'); - if(digits > 1) - str.append(size_type(digits - 1), '0'); - } +void format_float_string(S &str, boost::intmax_t my_exp, boost::intmax_t digits, + std::ios_base::fmtflags f, bool iszero) { + typedef typename S::size_type size_type; + bool scientific = + (f & std::ios_base::scientific) == std::ios_base::scientific; + bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; + bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint; + bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos; + + bool neg = str.size() && (str[0] == '-'); + + if (neg) + str.erase(0, 1); + + if (digits == 0) { + digits = (std::max)(str.size(), size_type(16)); + } + + if (iszero || str.empty() || (str.find_first_not_of('0') == S::npos)) { + // We will be printing zero, even though the value might not + // actually be zero (it just may have been rounded to zero). + str = "0"; + if (scientific || fixed) { + str.append(1, '.'); + str.append(size_type(digits), '0'); + if (scientific) + str.append("e+00"); + } else { + if (showpoint) { + str.append(1, '.'); + if (digits > 1) + str.append(size_type(digits - 1), '0'); } - if(neg) - str.insert(static_cast(0), 1, '-'); - else if(showpos) - str.insert(static_cast(0), 1, '+'); - return; - } - - if(!fixed && !scientific && !showpoint) - { - // - // Suppress trailing zeros: - // - std::string::iterator pos = str.end(); - while(pos != str.begin() && *--pos == '0'){} - if(pos != str.end()) - ++pos; - str.erase(pos, str.end()); - if(str.empty()) - str = '0'; - } - else if(!fixed || (my_exp >= 0)) - { - // - // Pad out the end with zero's if we need to: - // - boost::intmax_t chars = str.size(); - chars = digits - chars; - if(scientific) - ++chars; - if(chars > 0) - { - str.append(static_cast(chars), '0'); - } - } - - if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits))) - { - if(1 + my_exp > static_cast(str.size())) - { - // Just pad out the end with zeros: - str.append(static_cast(1 + my_exp - str.size()), '0'); - if(showpoint || fixed) - str.append("."); - } - else if(my_exp + 1 < static_cast(str.size())) - { - if(my_exp < 0) - { - str.insert(static_cast(0), static_cast(-1 - my_exp), '0'); - str.insert(static_cast(0), "0."); - } - else - { - // Insert the decimal point: - str.insert(static_cast(my_exp + 1), 1, '.'); - } - } - else if(showpoint || fixed) // we have exactly the digits we require to left of the point - str += "."; - - if(fixed) - { - // We may need to add trailing zeros: - boost::intmax_t l = str.find('.') + 1; - l = digits - (str.size() - l); - if(l > 0) - str.append(size_type(l), '0'); - } - } - else - { - BOOST_MP_USING_ABS - // Scientific format: - if(showpoint || (str.size() > 1)) - str.insert(static_cast(1u), 1, '.'); - str.append(static_cast(1u), 'e'); - S e = boost::lexical_cast(abs(my_exp)); - if(e.size() < BOOST_MP_MIN_EXPONENT_DIGITS) - e.insert(static_cast(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0'); - if(my_exp < 0) - e.insert(static_cast(0), 1, '-'); - else - e.insert(static_cast(0), 1, '+'); - str.append(e); - } - if(neg) + } + if (neg) str.insert(static_cast(0), 1, '-'); - else if(showpos) + else if (showpos) str.insert(static_cast(0), 1, '+'); + return; + } + + if (!fixed && !scientific && !showpoint) { + // + // Suppress trailing zeros: + // + std::string::iterator pos = str.end(); + while (pos != str.begin() && *--pos == '0') { + } + if (pos != str.end()) + ++pos; + str.erase(pos, str.end()); + if (str.empty()) + str = '0'; + } else if (!fixed || (my_exp >= 0)) { + // + // Pad out the end with zero's if we need to: + // + boost::intmax_t chars = str.size(); + chars = digits - chars; + if (scientific) + ++chars; + if (chars > 0) { + str.append(static_cast(chars), '0'); + } + } + + if (fixed || (!scientific && (my_exp >= -4) && (my_exp < digits))) { + if (1 + my_exp > static_cast(str.size())) { + // Just pad out the end with zeros: + str.append(static_cast(1 + my_exp - str.size()), + '0'); + if (showpoint || fixed) + str.append("."); + } else if (my_exp + 1 < static_cast(str.size())) { + if (my_exp < 0) { + str.insert(static_cast(0), + static_cast(-1 - my_exp), '0'); + str.insert(static_cast(0), "0."); + } else { + // Insert the decimal point: + str.insert(static_cast(my_exp + 1), 1, '.'); + } + } else if (showpoint || fixed) // we have exactly the digits we require to + // left of the point + str += "."; + + if (fixed) { + // We may need to add trailing zeros: + boost::intmax_t l = str.find('.') + 1; + l = digits - (str.size() - l); + if (l > 0) + str.append(size_type(l), '0'); + } + } else { + BOOST_MP_USING_ABS + // Scientific format: + if (showpoint || (str.size() > 1)) + str.insert(static_cast(1u), 1, '.'); + str.append(static_cast(1u), 'e'); + S e = boost::lexical_cast(abs(my_exp)); + if (e.size() < BOOST_MP_MIN_EXPONENT_DIGITS) + e.insert(static_cast(0), + BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0'); + if (my_exp < 0) + e.insert(static_cast(0), 1, '-'); + else + e.insert(static_cast(0), 1, '+'); + str.append(e); + } + if (neg) + str.insert(static_cast(0), 1, '-'); + else if (showpos) + str.insert(static_cast(0), 1, '+'); } template -void check_shift_range(V val, const mpl::true_&, const mpl::true_&) -{ - if(val > (std::numeric_limits::max)()) - BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits::max().")); - if(val < 0) - BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value.")); +void check_shift_range(V val, const mpl::true_ &, const mpl::true_ &) { + if (val > (std::numeric_limits::max)()) + BOOST_THROW_EXCEPTION( + std::out_of_range("Can not shift by a value greater than " + "std::numeric_limits::max().")); + if (val < 0) + BOOST_THROW_EXCEPTION( + std::out_of_range("Can not shift by a negative value.")); } template -void check_shift_range(V val, const mpl::false_&, const mpl::true_&) -{ - if(val < 0) - BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value.")); +void check_shift_range(V val, const mpl::false_ &, const mpl::true_ &) { + if (val < 0) + BOOST_THROW_EXCEPTION( + std::out_of_range("Can not shift by a negative value.")); } template -void check_shift_range(V val, const mpl::true_&, const mpl::false_&) -{ - if(val > (std::numeric_limits::max)()) - BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits::max().")); +void check_shift_range(V val, const mpl::true_ &, const mpl::false_ &) { + if (val > (std::numeric_limits::max)()) + BOOST_THROW_EXCEPTION( + std::out_of_range("Can not shift by a value greater than " + "std::numeric_limits::max().")); } template -void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT{} +void check_shift_range(V, const mpl::false_ &, + const mpl::false_ &) BOOST_NOEXCEPT {} -template -const T& evaluate_if_expression(const T& val) { return val; } +template const T &evaluate_if_expression(const T &val) { return val; } template -typename expression::result_type evaluate_if_expression(const expression& val) { return val; } - +typename expression::result_type +evaluate_if_expression(const expression &val) { + return val; +} } // namespace detail // -// Traits class, lets us know what kind of number we have, defaults to a floating point type: +// Traits class, lets us know what kind of number we have, defaults to a +// floating point type: // -enum number_category_type -{ - number_kind_unknown = -1, - number_kind_integer = 0, - number_kind_floating_point = 1, - number_kind_rational = 2, - number_kind_fixed_point = 3, - number_kind_complex = 4, - number_kind_modulus = 5 +enum number_category_type { + number_kind_unknown = -1, + number_kind_integer = 0, + number_kind_floating_point = 1, + number_kind_rational = 2, + number_kind_fixed_point = 3, + number_kind_complex = 4, + number_kind_modulus = 5 }; template struct number_category_base : public mpl::int_ {}; template -struct number_category_base : public mpl::int_::is_integer ? number_kind_integer : (std::numeric_limits::max_exponent ? number_kind_floating_point : number_kind_unknown)> {}; +struct number_category_base + : public mpl::int_::is_integer + ? number_kind_integer + : (std::numeric_limits::max_exponent + ? number_kind_floating_point + : number_kind_unknown)> {}; template -struct number_category : public number_category_base::value || boost::is_arithmetic::value, boost::is_abstract::value> {}; +struct number_category + : public number_category_base< + Num, boost::is_class::value || boost::is_arithmetic::value, + boost::is_abstract::value> {}; template -struct number_category > : public number_category{}; +struct number_category> + : public number_category {}; template -struct number_category > : public number_category::result_type>{}; +struct number_category> + : public number_category< + typename detail::expression::result_type> {}; // -// Specializations for types which do not always have numberic_limits specializations: +// Specializations for types which do not always have numberic_limits +// specializations: // #ifdef BOOST_HAS_INT128 template <> -struct number_category : public mpl::int_ {}; +struct number_category + : public mpl::int_ {}; template <> -struct number_category : public mpl::int_ {}; +struct number_category + : public mpl::int_ {}; #endif #ifdef BOOST_HAS_FLOAT128 template <> -struct number_category<__float128> : public mpl::int_ {}; +struct number_category<__float128> + : public mpl::int_ {}; #endif -template -struct component_type { typedef T type; }; +template struct component_type { typedef T type; }; template -struct component_type > : public component_type::result_type>{}; +struct component_type> + : public component_type< + typename detail::expression::result_type> {}; -template -struct scalar_result_from_possible_complex -{ - typedef typename mpl::if_c::value == number_kind_complex, - typename component_type::type, T>::type type; +template struct scalar_result_from_possible_complex { + typedef typename mpl::if_c::value == number_kind_complex, + typename component_type::type, T>::type type; }; template -struct complex_result_from_scalar; // individual backends must specialize this trait. +struct complex_result_from_scalar; // individual backends must specialize this + // trait. -template -struct is_unsigned_number : public mpl::false_{}; +template struct is_unsigned_number : public mpl::false_ {}; template -struct is_unsigned_number > : public is_unsigned_number {}; +struct is_unsigned_number> + : public is_unsigned_number {}; template struct is_signed_number : public mpl::bool_::value> {}; -template -struct is_interval_number : public mpl::false_ {}; +template struct is_interval_number : public mpl::false_ {}; template -struct is_interval_number > : public is_interval_number{}; +struct is_interval_number> + : public is_interval_number {}; -}} // namespaces +} // namespace multiprecision +} // namespace boost -namespace boost{ namespace math{ namespace tools{ +namespace boost { +namespace math { +namespace tools { -template -struct promote_arg; +template struct promote_arg; template -struct promote_arg > -{ - typedef typename boost::multiprecision::detail::expression::result_type type; +struct promote_arg< + boost::multiprecision::detail::expression> { + typedef + typename boost::multiprecision::detail::expression::result_type type; }; -template -inline R real_cast(const boost::multiprecision::number& val) -{ - return val.template convert_to(); +template +inline R real_cast(const boost::multiprecision::number &val) { + return val.template convert_to(); } template -inline R real_cast(const boost::multiprecision::detail::expression& val) -{ - typedef typename boost::multiprecision::detail::expression::result_type val_type; - return val_type(val).template convert_to(); +inline R real_cast( + const boost::multiprecision::detail::expression &val) { + typedef typename boost::multiprecision::detail::expression< + tag, A1, A2, A3, A4>::result_type val_type; + return val_type(val).template convert_to(); } +} // namespace tools -} - -namespace constants{ +namespace constants { - template - struct is_explicitly_convertible_from_string; +template struct is_explicitly_convertible_from_string; - template - struct is_explicitly_convertible_from_string > - { - static const bool value = true; - }; +template +struct is_explicitly_convertible_from_string< + boost::multiprecision::number> { + static const bool value = true; +}; -} +} // namespace constants -}} +} // namespace math +} // namespace boost #ifdef BOOST_MSVC -# pragma warning(pop) +#pragma warning(pop) #endif #endif // BOOST_MATH_BIG_NUM_BASE_HPP diff --git a/include/boost/multiprecision/detail/ublas_interop.hpp b/include/boost/multiprecision/detail/ublas_interop.hpp index cf56dc9fb..f1416c5a0 100644 --- a/include/boost/multiprecision/detail/ublas_interop.hpp +++ b/include/boost/multiprecision/detail/ublas_interop.hpp @@ -6,72 +6,107 @@ #ifndef BOOST_MP_UBLAS_HPP #define BOOST_MP_UBLAS_HPP -namespace boost { namespace numeric { namespace ublas { +namespace boost { +namespace numeric { +namespace ublas { -template -class sparse_vector_element; +template class sparse_vector_element; -template -inline bool operator == (const sparse_vector_element& a, const ::boost::multiprecision::number& b) -{ - typedef typename sparse_vector_element::const_reference ref_type; - return static_cast(a) == b; +template +inline bool operator==( + const sparse_vector_element &a, + const ::boost::multiprecision::number &b) { + typedef typename sparse_vector_element::const_reference ref_type; + return static_cast(a) == b; } -template -struct promote_traits; +template struct promote_traits; -template -struct promote_traits, boost::multiprecision::number > -{ - typedef boost::multiprecision::number number1_t; - typedef boost::multiprecision::number number2_t; - typedef typename mpl::if_c< - is_convertible::value && !is_convertible::value, - number2_t, number1_t - >::type promote_type; +template < + class Backend1, + boost::multiprecision::expression_template_option ExpressionTemplates1, + class Backend2, + boost::multiprecision::expression_template_option ExpressionTemplates2> +struct promote_traits< + boost::multiprecision::number, + boost::multiprecision::number> { + typedef boost::multiprecision::number + number1_t; + typedef boost::multiprecision::number + number2_t; + typedef typename mpl::if_c::value && + !is_convertible::value, + number2_t, number1_t>::type promote_type; }; -template -struct promote_traits, Arithmetic> -{ - typedef boost::multiprecision::number promote_type; +template < + class Backend1, + boost::multiprecision::expression_template_option ExpressionTemplates1, + class Arithmetic> +struct promote_traits< + boost::multiprecision::number, Arithmetic> { + typedef boost::multiprecision::number + promote_type; }; -template -struct promote_traits > -{ - typedef boost::multiprecision::number promote_type; +template < + class Arithmetic, class Backend1, + boost::multiprecision::expression_template_option ExpressionTemplates1> +struct promote_traits< + Arithmetic, boost::multiprecision::number> { + typedef boost::multiprecision::number + promote_type; }; -template -struct promote_traits, boost::multiprecision::detail::expression > -{ - typedef boost::multiprecision::number number1_t; - typedef boost::multiprecision::detail::expression expression_type; - typedef typename expression_type::result_type number2_t; - typedef typename promote_traits::promote_type promote_type; +template < + class Backend1, + boost::multiprecision::expression_template_option ExpressionTemplates1, + class tag, class Arg1, class Arg2, class Arg3, class Arg4> +struct promote_traits< + boost::multiprecision::number, + boost::multiprecision::detail::expression> { + typedef boost::multiprecision::number + number1_t; + typedef boost::multiprecision::detail::expression + expression_type; + typedef typename expression_type::result_type number2_t; + typedef + typename promote_traits::promote_type promote_type; }; -template -struct promote_traits, boost::multiprecision::number > -{ - typedef boost::multiprecision::number number1_t; - typedef boost::multiprecision::detail::expression expression_type; - typedef typename expression_type::result_type number2_t; - typedef typename promote_traits::promote_type promote_type; +template < + class tag, class Arg1, class Arg2, class Arg3, class Arg4, class Backend1, + boost::multiprecision::expression_template_option ExpressionTemplates1> +struct promote_traits< + boost::multiprecision::detail::expression, + boost::multiprecision::number> { + typedef boost::multiprecision::number + number1_t; + typedef boost::multiprecision::detail::expression + expression_type; + typedef typename expression_type::result_type number2_t; + typedef + typename promote_traits::promote_type promote_type; }; -template -struct promote_traits, boost::multiprecision::detail::expression > -{ - typedef boost::multiprecision::detail::expression expression1_t; - typedef typename expression1_t::result_type number1_t; - typedef boost::multiprecision::detail::expression expression2_t; - typedef typename expression2_t::result_type number2_t; +template +struct promote_traits< + boost::multiprecision::detail::expression, + boost::multiprecision::detail::expression> { + typedef boost::multiprecision::detail::expression + expression1_t; + typedef typename expression1_t::result_type number1_t; + typedef boost::multiprecision::detail::expression + expression2_t; + typedef typename expression2_t::result_type number2_t; }; -}}} // namespace +} // namespace ublas +} // namespace numeric +} // namespace boost #endif - diff --git a/include/boost/multiprecision/detail/utype_helper.hpp b/include/boost/multiprecision/detail/utype_helper.hpp index 000a74b47..1d6fffbb0 100644 --- a/include/boost/multiprecision/detail/utype_helper.hpp +++ b/include/boost/multiprecision/detail/utype_helper.hpp @@ -6,105 +6,107 @@ // #ifndef BOOST_MP_UTYPE_HELPER_HPP - #define BOOST_MP_UTYPE_HELPER_HPP +#define BOOST_MP_UTYPE_HELPER_HPP - #include - #include +#include +#include - namespace boost { namespace multiprecision { - namespace detail - { - template struct utype_helper { typedef boost::uint64_t exact; }; - template<> struct utype_helper<0U> { typedef boost::uint8_t exact; }; - template<> struct utype_helper<1U> { typedef boost::uint8_t exact; }; - template<> struct utype_helper<2U> { typedef boost::uint8_t exact; }; - template<> struct utype_helper<3U> { typedef boost::uint8_t exact; }; - template<> struct utype_helper<4U> { typedef boost::uint8_t exact; }; - template<> struct utype_helper<5U> { typedef boost::uint8_t exact; }; - template<> struct utype_helper<6U> { typedef boost::uint8_t exact; }; - template<> struct utype_helper<7U> { typedef boost::uint8_t exact; }; - template<> struct utype_helper<8U> { typedef boost::uint8_t exact; }; +namespace boost { +namespace multiprecision { +namespace detail { +template struct utype_helper { + typedef boost::uint64_t exact; +}; +template <> struct utype_helper<0U> { typedef boost::uint8_t exact; }; +template <> struct utype_helper<1U> { typedef boost::uint8_t exact; }; +template <> struct utype_helper<2U> { typedef boost::uint8_t exact; }; +template <> struct utype_helper<3U> { typedef boost::uint8_t exact; }; +template <> struct utype_helper<4U> { typedef boost::uint8_t exact; }; +template <> struct utype_helper<5U> { typedef boost::uint8_t exact; }; +template <> struct utype_helper<6U> { typedef boost::uint8_t exact; }; +template <> struct utype_helper<7U> { typedef boost::uint8_t exact; }; +template <> struct utype_helper<8U> { typedef boost::uint8_t exact; }; - template<> struct utype_helper<9U> { typedef boost::uint16_t exact; }; - template<> struct utype_helper<10U> { typedef boost::uint16_t exact; }; - template<> struct utype_helper<11U> { typedef boost::uint16_t exact; }; - template<> struct utype_helper<12U> { typedef boost::uint16_t exact; }; - template<> struct utype_helper<13U> { typedef boost::uint16_t exact; }; - template<> struct utype_helper<14U> { typedef boost::uint16_t exact; }; - template<> struct utype_helper<15U> { typedef boost::uint16_t exact; }; - template<> struct utype_helper<16U> { typedef boost::uint16_t exact; }; +template <> struct utype_helper<9U> { typedef boost::uint16_t exact; }; +template <> struct utype_helper<10U> { typedef boost::uint16_t exact; }; +template <> struct utype_helper<11U> { typedef boost::uint16_t exact; }; +template <> struct utype_helper<12U> { typedef boost::uint16_t exact; }; +template <> struct utype_helper<13U> { typedef boost::uint16_t exact; }; +template <> struct utype_helper<14U> { typedef boost::uint16_t exact; }; +template <> struct utype_helper<15U> { typedef boost::uint16_t exact; }; +template <> struct utype_helper<16U> { typedef boost::uint16_t exact; }; - template<> struct utype_helper<17U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<18U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<19U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<20U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<21U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<22U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<23U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<24U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<25U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<26U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<27U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<28U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<29U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<30U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<31U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<32U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<17U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<18U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<19U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<20U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<21U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<22U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<23U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<24U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<25U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<26U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<27U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<28U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<29U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<30U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<31U> { typedef boost::uint32_t exact; }; +template <> struct utype_helper<32U> { typedef boost::uint32_t exact; }; - template<> struct utype_helper<33U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<34U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<35U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<36U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<37U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<38U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<39U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<40U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<41U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<42U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<43U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<44U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<45U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<46U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<47U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<48U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<49U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<50U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<51U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<52U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<53U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<54U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<55U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<56U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<57U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<58U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<59U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<60U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<61U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<62U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<63U> { typedef boost::uint64_t exact; }; - template<> struct utype_helper<64U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<33U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<34U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<35U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<36U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<37U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<38U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<39U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<40U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<41U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<42U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<43U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<44U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<45U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<46U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<47U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<48U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<49U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<50U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<51U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<52U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<53U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<54U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<55U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<56U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<57U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<58U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<59U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<60U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<61U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<62U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<63U> { typedef boost::uint64_t exact; }; +template <> struct utype_helper<64U> { typedef boost::uint64_t exact; }; - template - int utype_prior(unsigned_type ui) - { - // TBD: Implement a templated binary search for this. - int priority_bit; +template int utype_prior(unsigned_type ui) { + // TBD: Implement a templated binary search for this. + int priority_bit; - unsigned_type priority_mask = unsigned_type(unsigned_type(1U) << (std::numeric_limits::digits - 1)); + unsigned_type priority_mask = unsigned_type( + unsigned_type(1U) << (std::numeric_limits::digits - 1)); - for(priority_bit = std::numeric_limits::digits - 1; priority_bit >= 0; --priority_bit) - { - if(unsigned_type(priority_mask & ui) != unsigned_type(0U)) - { - break; - } - - priority_mask >>= 1; + for (priority_bit = std::numeric_limits::digits - 1; + priority_bit >= 0; --priority_bit) { + if (unsigned_type(priority_mask & ui) != unsigned_type(0U)) { + break; } - return priority_bit; + priority_mask >>= 1; } - } } } + return priority_bit; +} + +} // namespace detail +} // namespace multiprecision +} // namespace boost #endif // BOOST_MP_UTYPE_HELPER_HPP diff --git a/include/boost/multiprecision/gmp.hpp b/include/boost/multiprecision/gmp.hpp index a03b75b9c..6b2bab9bd 100644 --- a/include/boost/multiprecision/gmp.hpp +++ b/include/boost/multiprecision/gmp.hpp @@ -6,421 +6,396 @@ #ifndef BOOST_MATH_ER_GMP_BACKEND_HPP #define BOOST_MATH_ER_GMP_BACKEND_HPP -#include +#include +#include +#include #include -#include #include #include -#include -#include -#include +#include +#include // -// Some includes we need from Boost.Math, since we rely on that library to provide these functions: +// Some includes we need from Boost.Math, since we rely on that library to +// provide these functions: // -#include #include +#include #include #include #include #include #ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable:4127) +#pragma warning(push) +#pragma warning(disable : 4127) #endif #include #ifdef BOOST_MSVC -# pragma warning(pop) +#pragma warning(pop) #endif -#if defined(__MPIR_VERSION) && defined(__MPIR_VERSION_MINOR) && defined(__MPIR_VERSION_PATCHLEVEL) -# define BOOST_MP_MPIR_VERSION (__MPIR_VERSION * 10000 + __MPIR_VERSION_MINOR * 100 + __MPIR_VERSION_PATCHLEVEL) +#if defined(__MPIR_VERSION) && defined(__MPIR_VERSION_MINOR) && \ + defined(__MPIR_VERSION_PATCHLEVEL) +#define BOOST_MP_MPIR_VERSION \ + (__MPIR_VERSION * 10000 + __MPIR_VERSION_MINOR * 100 + \ + __MPIR_VERSION_PATCHLEVEL) #else -# define BOOST_MP_MPIR_VERSION 0 +#define BOOST_MP_MPIR_VERSION 0 #endif #include +#include #include #include -#include -namespace boost{ -namespace multiprecision{ -namespace backends{ +namespace boost { +namespace multiprecision { +namespace backends { #ifdef BOOST_MSVC // warning C4127: conditional expression is constant #pragma warning(push) -#pragma warning(disable:4127) +#pragma warning(disable : 4127) #endif -template -struct gmp_float; +template struct gmp_float; struct gmp_int; struct gmp_rational; } // namespace backends -template<> -struct number_category : public mpl::int_{}; -template<> -struct number_category : public mpl::int_{}; +template <> +struct number_category + : public mpl::int_ {}; +template <> +struct number_category + : public mpl::int_ {}; template -struct number_category > : public mpl::int_{}; +struct number_category> + : public mpl::int_ {}; -namespace backends{ +namespace backends { // -// Within this file, the only functions we mark as noexcept are those that manipulate -// (but don't create) an mpf_t. All other types may allocate at pretty much any time -// via a user-supplied allocator, and therefore throw. +// Within this file, the only functions we mark as noexcept are those that +// manipulate (but don't create) an mpf_t. All other types may allocate at +// pretty much any time via a user-supplied allocator, and therefore throw. // -namespace detail{ +namespace detail { -template -struct gmp_float_imp -{ +template struct gmp_float_imp { #ifdef BOOST_HAS_LONG_LONG - typedef mpl::list signed_types; - typedef mpl::list unsigned_types; + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; #else - typedef mpl::list signed_types; - typedef mpl::list unsigned_types; + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; #endif - typedef mpl::list float_types; - typedef long exponent_type; - - gmp_float_imp() BOOST_NOEXCEPT - { - m_data[0]._mp_d = 0; // uninitialized m_data - } - - gmp_float_imp(const gmp_float_imp& o) - { - // - // We have to do an init followed by a set here, otherwise *this may be at - // a lower precision than o: seems like mpf_init_set copies just enough bits - // to get the right value, but if it's then used in further calculations - // things go badly wrong!! - // - mpf_init2(m_data, mpf_get_prec(o.data())); - if(o.m_data[0]._mp_d) - mpf_set(m_data, o.m_data); - } + typedef mpl::list float_types; + typedef long exponent_type; + + gmp_float_imp() BOOST_NOEXCEPT { + m_data[0]._mp_d = 0; // uninitialized m_data + } + + gmp_float_imp(const gmp_float_imp &o) { + // + // We have to do an init followed by a set here, otherwise *this may be at + // a lower precision than o: seems like mpf_init_set copies just enough bits + // to get the right value, but if it's then used in further calculations + // things go badly wrong!! + // + mpf_init2(m_data, mpf_get_prec(o.data())); + if (o.m_data[0]._mp_d) + mpf_set(m_data, o.m_data); + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_float_imp(gmp_float_imp&& o) BOOST_NOEXCEPT - { - m_data[0] = o.m_data[0]; - o.m_data[0]._mp_d = 0; - } + gmp_float_imp(gmp_float_imp &&o) BOOST_NOEXCEPT { + m_data[0] = o.m_data[0]; + o.m_data[0]._mp_d = 0; + } #endif - gmp_float_imp& operator = (const gmp_float_imp& o) - { - if(m_data[0]._mp_d == 0) - mpf_init2(m_data, mpf_get_prec(o.data())); - if (mpf_get_prec(data()) != mpf_get_prec(o.data())) - { - mpf_t t; - mpf_init2(t, mpf_get_prec(o.data())); - mpf_set(t, o.data()); - mpf_swap(data(), t); - mpf_clear(t); - } - else - { - if (o.m_data[0]._mp_d) - mpf_set(m_data, o.m_data); - } - return *this; - } + gmp_float_imp &operator=(const gmp_float_imp &o) { + if (m_data[0]._mp_d == 0) + mpf_init2(m_data, mpf_get_prec(o.data())); + if (mpf_get_prec(data()) != mpf_get_prec(o.data())) { + mpf_t t; + mpf_init2(t, mpf_get_prec(o.data())); + mpf_set(t, o.data()); + mpf_swap(data(), t); + mpf_clear(t); + } else { + if (o.m_data[0]._mp_d) + mpf_set(m_data, o.m_data); + } + return *this; + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_float_imp& operator = (gmp_float_imp&& o) BOOST_NOEXCEPT - { - mpf_swap(m_data, o.m_data); - return *this; - } + gmp_float_imp &operator=(gmp_float_imp &&o) BOOST_NOEXCEPT { + mpf_swap(m_data, o.m_data); + return *this; + } #endif #ifdef BOOST_HAS_LONG_LONG #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) - gmp_float_imp& operator = (boost::ulong_long_type i) - { - *this = static_cast(i); - return *this; - } + gmp_float_imp &operator=(boost::ulong_long_type i) { + *this = static_cast(i); + return *this; + } #else - gmp_float_imp& operator = (boost::ulong_long_type i) - { - if(m_data[0]._mp_d == 0) - mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); - boost::ulong_long_type mask = ((((1uLL << (std::numeric_limits::digits - 1)) - 1) << 1) | 1uLL); - unsigned shift = 0; - mpf_t t; - mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); - mpf_set_ui(m_data, 0); - while(i) - { - mpf_set_ui(t, static_cast(i & mask)); - if(shift) - mpf_mul_2exp(t, t, shift); - mpf_add(m_data, m_data, t); - shift += std::numeric_limits::digits; - i >>= std::numeric_limits::digits; - } - mpf_clear(t); - return *this; - } + gmp_float_imp &operator=(boost::ulong_long_type i) { + if (m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2( + digits10 ? digits10 : get_default_precision())); + boost::ulong_long_type mask = + ((((1uLL << (std::numeric_limits::digits - 1)) - 1) + << 1) | + 1uLL); + unsigned shift = 0; + mpf_t t; + mpf_init2(t, multiprecision::detail::digits10_2_2( + digits10 ? digits10 : get_default_precision())); + mpf_set_ui(m_data, 0); + while (i) { + mpf_set_ui(t, static_cast(i & mask)); + if (shift) + mpf_mul_2exp(t, t, shift); + mpf_add(m_data, m_data, t); + shift += std::numeric_limits::digits; + i >>= std::numeric_limits::digits; + } + mpf_clear(t); + return *this; + } #endif - gmp_float_imp& operator = (boost::long_long_type i) - { - if(m_data[0]._mp_d == 0) - mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); - bool neg = i < 0; - *this = static_cast(boost::multiprecision::detail::unsigned_abs(i)); - if(neg) - mpf_neg(m_data, m_data); - return *this; - } + gmp_float_imp &operator=(boost::long_long_type i) { + if (m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2( + digits10 ? digits10 : get_default_precision())); + bool neg = i < 0; + *this = static_cast( + boost::multiprecision::detail::unsigned_abs(i)); + if (neg) + mpf_neg(m_data, m_data); + return *this; + } #endif - gmp_float_imp& operator = (unsigned long i) - { - if(m_data[0]._mp_d == 0) - mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); - mpf_set_ui(m_data, i); - return *this; - } - gmp_float_imp& operator = (long i) - { - if(m_data[0]._mp_d == 0) - mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); - mpf_set_si(m_data, i); + gmp_float_imp &operator=(unsigned long i) { + if (m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2( + digits10 ? digits10 : get_default_precision())); + mpf_set_ui(m_data, i); + return *this; + } + gmp_float_imp &operator=(long i) { + if (m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2( + digits10 ? digits10 : get_default_precision())); + mpf_set_si(m_data, i); + return *this; + } + gmp_float_imp &operator=(double d) { + if (m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2( + digits10 ? digits10 : get_default_precision())); + mpf_set_d(m_data, d); + return *this; + } + gmp_float_imp &operator=(long double a) { + using std::floor; + using std::frexp; + using std::ldexp; + + if (m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2( + digits10 ? digits10 : get_default_precision())); + + if (a == 0) { + mpf_set_si(m_data, 0); return *this; - } - gmp_float_imp& operator = (double d) - { - if(m_data[0]._mp_d == 0) - mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); - mpf_set_d(m_data, d); + } + + if (a == 1) { + mpf_set_si(m_data, 1); return *this; - } - gmp_float_imp& operator = (long double a) - { - using std::frexp; - using std::ldexp; - using std::floor; - - if(m_data[0]._mp_d == 0) - mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); - - if (a == 0) { - mpf_set_si(m_data, 0); - return *this; - } + } - if (a == 1) { - mpf_set_si(m_data, 1); - return *this; - } + BOOST_ASSERT(!(boost::math::isinf)(a)); + BOOST_ASSERT(!(boost::math::isnan)(a)); - BOOST_ASSERT(!(boost::math::isinf)(a)); - BOOST_ASSERT(!(boost::math::isnan)(a)); - - int e; - long double f, term; - mpf_set_ui(m_data, 0u); - - f = frexp(a, &e); - - static const int shift = std::numeric_limits::digits - 1; - - while(f) - { - // extract int sized bits from f: - f = ldexp(f, shift); - term = floor(f); - e -= shift; - mpf_mul_2exp(m_data, m_data, shift); - if(term > 0) - mpf_add_ui(m_data, m_data, static_cast(term)); - else - mpf_sub_ui(m_data, m_data, static_cast(-term)); - f -= term; - } - if(e > 0) - mpf_mul_2exp(m_data, m_data, e); - else if(e < 0) - mpf_div_2exp(m_data, m_data, -e); - return *this; - } - gmp_float_imp& operator = (const char* s) - { - if(m_data[0]._mp_d == 0) - mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); - if(0 != mpf_set_str(m_data, s, 10)) - BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid floating point number."))); - return *this; - } - void swap(gmp_float_imp& o) BOOST_NOEXCEPT - { - mpf_swap(m_data, o.m_data); - } - std::string str(std::streamsize digits, std::ios_base::fmtflags f)const - { - BOOST_ASSERT(m_data[0]._mp_d); - - bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; - bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; - std::streamsize org_digits(digits); - - if(scientific && digits) - ++digits; - - std::string result; - mp_exp_t e; - void *(*alloc_func_ptr) (size_t); - void *(*realloc_func_ptr) (void *, size_t, size_t); - void (*free_func_ptr) (void *, size_t); - mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); - - if(mpf_sgn(m_data) == 0) - { - e = 0; - result = "0"; - if(fixed && digits) - ++digits; - } + int e; + long double f, term; + mpf_set_ui(m_data, 0u); + + f = frexp(a, &e); + + static const int shift = std::numeric_limits::digits - 1; + + while (f) { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + mpf_mul_2exp(m_data, m_data, shift); + if (term > 0) + mpf_add_ui(m_data, m_data, static_cast(term)); else - { - char* ps = mpf_get_str (0, &e, 10, static_cast(digits), m_data); - --e; // To match with what our formatter expects. - if(fixed && e != -1) - { - // Oops we actually need a different number of digits to what we asked for: - (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); - digits += e + 1; - if(digits == 0) - { - // We need to get *all* the digits and then possibly round up, - // we end up with either "0" or "1" as the result. - ps = mpf_get_str (0, &e, 10, 0, m_data); - --e; - unsigned offset = *ps == '-' ? 1 : 0; - if(ps[offset] > '5') - { - ++e; - ps[offset] = '1'; - ps[offset + 1] = 0; - } - else if(ps[offset] == '5') - { - unsigned i = offset + 1; - bool round_up = false; - while(ps[i] != 0) - { - if(ps[i] != '0') - { - round_up = true; - break; - } - ++i; - } - if(round_up) - { - ++e; - ps[offset] = '1'; - ps[offset + 1] = 0; - } - else - { - ps[offset] = '0'; - ps[offset + 1] = 0; - } - } - else - { - ps[offset] = '0'; - ps[offset + 1] = 0; - } - } - else if(digits > 0) - { - mp_exp_t old_e = e; - ps = mpf_get_str (0, &e, 10, static_cast(digits), m_data); - --e; // To match with what our formatter expects. - if (old_e > e) - { - // in some cases, when we ask for more digits of precision, it will - // change the number of digits to the left of the decimal, if that - // happens, account for it here. - // example: cout << fixed << setprecision(3) << mpf_float_50("99.9809") - digits -= old_e - e; - ps = mpf_get_str (0, &e, 10, static_cast(digits), m_data); - --e; // To match with what our formatter expects. - } + mpf_sub_ui(m_data, m_data, static_cast(-term)); + f -= term; + } + if (e > 0) + mpf_mul_2exp(m_data, m_data, e); + else if (e < 0) + mpf_div_2exp(m_data, m_data, -e); + return *this; + } + gmp_float_imp &operator=(const char *s) { + if (m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2( + digits10 ? digits10 : get_default_precision())); + if (0 != mpf_set_str(m_data, s, 10)) + BOOST_THROW_EXCEPTION(std::runtime_error( + std::string("The string \"") + s + + std::string( + "\"could not be interpreted as a valid floating point number."))); + return *this; + } + void swap(gmp_float_imp &o) BOOST_NOEXCEPT { mpf_swap(m_data, o.m_data); } + std::string str(std::streamsize digits, std::ios_base::fmtflags f) const { + BOOST_ASSERT(m_data[0]._mp_d); + + bool scientific = + (f & std::ios_base::scientific) == std::ios_base::scientific; + bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; + std::streamsize org_digits(digits); + + if (scientific && digits) + ++digits; + + std::string result; + mp_exp_t e; + void *(*alloc_func_ptr)(size_t); + void *(*realloc_func_ptr)(void *, size_t, size_t); + void (*free_func_ptr)(void *, size_t); + mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); + + if (mpf_sgn(m_data) == 0) { + e = 0; + result = "0"; + if (fixed && digits) + ++digits; + } else { + char *ps = + mpf_get_str(0, &e, 10, static_cast(digits), m_data); + --e; // To match with what our formatter expects. + if (fixed && e != -1) { + // Oops we actually need a different number of digits to what we asked + // for: + (*free_func_ptr)((void *)ps, std::strlen(ps) + 1); + digits += e + 1; + if (digits == 0) { + // We need to get *all* the digits and then possibly round up, + // we end up with either "0" or "1" as the result. + ps = mpf_get_str(0, &e, 10, 0, m_data); + --e; + unsigned offset = *ps == '-' ? 1 : 0; + if (ps[offset] > '5') { + ++e; + ps[offset] = '1'; + ps[offset + 1] = 0; + } else if (ps[offset] == '5') { + unsigned i = offset + 1; + bool round_up = false; + while (ps[i] != 0) { + if (ps[i] != '0') { + round_up = true; + break; + } + ++i; } - else - { - ps = mpf_get_str (0, &e, 10, 1, m_data); - --e; - unsigned offset = *ps == '-' ? 1 : 0; - ps[offset] = '0'; - ps[offset + 1] = 0; + if (round_up) { + ++e; + ps[offset] = '1'; + ps[offset + 1] = 0; + } else { + ps[offset] = '0'; + ps[offset + 1] = 0; } - } - result = ps; - (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); + } else { + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } else if (digits > 0) { + mp_exp_t old_e = e; + ps = mpf_get_str(0, &e, 10, static_cast(digits), m_data); + --e; // To match with what our formatter expects. + if (old_e > e) { + // in some cases, when we ask for more digits of precision, it will + // change the number of digits to the left of the decimal, if that + // happens, account for it here. + // example: cout << fixed << setprecision(3) << + // mpf_float_50("99.9809") + digits -= old_e - e; + ps = mpf_get_str(0, &e, 10, static_cast(digits), + m_data); + --e; // To match with what our formatter expects. + } + } else { + ps = mpf_get_str(0, &e, 10, 1, m_data); + --e; + unsigned offset = *ps == '-' ? 1 : 0; + ps[offset] = '0'; + ps[offset + 1] = 0; + } } - boost::multiprecision::detail::format_float_string(result, e, org_digits, f, mpf_sgn(m_data) == 0); - return result; - } - ~gmp_float_imp() BOOST_NOEXCEPT - { - if(m_data[0]._mp_d) - mpf_clear(m_data); - } - void negate() BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - mpf_neg(m_data, m_data); - } - int compare(const gmp_float& o)const BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); - return mpf_cmp(m_data, o.m_data); - } - int compare(long i)const BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - return mpf_cmp_si(m_data, i); - } - int compare(unsigned long i)const BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - return mpf_cmp_ui(m_data, i); - } - template - typename enable_if, int>::type compare(V v)const - { - gmp_float d; - d = v; - return compare(d); - } - mpf_t& data() BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - return m_data; - } - const mpf_t& data()const BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - return m_data; - } + result = ps; + (*free_func_ptr)((void *)ps, std::strlen(ps) + 1); + } + boost::multiprecision::detail::format_float_string(result, e, org_digits, f, + mpf_sgn(m_data) == 0); + return result; + } + ~gmp_float_imp() BOOST_NOEXCEPT { + if (m_data[0]._mp_d) + mpf_clear(m_data); + } + void negate() BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + mpf_neg(m_data, m_data); + } + int compare(const gmp_float &o) const BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); + return mpf_cmp(m_data, o.m_data); + } + int compare(long i) const BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + return mpf_cmp_si(m_data, i); + } + int compare(unsigned long i) const BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + return mpf_cmp_ui(m_data, i); + } + template + typename enable_if, int>::type compare(V v) const { + gmp_float d; + d = v; + return compare(d); + } + mpf_t &data() BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + return m_data; + } + const mpf_t &data() const BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + return m_data; + } + protected: - mpf_t m_data; - static unsigned& get_default_precision() BOOST_NOEXCEPT - { - static unsigned val = 50; - return val; - } + mpf_t m_data; + static unsigned &get_default_precision() BOOST_NOEXCEPT { + static unsigned val = 50; + return val; + } }; } // namespace detail @@ -429,561 +404,517 @@ struct gmp_int; struct gmp_rational; template -struct gmp_float : public detail::gmp_float_imp -{ - gmp_float() - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - } - gmp_float(const gmp_float& o) : detail::gmp_float_imp(o) {} - template - gmp_float(const gmp_float& o, typename enable_if_c::type* = 0); - template - explicit gmp_float(const gmp_float& o, typename disable_if_c::type* = 0); - gmp_float(const gmp_int& o); - gmp_float(const gmp_rational& o); - gmp_float(const mpf_t val) - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - mpf_set(this->m_data, val); - } - gmp_float(const mpz_t val) - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - mpf_set_z(this->m_data, val); - } - gmp_float(const mpq_t val) - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - mpf_set_q(this->m_data, val); - } +struct gmp_float : public detail::gmp_float_imp { + gmp_float() { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + } + gmp_float(const gmp_float &o) : detail::gmp_float_imp(o) {} + template + gmp_float(const gmp_float &o, + typename enable_if_c::type * = 0); + template + explicit gmp_float(const gmp_float &o, + typename disable_if_c::type * = 0); + gmp_float(const gmp_int &o); + gmp_float(const gmp_rational &o); + gmp_float(const mpf_t val) { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set(this->m_data, val); + } + gmp_float(const mpz_t val) { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set_z(this->m_data, val); + } + gmp_float(const mpq_t val) { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set_q(this->m_data, val); + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp(static_cast&&>(o)) {} + gmp_float(gmp_float &&o) BOOST_NOEXCEPT + : detail::gmp_float_imp( + static_cast &&>(o)) {} #endif - gmp_float& operator=(const gmp_float& o) - { - *static_cast*>(this) = static_cast const&>(o); - return *this; - } + gmp_float &operator=(const gmp_float &o) { + *static_cast *>(this) = + static_cast const &>(o); + return *this; + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT - { - *static_cast*>(this) = static_cast&&>(o); - return *this; - } + gmp_float &operator=(gmp_float &&o) BOOST_NOEXCEPT { + *static_cast *>(this) = + static_cast &&>(o); + return *this; + } #endif - template - gmp_float& operator=(const gmp_float& o); - gmp_float& operator=(const gmp_int& o); - gmp_float& operator=(const gmp_rational& o); - gmp_float& operator=(const mpf_t val) - { - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - mpf_set(this->m_data, val); - return *this; - } - gmp_float& operator=(const mpz_t val) - { - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - mpf_set_z(this->m_data, val); - return *this; - } - gmp_float& operator=(const mpq_t val) - { - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - mpf_set_q(this->m_data, val); - return *this; - } - template - gmp_float& operator=(const V& v) - { - *static_cast*>(this) = v; - return *this; - } + template gmp_float &operator=(const gmp_float &o); + gmp_float &operator=(const gmp_int &o); + gmp_float &operator=(const gmp_rational &o); + gmp_float &operator=(const mpf_t val) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set(this->m_data, val); + return *this; + } + gmp_float &operator=(const mpz_t val) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set_z(this->m_data, val); + return *this; + } + gmp_float &operator=(const mpq_t val) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set_q(this->m_data, val); + return *this; + } + template gmp_float &operator=(const V &v) { + *static_cast *>(this) = v; + return *this; + } }; -template <> -struct gmp_float<0> : public detail::gmp_float_imp<0> -{ - gmp_float() - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); - } - gmp_float(const mpf_t val) - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); - mpf_set(this->m_data, val); - } - gmp_float(const mpz_t val) - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); - mpf_set_z(this->m_data, val); - } - gmp_float(const mpq_t val) - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); - mpf_set_q(this->m_data, val); - } - gmp_float(const gmp_float& o) : detail::gmp_float_imp<0>(o) {} - template - gmp_float(const gmp_float& o) - { - mpf_init2(this->m_data, mpf_get_prec(o.data())); - mpf_set(this->m_data, o.data()); - } +template <> struct gmp_float<0> : public detail::gmp_float_imp<0> { + gmp_float() { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2(get_default_precision())); + } + gmp_float(const mpf_t val) { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set(this->m_data, val); + } + gmp_float(const mpz_t val) { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_z(this->m_data, val); + } + gmp_float(const mpq_t val) { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_q(this->m_data, val); + } + gmp_float(const gmp_float &o) : detail::gmp_float_imp<0>(o) {} + template gmp_float(const gmp_float &o) { + mpf_init2(this->m_data, mpf_get_prec(o.data())); + mpf_set(this->m_data, o.data()); + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp<0>(static_cast&&>(o)) {} + gmp_float(gmp_float &&o) BOOST_NOEXCEPT + : detail::gmp_float_imp<0>(static_cast &&>(o)) {} #endif - gmp_float(const gmp_int& o); - gmp_float(const gmp_rational& o); - gmp_float(const gmp_float& o, unsigned digits10) - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - mpf_set(this->m_data, o.data()); - } - template - gmp_float(const V& o, unsigned digits10) - { - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - *this = o; - } + gmp_float(const gmp_int &o); + gmp_float(const gmp_rational &o); + gmp_float(const gmp_float &o, unsigned digits10) { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set(this->m_data, o.data()); + } + template gmp_float(const V &o, unsigned digits10) { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + *this = o; + } #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW - // - // Support for new types in C++17 - // - template - gmp_float(const std::basic_string_view& o, unsigned digits10) - { - using default_ops::assign_from_string_view; - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - assign_from_string_view(*this, o); - } + // + // Support for new types in C++17 + // + template + gmp_float(const std::basic_string_view &o, unsigned digits10) { + using default_ops::assign_from_string_view; + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + assign_from_string_view(*this, o); + } #endif - gmp_float& operator=(const gmp_float& o) - { - *static_cast*>(this) = static_cast const&>(o); - return *this; - } + gmp_float &operator=(const gmp_float &o) { + *static_cast *>(this) = + static_cast const &>(o); + return *this; + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT - { - *static_cast*>(this) = static_cast &&>(o); - return *this; - } + gmp_float &operator=(gmp_float &&o) BOOST_NOEXCEPT { + *static_cast *>(this) = + static_cast &&>(o); + return *this; + } #endif - template - gmp_float& operator=(const gmp_float& o) - { - if(this->m_data[0]._mp_d == 0) - { - mpf_init2(this->m_data, mpf_get_prec(o.data())); - } - else - { - mpf_set_prec(this->m_data, mpf_get_prec(o.data())); - } - mpf_set(this->m_data, o.data()); - return *this; - } - gmp_float& operator=(const gmp_int& o); - gmp_float& operator=(const gmp_rational& o); - gmp_float& operator=(const mpf_t val) - { - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); - mpf_set(this->m_data, val); - return *this; - } - gmp_float& operator=(const mpz_t val) - { - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); - mpf_set_z(this->m_data, val); - return *this; - } - gmp_float& operator=(const mpq_t val) - { - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); - mpf_set_q(this->m_data, val); - return *this; - } - template - gmp_float& operator=(const V& v) - { - *static_cast*>(this) = v; - return *this; - } - static unsigned default_precision() BOOST_NOEXCEPT - { - return get_default_precision(); - } - static void default_precision(unsigned v) BOOST_NOEXCEPT - { - get_default_precision() = v; - } - unsigned precision()const BOOST_NOEXCEPT - { - return static_cast(multiprecision::detail::digits2_2_10(static_cast(mpf_get_prec(this->m_data)))); - } - void precision(unsigned digits10) BOOST_NOEXCEPT - { - mpf_set_prec(this->m_data, multiprecision::detail::digits10_2_2(digits10)); - } + template gmp_float &operator=(const gmp_float &o) { + if (this->m_data[0]._mp_d == 0) { + mpf_init2(this->m_data, mpf_get_prec(o.data())); + } else { + mpf_set_prec(this->m_data, mpf_get_prec(o.data())); + } + mpf_set(this->m_data, o.data()); + return *this; + } + gmp_float &operator=(const gmp_int &o); + gmp_float &operator=(const gmp_rational &o); + gmp_float &operator=(const mpf_t val) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set(this->m_data, val); + return *this; + } + gmp_float &operator=(const mpz_t val) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_z(this->m_data, val); + return *this; + } + gmp_float &operator=(const mpq_t val) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_q(this->m_data, val); + return *this; + } + template gmp_float &operator=(const V &v) { + *static_cast *>(this) = v; + return *this; + } + static unsigned default_precision() BOOST_NOEXCEPT { + return get_default_precision(); + } + static void default_precision(unsigned v) BOOST_NOEXCEPT { + get_default_precision() = v; + } + unsigned precision() const BOOST_NOEXCEPT { + return static_cast(multiprecision::detail::digits2_2_10( + static_cast(mpf_get_prec(this->m_data)))); + } + void precision(unsigned digits10) BOOST_NOEXCEPT { + mpf_set_prec(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + } }; template -inline typename enable_if_c::value, bool>::type eval_eq(const gmp_float& a, const T& b) BOOST_NOEXCEPT -{ - return a.compare(b) == 0; +inline typename enable_if_c::value, bool>::type +eval_eq(const gmp_float &a, const T &b) BOOST_NOEXCEPT { + return a.compare(b) == 0; } template -inline typename enable_if_c::value, bool>::type eval_lt(const gmp_float& a, const T& b) BOOST_NOEXCEPT -{ - return a.compare(b) < 0; +inline typename enable_if_c::value, bool>::type +eval_lt(const gmp_float &a, const T &b) BOOST_NOEXCEPT { + return a.compare(b) < 0; } template -inline typename enable_if_c::value, bool>::type eval_gt(const gmp_float& a, const T& b) BOOST_NOEXCEPT -{ - return a.compare(b) > 0; +inline typename enable_if_c::value, bool>::type +eval_gt(const gmp_float &a, const T &b) BOOST_NOEXCEPT { + return a.compare(b) > 0; } template -inline void eval_add(gmp_float& result, const gmp_float& o) -{ - mpf_add(result.data(), result.data(), o.data()); +inline void eval_add(gmp_float &result, const gmp_float &o) { + mpf_add(result.data(), result.data(), o.data()); } template -inline void eval_subtract(gmp_float& result, const gmp_float& o) -{ - mpf_sub(result.data(), result.data(), o.data()); +inline void eval_subtract(gmp_float &result, const gmp_float &o) { + mpf_sub(result.data(), result.data(), o.data()); } template -inline void eval_multiply(gmp_float& result, const gmp_float& o) -{ - mpf_mul(result.data(), result.data(), o.data()); +inline void eval_multiply(gmp_float &result, const gmp_float &o) { + mpf_mul(result.data(), result.data(), o.data()); } template -inline bool eval_is_zero(const gmp_float& val) BOOST_NOEXCEPT -{ - return mpf_sgn(val.data()) == 0; +inline bool eval_is_zero(const gmp_float &val) BOOST_NOEXCEPT { + return mpf_sgn(val.data()) == 0; } template -inline void eval_divide(gmp_float& result, const gmp_float& o) -{ - if(eval_is_zero(o)) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpf_div(result.data(), result.data(), o.data()); +inline void eval_divide(gmp_float &result, const gmp_float &o) { + if (eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div(result.data(), result.data(), o.data()); } template -inline void eval_add(gmp_float& result, unsigned long i) -{ - mpf_add_ui(result.data(), result.data(), i); +inline void eval_add(gmp_float &result, unsigned long i) { + mpf_add_ui(result.data(), result.data(), i); } template -inline void eval_subtract(gmp_float& result, unsigned long i) -{ - mpf_sub_ui(result.data(), result.data(), i); +inline void eval_subtract(gmp_float &result, unsigned long i) { + mpf_sub_ui(result.data(), result.data(), i); } template -inline void eval_multiply(gmp_float& result, unsigned long i) -{ - mpf_mul_ui(result.data(), result.data(), i); +inline void eval_multiply(gmp_float &result, unsigned long i) { + mpf_mul_ui(result.data(), result.data(), i); } template -inline void eval_divide(gmp_float& result, unsigned long i) -{ - if(i == 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpf_div_ui(result.data(), result.data(), i); +inline void eval_divide(gmp_float &result, unsigned long i) { + if (i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div_ui(result.data(), result.data(), i); } template -inline void eval_add(gmp_float& result, long i) -{ - if(i > 0) - mpf_add_ui(result.data(), result.data(), i); - else - mpf_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); +inline void eval_add(gmp_float &result, long i) { + if (i > 0) + mpf_add_ui(result.data(), result.data(), i); + else + mpf_sub_ui(result.data(), result.data(), + boost::multiprecision::detail::unsigned_abs(i)); } template -inline void eval_subtract(gmp_float& result, long i) -{ - if(i > 0) - mpf_sub_ui(result.data(), result.data(), i); - else - mpf_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); +inline void eval_subtract(gmp_float &result, long i) { + if (i > 0) + mpf_sub_ui(result.data(), result.data(), i); + else + mpf_add_ui(result.data(), result.data(), + boost::multiprecision::detail::unsigned_abs(i)); } template -inline void eval_multiply(gmp_float& result, long i) -{ - mpf_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); - if(i < 0) - mpf_neg(result.data(), result.data()); +inline void eval_multiply(gmp_float &result, long i) { + mpf_mul_ui(result.data(), result.data(), + boost::multiprecision::detail::unsigned_abs(i)); + if (i < 0) + mpf_neg(result.data(), result.data()); } template -inline void eval_divide(gmp_float& result, long i) -{ - if(i == 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpf_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); - if(i < 0) - mpf_neg(result.data(), result.data()); +inline void eval_divide(gmp_float &result, long i) { + if (i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div_ui(result.data(), result.data(), + boost::multiprecision::detail::unsigned_abs(i)); + if (i < 0) + mpf_neg(result.data(), result.data()); } // // Specialised 3 arg versions of the basic operators: // template -inline void eval_add(gmp_float& a, const gmp_float& x, const gmp_float& y) -{ - mpf_add(a.data(), x.data(), y.data()); +inline void eval_add(gmp_float &a, const gmp_float &x, + const gmp_float &y) { + mpf_add(a.data(), x.data(), y.data()); } template -inline void eval_add(gmp_float& a, const gmp_float& x, unsigned long y) -{ - mpf_add_ui(a.data(), x.data(), y); +inline void eval_add(gmp_float &a, const gmp_float &x, + unsigned long y) { + mpf_add_ui(a.data(), x.data(), y); } template -inline void eval_add(gmp_float& a, const gmp_float& x, long y) -{ - if(y < 0) - mpf_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); - else - mpf_add_ui(a.data(), x.data(), y); +inline void eval_add(gmp_float &a, const gmp_float &x, long y) { + if (y < 0) + mpf_sub_ui(a.data(), x.data(), + boost::multiprecision::detail::unsigned_abs(y)); + else + mpf_add_ui(a.data(), x.data(), y); } template -inline void eval_add(gmp_float& a, unsigned long x, const gmp_float& y) -{ - mpf_add_ui(a.data(), y.data(), x); +inline void eval_add(gmp_float &a, unsigned long x, + const gmp_float &y) { + mpf_add_ui(a.data(), y.data(), x); } template -inline void eval_add(gmp_float& a, long x, const gmp_float& y) -{ - if(x < 0) - { - mpf_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data()); - mpf_neg(a.data(), a.data()); - } - else - mpf_add_ui(a.data(), y.data(), x); +inline void eval_add(gmp_float &a, long x, const gmp_float &y) { + if (x < 0) { + mpf_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), + y.data()); + mpf_neg(a.data(), a.data()); + } else + mpf_add_ui(a.data(), y.data(), x); } template -inline void eval_subtract(gmp_float& a, const gmp_float& x, const gmp_float& y) -{ - mpf_sub(a.data(), x.data(), y.data()); +inline void eval_subtract(gmp_float &a, const gmp_float &x, + const gmp_float &y) { + mpf_sub(a.data(), x.data(), y.data()); } template -inline void eval_subtract(gmp_float& a, const gmp_float& x, unsigned long y) -{ - mpf_sub_ui(a.data(), x.data(), y); +inline void eval_subtract(gmp_float &a, const gmp_float &x, + unsigned long y) { + mpf_sub_ui(a.data(), x.data(), y); } template -inline void eval_subtract(gmp_float& a, const gmp_float& x, long y) -{ - if(y < 0) - mpf_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); - else - mpf_sub_ui(a.data(), x.data(), y); +inline void eval_subtract(gmp_float &a, const gmp_float &x, long y) { + if (y < 0) + mpf_add_ui(a.data(), x.data(), + boost::multiprecision::detail::unsigned_abs(y)); + else + mpf_sub_ui(a.data(), x.data(), y); } template -inline void eval_subtract(gmp_float& a, unsigned long x, const gmp_float& y) -{ - mpf_ui_sub(a.data(), x, y.data()); +inline void eval_subtract(gmp_float &a, unsigned long x, + const gmp_float &y) { + mpf_ui_sub(a.data(), x, y.data()); } template -inline void eval_subtract(gmp_float& a, long x, const gmp_float& y) -{ - if(x < 0) - { - mpf_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x)); - mpf_neg(a.data(), a.data()); - } - else - mpf_ui_sub(a.data(), x, y.data()); +inline void eval_subtract(gmp_float &a, long x, const gmp_float &y) { + if (x < 0) { + mpf_add_ui(a.data(), y.data(), + boost::multiprecision::detail::unsigned_abs(x)); + mpf_neg(a.data(), a.data()); + } else + mpf_ui_sub(a.data(), x, y.data()); } template -inline void eval_multiply(gmp_float& a, const gmp_float& x, const gmp_float& y) -{ - mpf_mul(a.data(), x.data(), y.data()); +inline void eval_multiply(gmp_float &a, const gmp_float &x, + const gmp_float &y) { + mpf_mul(a.data(), x.data(), y.data()); } template -inline void eval_multiply(gmp_float& a, const gmp_float& x, unsigned long y) -{ - mpf_mul_ui(a.data(), x.data(), y); +inline void eval_multiply(gmp_float &a, const gmp_float &x, + unsigned long y) { + mpf_mul_ui(a.data(), x.data(), y); } template -inline void eval_multiply(gmp_float& a, const gmp_float& x, long y) -{ - if(y < 0) - { - mpf_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); - a.negate(); - } - else - mpf_mul_ui(a.data(), x.data(), y); +inline void eval_multiply(gmp_float &a, const gmp_float &x, long y) { + if (y < 0) { + mpf_mul_ui(a.data(), x.data(), + boost::multiprecision::detail::unsigned_abs(y)); + a.negate(); + } else + mpf_mul_ui(a.data(), x.data(), y); } template -inline void eval_multiply(gmp_float& a, unsigned long x, const gmp_float& y) -{ - mpf_mul_ui(a.data(), y.data(), x); +inline void eval_multiply(gmp_float &a, unsigned long x, + const gmp_float &y) { + mpf_mul_ui(a.data(), y.data(), x); } template -inline void eval_multiply(gmp_float& a, long x, const gmp_float& y) -{ - if(x < 0) - { - mpf_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x)); - mpf_neg(a.data(), a.data()); - } - else - mpf_mul_ui(a.data(), y.data(), x); +inline void eval_multiply(gmp_float &a, long x, const gmp_float &y) { + if (x < 0) { + mpf_mul_ui(a.data(), y.data(), + boost::multiprecision::detail::unsigned_abs(x)); + mpf_neg(a.data(), a.data()); + } else + mpf_mul_ui(a.data(), y.data(), x); } template -inline void eval_divide(gmp_float& a, const gmp_float& x, const gmp_float& y) -{ - if(eval_is_zero(y)) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpf_div(a.data(), x.data(), y.data()); +inline void eval_divide(gmp_float &a, const gmp_float &x, + const gmp_float &y) { + if (eval_is_zero(y)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div(a.data(), x.data(), y.data()); } template -inline void eval_divide(gmp_float& a, const gmp_float& x, unsigned long y) -{ - if(y == 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpf_div_ui(a.data(), x.data(), y); +inline void eval_divide(gmp_float &a, const gmp_float &x, + unsigned long y) { + if (y == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div_ui(a.data(), x.data(), y); } template -inline void eval_divide(gmp_float& a, const gmp_float& x, long y) -{ - if(y == 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - if(y < 0) - { - mpf_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); - a.negate(); - } - else - mpf_div_ui(a.data(), x.data(), y); +inline void eval_divide(gmp_float &a, const gmp_float &x, long y) { + if (y == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + if (y < 0) { + mpf_div_ui(a.data(), x.data(), + boost::multiprecision::detail::unsigned_abs(y)); + a.negate(); + } else + mpf_div_ui(a.data(), x.data(), y); } template -inline void eval_divide(gmp_float& a, unsigned long x, const gmp_float& y) -{ - if(eval_is_zero(y)) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpf_ui_div(a.data(), x, y.data()); +inline void eval_divide(gmp_float &a, unsigned long x, + const gmp_float &y) { + if (eval_is_zero(y)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_ui_div(a.data(), x, y.data()); } template -inline void eval_divide(gmp_float& a, long x, const gmp_float& y) -{ - if(eval_is_zero(y)) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - if(x < 0) - { - mpf_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data()); - mpf_neg(a.data(), a.data()); - } - else - mpf_ui_div(a.data(), x, y.data()); +inline void eval_divide(gmp_float &a, long x, const gmp_float &y) { + if (eval_is_zero(y)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + if (x < 0) { + mpf_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), + y.data()); + mpf_neg(a.data(), a.data()); + } else + mpf_ui_div(a.data(), x, y.data()); } template -inline int eval_get_sign(const gmp_float& val) BOOST_NOEXCEPT -{ - return mpf_sgn(val.data()); +inline int eval_get_sign(const gmp_float &val) BOOST_NOEXCEPT { + return mpf_sgn(val.data()); } template -inline void eval_convert_to(unsigned long* result, const gmp_float& val) BOOST_NOEXCEPT -{ - if(0 == mpf_fits_ulong_p(val.data())) - *result = (std::numeric_limits::max)(); - else - *result = (unsigned long)mpf_get_ui(val.data()); +inline void eval_convert_to(unsigned long *result, + const gmp_float &val) BOOST_NOEXCEPT { + if (0 == mpf_fits_ulong_p(val.data())) + *result = (std::numeric_limits::max)(); + else + *result = (unsigned long)mpf_get_ui(val.data()); } template -inline void eval_convert_to(long* result, const gmp_float& val) BOOST_NOEXCEPT -{ - if(0 == mpf_fits_slong_p(val.data())) - { - *result = (std::numeric_limits::max)(); - *result *= mpf_sgn(val.data()); - } - else - *result = (long)mpf_get_si(val.data()); +inline void eval_convert_to(long *result, + const gmp_float &val) BOOST_NOEXCEPT { + if (0 == mpf_fits_slong_p(val.data())) { + *result = (std::numeric_limits::max)(); + *result *= mpf_sgn(val.data()); + } else + *result = (long)mpf_get_si(val.data()); } template -inline void eval_convert_to(double* result, const gmp_float& val) BOOST_NOEXCEPT -{ - *result = mpf_get_d(val.data()); +inline void eval_convert_to(double *result, + const gmp_float &val) BOOST_NOEXCEPT { + *result = mpf_get_d(val.data()); } #ifdef BOOST_HAS_LONG_LONG template -inline void eval_convert_to(boost::long_long_type* result, const gmp_float& val) -{ - gmp_float t(val); - if(eval_get_sign(t) < 0) - t.negate(); - - long digits = std::numeric_limits::digits - std::numeric_limits::digits; - - if(digits > 0) - mpf_div_2exp(t.data(), t.data(), digits); - - if(!mpf_fits_slong_p(t.data())) - { - if(eval_get_sign(val) < 0) - *result = (std::numeric_limits::min)(); - else - *result = (std::numeric_limits::max)(); - return; - }; - - *result = mpf_get_si(t.data()); - while(digits > 0) - { - *result <<= digits; - digits -= std::numeric_limits::digits; - mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits::digits : std::numeric_limits::digits + digits); - unsigned long l = (unsigned long)mpf_get_ui(t.data()); - if(digits < 0) - l >>= -digits; - *result |= l; - } - if(eval_get_sign(val) < 0) - *result = -*result; +inline void eval_convert_to(boost::long_long_type *result, + const gmp_float &val) { + gmp_float t(val); + if (eval_get_sign(t) < 0) + t.negate(); + + long digits = std::numeric_limits::digits - + std::numeric_limits::digits; + + if (digits > 0) + mpf_div_2exp(t.data(), t.data(), digits); + + if (!mpf_fits_slong_p(t.data())) { + if (eval_get_sign(val) < 0) + *result = (std::numeric_limits::min)(); + else + *result = (std::numeric_limits::max)(); + return; + }; + + *result = mpf_get_si(t.data()); + while (digits > 0) { + *result <<= digits; + digits -= std::numeric_limits::digits; + mpf_mul_2exp(t.data(), t.data(), + digits >= 0 + ? std::numeric_limits::digits + : std::numeric_limits::digits + digits); + unsigned long l = (unsigned long)mpf_get_ui(t.data()); + if (digits < 0) + l >>= -digits; + *result |= l; + } + if (eval_get_sign(val) < 0) + *result = -*result; } template -inline void eval_convert_to(boost::ulong_long_type* result, const gmp_float& val) -{ - gmp_float t(val); - - long digits = std::numeric_limits::digits - std::numeric_limits::digits; - - if(digits > 0) - mpf_div_2exp(t.data(), t.data(), digits); - - if(!mpf_fits_ulong_p(t.data())) - { - *result = (std::numeric_limits::max)(); - return; - } - - *result = mpf_get_ui(t.data()); - while(digits > 0) - { - *result <<= digits; - digits -= std::numeric_limits::digits; - mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits::digits : std::numeric_limits::digits + digits); - unsigned long l = (unsigned long)mpf_get_ui(t.data()); - if(digits < 0) - l >>= -digits; - *result |= l; - } +inline void eval_convert_to(boost::ulong_long_type *result, + const gmp_float &val) { + gmp_float t(val); + + long digits = std::numeric_limits::digits - + std::numeric_limits::digits; + + if (digits > 0) + mpf_div_2exp(t.data(), t.data(), digits); + + if (!mpf_fits_ulong_p(t.data())) { + *result = (std::numeric_limits::max)(); + return; + } + + *result = mpf_get_ui(t.data()); + while (digits > 0) { + *result <<= digits; + digits -= std::numeric_limits::digits; + mpf_mul_2exp(t.data(), t.data(), + digits >= 0 + ? std::numeric_limits::digits + : std::numeric_limits::digits + digits); + unsigned long l = (unsigned long)mpf_get_ui(t.data()); + if (digits < 0) + l >>= -digits; + *result |= l; + } } #endif @@ -991,1220 +922,1081 @@ inline void eval_convert_to(boost::ulong_long_type* result, const gmp_float -inline void eval_sqrt(gmp_float& result, const gmp_float& val) -{ - mpf_sqrt(result.data(), val.data()); +inline void eval_sqrt(gmp_float &result, + const gmp_float &val) { + mpf_sqrt(result.data(), val.data()); } template -inline void eval_abs(gmp_float& result, const gmp_float& val) -{ - mpf_abs(result.data(), val.data()); +inline void eval_abs(gmp_float &result, + const gmp_float &val) { + mpf_abs(result.data(), val.data()); } template -inline void eval_fabs(gmp_float& result, const gmp_float& val) -{ - mpf_abs(result.data(), val.data()); +inline void eval_fabs(gmp_float &result, + const gmp_float &val) { + mpf_abs(result.data(), val.data()); } template -inline void eval_ceil(gmp_float& result, const gmp_float& val) -{ - mpf_ceil(result.data(), val.data()); +inline void eval_ceil(gmp_float &result, + const gmp_float &val) { + mpf_ceil(result.data(), val.data()); } template -inline void eval_floor(gmp_float& result, const gmp_float& val) -{ - mpf_floor(result.data(), val.data()); +inline void eval_floor(gmp_float &result, + const gmp_float &val) { + mpf_floor(result.data(), val.data()); } template -inline void eval_trunc(gmp_float& result, const gmp_float& val) -{ - mpf_trunc(result.data(), val.data()); +inline void eval_trunc(gmp_float &result, + const gmp_float &val) { + mpf_trunc(result.data(), val.data()); } template -inline void eval_ldexp(gmp_float& result, const gmp_float& val, long e) -{ - if(e > 0) - mpf_mul_2exp(result.data(), val.data(), e); - else if(e < 0) - mpf_div_2exp(result.data(), val.data(), -e); - else - result = val; +inline void eval_ldexp(gmp_float &result, + const gmp_float &val, long e) { + if (e > 0) + mpf_mul_2exp(result.data(), val.data(), e); + else if (e < 0) + mpf_div_2exp(result.data(), val.data(), -e); + else + result = val; } template -inline void eval_frexp(gmp_float& result, const gmp_float& val, int* e) -{ +inline void eval_frexp(gmp_float &result, + const gmp_float &val, int *e) { #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000) - mpir_si v; - mpf_get_d_2exp(&v, val.data()); + mpir_si v; + mpf_get_d_2exp(&v, val.data()); #else - long v; - mpf_get_d_2exp(&v, val.data()); + long v; + mpf_get_d_2exp(&v, val.data()); #endif - *e = v; - eval_ldexp(result, val, -v); + *e = v; + eval_ldexp(result, val, -v); } template -inline void eval_frexp(gmp_float& result, const gmp_float& val, long* e) -{ +inline void eval_frexp(gmp_float &result, + const gmp_float &val, long *e) { #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000) - mpir_si v; - mpf_get_d_2exp(&v, val.data()); - *e = v; - eval_ldexp(result, val, -v); + mpir_si v; + mpf_get_d_2exp(&v, val.data()); + *e = v; + eval_ldexp(result, val, -v); #else - mpf_get_d_2exp(e, val.data()); - eval_ldexp(result, val, -*e); + mpf_get_d_2exp(e, val.data()); + eval_ldexp(result, val, -*e); #endif } template -inline std::size_t hash_value(const gmp_float& val) -{ - std::size_t result = 0; - for(int i = 0; i < std::abs(val.data()[0]._mp_size); ++i) - boost::hash_combine(result, val.data()[0]._mp_d[i]); - boost::hash_combine(result, val.data()[0]._mp_exp); - boost::hash_combine(result, val.data()[0]._mp_size); - return result; +inline std::size_t hash_value(const gmp_float &val) { + std::size_t result = 0; + for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i) + boost::hash_combine(result, val.data()[0]._mp_d[i]); + boost::hash_combine(result, val.data()[0]._mp_exp); + boost::hash_combine(result, val.data()[0]._mp_size); + return result; } -struct gmp_int -{ +struct gmp_int { #ifdef BOOST_HAS_LONG_LONG - typedef mpl::list signed_types; - typedef mpl::list unsigned_types; + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; #else - typedef mpl::list signed_types; - typedef mpl::list unsigned_types; + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; #endif - typedef mpl::list float_types; + typedef mpl::list float_types; - gmp_int() - { + gmp_int() { mpz_init(this->m_data); } + gmp_int(const gmp_int &o) { + if (o.m_data[0]._mp_d) + mpz_init_set(m_data, o.m_data); + else mpz_init(this->m_data); - } - gmp_int(const gmp_int& o) - { - if(o.m_data[0]._mp_d) - mpz_init_set(m_data, o.m_data); - else - mpz_init(this->m_data); - } + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_int(gmp_int&& o) BOOST_NOEXCEPT - { - m_data[0] = o.m_data[0]; - o.m_data[0]._mp_d = 0; - } + gmp_int(gmp_int &&o) BOOST_NOEXCEPT { + m_data[0] = o.m_data[0]; + o.m_data[0]._mp_d = 0; + } #endif - explicit gmp_int(const mpf_t val) - { - mpz_init(this->m_data); - mpz_set_f(this->m_data, val); - } - gmp_int(const mpz_t val) - { - mpz_init_set(this->m_data, val); - } - explicit gmp_int(const mpq_t val) - { - mpz_init(this->m_data); - mpz_set_q(this->m_data, val); - } - template - explicit gmp_int(const gmp_float& o) - { + explicit gmp_int(const mpf_t val) { + mpz_init(this->m_data); + mpz_set_f(this->m_data, val); + } + gmp_int(const mpz_t val) { mpz_init_set(this->m_data, val); } + explicit gmp_int(const mpq_t val) { + mpz_init(this->m_data); + mpz_set_q(this->m_data, val); + } + template explicit gmp_int(const gmp_float &o) { + mpz_init(this->m_data); + mpz_set_f(this->m_data, o.data()); + } + explicit gmp_int(const gmp_rational &o); + gmp_int &operator=(const gmp_int &o) { + if (m_data[0]._mp_d == 0) mpz_init(this->m_data); - mpz_set_f(this->m_data, o.data()); - } - explicit gmp_int(const gmp_rational& o); - gmp_int& operator = (const gmp_int& o) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - mpz_set(m_data, o.m_data); - return *this; - } + mpz_set(m_data, o.m_data); + return *this; + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_int& operator = (gmp_int&& o) BOOST_NOEXCEPT - { - mpz_swap(m_data, o.m_data); - return *this; - } + gmp_int &operator=(gmp_int &&o) BOOST_NOEXCEPT { + mpz_swap(m_data, o.m_data); + return *this; + } #endif #ifdef BOOST_HAS_LONG_LONG #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) - gmp_int& operator = (boost::ulong_long_type i) - { - *this = static_cast(i); - return *this; - } + gmp_int &operator=(boost::ulong_long_type i) { + *this = static_cast(i); + return *this; + } #else - gmp_int& operator = (boost::ulong_long_type i) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - boost::ulong_long_type mask = ((((1uLL << (std::numeric_limits::digits - 1)) - 1) << 1) | 1uLL); - unsigned shift = 0; - mpz_t t; - mpz_set_ui(m_data, 0); - mpz_init_set_ui(t, 0); - while(i) - { - mpz_set_ui(t, static_cast(i & mask)); - if(shift) - mpz_mul_2exp(t, t, shift); - mpz_add(m_data, m_data, t); - shift += std::numeric_limits::digits; - i >>= std::numeric_limits::digits; - } - mpz_clear(t); - return *this; - } + gmp_int &operator=(boost::ulong_long_type i) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + boost::ulong_long_type mask = + ((((1uLL << (std::numeric_limits::digits - 1)) - 1) + << 1) | + 1uLL); + unsigned shift = 0; + mpz_t t; + mpz_set_ui(m_data, 0); + mpz_init_set_ui(t, 0); + while (i) { + mpz_set_ui(t, static_cast(i & mask)); + if (shift) + mpz_mul_2exp(t, t, shift); + mpz_add(m_data, m_data, t); + shift += std::numeric_limits::digits; + i >>= std::numeric_limits::digits; + } + mpz_clear(t); + return *this; + } #endif - gmp_int& operator = (boost::long_long_type i) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - bool neg = i < 0; - *this = boost::multiprecision::detail::unsigned_abs(i); - if(neg) - mpz_neg(m_data, m_data); - return *this; - } + gmp_int &operator=(boost::long_long_type i) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + bool neg = i < 0; + *this = boost::multiprecision::detail::unsigned_abs(i); + if (neg) + mpz_neg(m_data, m_data); + return *this; + } #endif - gmp_int& operator = (unsigned long i) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - mpz_set_ui(m_data, i); - return *this; - } - gmp_int& operator = (long i) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - mpz_set_si(m_data, i); + gmp_int &operator=(unsigned long i) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_ui(m_data, i); + return *this; + } + gmp_int &operator=(long i) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_si(m_data, i); + return *this; + } + gmp_int &operator=(double d) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_d(m_data, d); + return *this; + } + gmp_int &operator=(long double a) { + using std::floor; + using std::frexp; + using std::ldexp; + + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + + if (a == 0) { + mpz_set_si(m_data, 0); return *this; - } - gmp_int& operator = (double d) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - mpz_set_d(m_data, d); + } + + if (a == 1) { + mpz_set_si(m_data, 1); return *this; - } - gmp_int& operator = (long double a) - { - using std::frexp; - using std::ldexp; - using std::floor; - - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - - if (a == 0) { - mpz_set_si(m_data, 0); - return *this; - } + } - if (a == 1) { - mpz_set_si(m_data, 1); - return *this; - } + BOOST_ASSERT(!(boost::math::isinf)(a)); + BOOST_ASSERT(!(boost::math::isnan)(a)); - BOOST_ASSERT(!(boost::math::isinf)(a)); - BOOST_ASSERT(!(boost::math::isnan)(a)); - - int e; - long double f, term; - mpz_set_ui(m_data, 0u); - - f = frexp(a, &e); - - static const int shift = std::numeric_limits::digits - 1; - - while(f) - { - // extract int sized bits from f: - f = ldexp(f, shift); - term = floor(f); - e -= shift; - mpz_mul_2exp(m_data, m_data, shift); - if(term > 0) - mpz_add_ui(m_data, m_data, static_cast(term)); - else - mpz_sub_ui(m_data, m_data, static_cast(-term)); - f -= term; - } - if(e > 0) - mpz_mul_2exp(m_data, m_data, e); - else if(e < 0) - mpz_div_2exp(m_data, m_data, -e); - return *this; - } - gmp_int& operator = (const char* s) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - std::size_t n = s ? std::strlen(s) : 0; - int radix = 10; - if(n && (*s == '0')) - { - if((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) - { - radix = 16; - s +=2; - n -= 2; - } - else - { - radix = 8; - n -= 1; - } - } - if(n) - { - if(0 != mpz_set_str(m_data, s, radix)) - BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid integer."))); - } + int e; + long double f, term; + mpz_set_ui(m_data, 0u); + + f = frexp(a, &e); + + static const int shift = std::numeric_limits::digits - 1; + + while (f) { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + mpz_mul_2exp(m_data, m_data, shift); + if (term > 0) + mpz_add_ui(m_data, m_data, static_cast(term)); else - mpz_set_ui(m_data, 0); - return *this; - } - gmp_int& operator=(const mpf_t val) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - mpz_set_f(this->m_data, val); - return *this; - } - gmp_int& operator=(const mpz_t val) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - mpz_set(this->m_data, val); - return *this; - } - gmp_int& operator=(const mpq_t val) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - mpz_set_q(this->m_data, val); - return *this; - } - template - gmp_int& operator=(const gmp_float& o) - { - if(m_data[0]._mp_d == 0) - mpz_init(this->m_data); - mpz_set_f(this->m_data, o.data()); - return *this; - } - gmp_int& operator=(const gmp_rational& o); - void swap(gmp_int& o) - { - mpz_swap(m_data, o.m_data); - } - std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f)const - { - BOOST_ASSERT(m_data[0]._mp_d); - - int base = 10; - if((f & std::ios_base::oct) == std::ios_base::oct) - base = 8; - else if((f & std::ios_base::hex) == std::ios_base::hex) - base = 16; - // - // sanity check, bases 8 and 16 are only available for positive numbers: - // - if((base != 10) && (mpz_sgn(m_data) < 0)) - BOOST_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers")); - void *(*alloc_func_ptr) (size_t); - void *(*realloc_func_ptr) (void *, size_t, size_t); - void (*free_func_ptr) (void *, size_t); - const char* ps = mpz_get_str (0, base, m_data); - std::string s = ps; - mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); - (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); - if (f & std::ios_base::uppercase) - for (size_t i = 0; i < s.length(); ++i) - s[i] = std::toupper(s[i]); - if((base != 10) && (f & std::ios_base::showbase)) - { - int pos = s[0] == '-' ? 1 : 0; - const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x"; - s.insert(static_cast(pos), pp); + mpz_sub_ui(m_data, m_data, static_cast(-term)); + f -= term; + } + if (e > 0) + mpz_mul_2exp(m_data, m_data, e); + else if (e < 0) + mpz_div_2exp(m_data, m_data, -e); + return *this; + } + gmp_int &operator=(const char *s) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + std::size_t n = s ? std::strlen(s) : 0; + int radix = 10; + if (n && (*s == '0')) { + if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) { + radix = 16; + s += 2; + n -= 2; + } else { + radix = 8; + n -= 1; } - if((f & std::ios_base::showpos) && (s[0] != '-')) - s.insert(static_cast(0), 1, '+'); - - return s; - } - ~gmp_int() BOOST_NOEXCEPT - { - if(m_data[0]._mp_d) - mpz_clear(m_data); - } - void negate() BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - mpz_neg(m_data, m_data); - } - int compare(const gmp_int& o)const BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); - return mpz_cmp(m_data, o.m_data); - } - int compare(long i)const BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - return mpz_cmp_si(m_data, i); - } - int compare(unsigned long i)const BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - return mpz_cmp_ui(m_data, i); - } - template - int compare(V v)const - { - gmp_int d; - d = v; - return compare(d); - } - mpz_t& data() BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - return m_data; - } - const mpz_t& data()const BOOST_NOEXCEPT - { - BOOST_ASSERT(m_data[0]._mp_d); - return m_data; - } + } + if (n) { + if (0 != mpz_set_str(m_data, s, radix)) + BOOST_THROW_EXCEPTION(std::runtime_error( + std::string("The string \"") + s + + std::string("\"could not be interpreted as a valid integer."))); + } else + mpz_set_ui(m_data, 0); + return *this; + } + gmp_int &operator=(const mpf_t val) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_f(this->m_data, val); + return *this; + } + gmp_int &operator=(const mpz_t val) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set(this->m_data, val); + return *this; + } + gmp_int &operator=(const mpq_t val) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_q(this->m_data, val); + return *this; + } + template + gmp_int &operator=(const gmp_float &o) { + if (m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_f(this->m_data, o.data()); + return *this; + } + gmp_int &operator=(const gmp_rational &o); + void swap(gmp_int &o) { mpz_swap(m_data, o.m_data); } + std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f) const { + BOOST_ASSERT(m_data[0]._mp_d); + + int base = 10; + if ((f & std::ios_base::oct) == std::ios_base::oct) + base = 8; + else if ((f & std::ios_base::hex) == std::ios_base::hex) + base = 16; + // + // sanity check, bases 8 and 16 are only available for positive numbers: + // + if ((base != 10) && (mpz_sgn(m_data) < 0)) + BOOST_THROW_EXCEPTION( + std::runtime_error("Formatted output in bases 8 or 16 is only " + "available for positive numbers")); + void *(*alloc_func_ptr)(size_t); + void *(*realloc_func_ptr)(void *, size_t, size_t); + void (*free_func_ptr)(void *, size_t); + const char *ps = mpz_get_str(0, base, m_data); + std::string s = ps; + mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); + (*free_func_ptr)((void *)ps, std::strlen(ps) + 1); + if (f & std::ios_base::uppercase) + for (size_t i = 0; i < s.length(); ++i) + s[i] = std::toupper(s[i]); + if ((base != 10) && (f & std::ios_base::showbase)) { + int pos = s[0] == '-' ? 1 : 0; + const char *pp = + base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x"; + s.insert(static_cast(pos), pp); + } + if ((f & std::ios_base::showpos) && (s[0] != '-')) + s.insert(static_cast(0), 1, '+'); + + return s; + } + ~gmp_int() BOOST_NOEXCEPT { + if (m_data[0]._mp_d) + mpz_clear(m_data); + } + void negate() BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + mpz_neg(m_data, m_data); + } + int compare(const gmp_int &o) const BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); + return mpz_cmp(m_data, o.m_data); + } + int compare(long i) const BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + return mpz_cmp_si(m_data, i); + } + int compare(unsigned long i) const BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + return mpz_cmp_ui(m_data, i); + } + template int compare(V v) const { + gmp_int d; + d = v; + return compare(d); + } + mpz_t &data() BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + return m_data; + } + const mpz_t &data() const BOOST_NOEXCEPT { + BOOST_ASSERT(m_data[0]._mp_d); + return m_data; + } + protected: - mpz_t m_data; + mpz_t m_data; }; template -inline typename enable_if, bool>::type eval_eq(const gmp_int& a, const T& b) -{ - return a.compare(b) == 0; +inline typename enable_if, bool>::type +eval_eq(const gmp_int &a, const T &b) { + return a.compare(b) == 0; } template -inline typename enable_if, bool>::type eval_lt(const gmp_int& a, const T& b) -{ - return a.compare(b) < 0; +inline typename enable_if, bool>::type +eval_lt(const gmp_int &a, const T &b) { + return a.compare(b) < 0; } template -inline typename enable_if, bool>::type eval_gt(const gmp_int& a, const T& b) -{ - return a.compare(b) > 0; -} - -inline bool eval_is_zero(const gmp_int& val) -{ - return mpz_sgn(val.data()) == 0; -} -inline void eval_add(gmp_int& t, const gmp_int& o) -{ - mpz_add(t.data(), t.data(), o.data()); -} -inline void eval_multiply_add(gmp_int& t, const gmp_int& a, const gmp_int& b) -{ - mpz_addmul(t.data(), a.data(), b.data()); +inline typename enable_if, bool>::type +eval_gt(const gmp_int &a, const T &b) { + return a.compare(b) > 0; +} + +inline bool eval_is_zero(const gmp_int &val) { + return mpz_sgn(val.data()) == 0; +} +inline void eval_add(gmp_int &t, const gmp_int &o) { + mpz_add(t.data(), t.data(), o.data()); +} +inline void eval_multiply_add(gmp_int &t, const gmp_int &a, const gmp_int &b) { + mpz_addmul(t.data(), a.data(), b.data()); +} +inline void eval_multiply_subtract(gmp_int &t, const gmp_int &a, + const gmp_int &b) { + mpz_submul(t.data(), a.data(), b.data()); +} +inline void eval_subtract(gmp_int &t, const gmp_int &o) { + mpz_sub(t.data(), t.data(), o.data()); +} +inline void eval_multiply(gmp_int &t, const gmp_int &o) { + mpz_mul(t.data(), t.data(), o.data()); +} +inline void eval_divide(gmp_int &t, const gmp_int &o) { + if (eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q(t.data(), t.data(), o.data()); +} +inline void eval_modulus(gmp_int &t, const gmp_int &o) { + mpz_tdiv_r(t.data(), t.data(), o.data()); +} +inline void eval_add(gmp_int &t, unsigned long i) { + mpz_add_ui(t.data(), t.data(), i); +} +inline void eval_multiply_add(gmp_int &t, const gmp_int &a, unsigned long i) { + mpz_addmul_ui(t.data(), a.data(), i); +} +inline void eval_multiply_subtract(gmp_int &t, const gmp_int &a, + unsigned long i) { + mpz_submul_ui(t.data(), a.data(), i); +} +inline void eval_subtract(gmp_int &t, unsigned long i) { + mpz_sub_ui(t.data(), t.data(), i); +} +inline void eval_multiply(gmp_int &t, unsigned long i) { + mpz_mul_ui(t.data(), t.data(), i); +} +inline void eval_modulus(gmp_int &t, unsigned long i) { + mpz_tdiv_r_ui(t.data(), t.data(), i); +} +inline void eval_divide(gmp_int &t, unsigned long i) { + if (i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q_ui(t.data(), t.data(), i); +} +inline void eval_add(gmp_int &t, long i) { + if (i > 0) + mpz_add_ui(t.data(), t.data(), i); + else + mpz_sub_ui(t.data(), t.data(), + boost::multiprecision::detail::unsigned_abs(i)); +} +inline void eval_multiply_add(gmp_int &t, const gmp_int &a, long i) { + if (i > 0) + mpz_addmul_ui(t.data(), a.data(), i); + else + mpz_submul_ui(t.data(), a.data(), + boost::multiprecision::detail::unsigned_abs(i)); +} +inline void eval_multiply_subtract(gmp_int &t, const gmp_int &a, long i) { + if (i > 0) + mpz_submul_ui(t.data(), a.data(), i); + else + mpz_addmul_ui(t.data(), a.data(), + boost::multiprecision::detail::unsigned_abs(i)); +} +inline void eval_subtract(gmp_int &t, long i) { + if (i > 0) + mpz_sub_ui(t.data(), t.data(), i); + else + mpz_add_ui(t.data(), t.data(), + boost::multiprecision::detail::unsigned_abs(i)); +} +inline void eval_multiply(gmp_int &t, long i) { + mpz_mul_ui(t.data(), t.data(), + boost::multiprecision::detail::unsigned_abs(i)); + if (i < 0) + mpz_neg(t.data(), t.data()); +} +inline void eval_modulus(gmp_int &t, long i) { + mpz_tdiv_r_ui(t.data(), t.data(), + boost::multiprecision::detail::unsigned_abs(i)); +} +inline void eval_divide(gmp_int &t, long i) { + if (i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q_ui(t.data(), t.data(), + boost::multiprecision::detail::unsigned_abs(i)); + if (i < 0) + mpz_neg(t.data(), t.data()); } -inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, const gmp_int& b) -{ - mpz_submul(t.data(), a.data(), b.data()); -} -inline void eval_subtract(gmp_int& t, const gmp_int& o) -{ - mpz_sub(t.data(), t.data(), o.data()); -} -inline void eval_multiply(gmp_int& t, const gmp_int& o) -{ - mpz_mul(t.data(), t.data(), o.data()); -} -inline void eval_divide(gmp_int& t, const gmp_int& o) -{ - if(eval_is_zero(o)) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpz_tdiv_q(t.data(), t.data(), o.data()); -} -inline void eval_modulus(gmp_int& t, const gmp_int& o) -{ - mpz_tdiv_r(t.data(), t.data(), o.data()); -} -inline void eval_add(gmp_int& t, unsigned long i) -{ - mpz_add_ui(t.data(), t.data(), i); -} -inline void eval_multiply_add(gmp_int& t, const gmp_int& a, unsigned long i) -{ - mpz_addmul_ui(t.data(), a.data(), i); -} -inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, unsigned long i) -{ - mpz_submul_ui(t.data(), a.data(), i); -} -inline void eval_subtract(gmp_int& t, unsigned long i) -{ - mpz_sub_ui(t.data(), t.data(), i); -} -inline void eval_multiply(gmp_int& t, unsigned long i) -{ - mpz_mul_ui(t.data(), t.data(), i); -} -inline void eval_modulus(gmp_int& t, unsigned long i) -{ - mpz_tdiv_r_ui(t.data(), t.data(), i); -} -inline void eval_divide(gmp_int& t, unsigned long i) -{ - if(i == 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpz_tdiv_q_ui(t.data(), t.data(), i); -} -inline void eval_add(gmp_int& t, long i) -{ - if(i > 0) - mpz_add_ui(t.data(), t.data(), i); - else - mpz_sub_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); -} -inline void eval_multiply_add(gmp_int& t, const gmp_int& a, long i) -{ - if(i > 0) - mpz_addmul_ui(t.data(), a.data(), i); - else - mpz_submul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i)); -} -inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, long i) -{ - if(i > 0) - mpz_submul_ui(t.data(), a.data(), i); - else - mpz_addmul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i)); -} -inline void eval_subtract(gmp_int& t, long i) -{ - if(i > 0) - mpz_sub_ui(t.data(), t.data(), i); - else - mpz_add_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); -} -inline void eval_multiply(gmp_int& t, long i) -{ - mpz_mul_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); - if(i < 0) - mpz_neg(t.data(), t.data()); -} -inline void eval_modulus(gmp_int& t, long i) -{ - mpz_tdiv_r_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); -} -inline void eval_divide(gmp_int& t, long i) -{ - if(i == 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpz_tdiv_q_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); - if(i < 0) - mpz_neg(t.data(), t.data()); +template inline void eval_left_shift(gmp_int &t, UI i) { + mpz_mul_2exp(t.data(), t.data(), static_cast(i)); +} +template inline void eval_right_shift(gmp_int &t, UI i) { + mpz_fdiv_q_2exp(t.data(), t.data(), static_cast(i)); } template -inline void eval_left_shift(gmp_int& t, UI i) -{ - mpz_mul_2exp(t.data(), t.data(), static_cast(i)); +inline void eval_left_shift(gmp_int &t, const gmp_int &v, UI i) { + mpz_mul_2exp(t.data(), v.data(), static_cast(i)); } template -inline void eval_right_shift(gmp_int& t, UI i) -{ - mpz_fdiv_q_2exp(t.data(), t.data(), static_cast(i)); -} -template -inline void eval_left_shift(gmp_int& t, const gmp_int& v, UI i) -{ - mpz_mul_2exp(t.data(), v.data(), static_cast(i)); -} -template -inline void eval_right_shift(gmp_int& t, const gmp_int& v, UI i) -{ - mpz_fdiv_q_2exp(t.data(), v.data(), static_cast(i)); +inline void eval_right_shift(gmp_int &t, const gmp_int &v, UI i) { + mpz_fdiv_q_2exp(t.data(), v.data(), static_cast(i)); } -inline void eval_bitwise_and(gmp_int& result, const gmp_int& v) -{ - mpz_and(result.data(), result.data(), v.data()); +inline void eval_bitwise_and(gmp_int &result, const gmp_int &v) { + mpz_and(result.data(), result.data(), v.data()); } -inline void eval_bitwise_or(gmp_int& result, const gmp_int& v) -{ - mpz_ior(result.data(), result.data(), v.data()); +inline void eval_bitwise_or(gmp_int &result, const gmp_int &v) { + mpz_ior(result.data(), result.data(), v.data()); } -inline void eval_bitwise_xor(gmp_int& result, const gmp_int& v) -{ - mpz_xor(result.data(), result.data(), v.data()); +inline void eval_bitwise_xor(gmp_int &result, const gmp_int &v) { + mpz_xor(result.data(), result.data(), v.data()); } -inline void eval_add(gmp_int& t, const gmp_int& p, const gmp_int& o) -{ - mpz_add(t.data(), p.data(), o.data()); +inline void eval_add(gmp_int &t, const gmp_int &p, const gmp_int &o) { + mpz_add(t.data(), p.data(), o.data()); } -inline void eval_subtract(gmp_int& t, const gmp_int& p, const gmp_int& o) -{ - mpz_sub(t.data(), p.data(), o.data()); +inline void eval_subtract(gmp_int &t, const gmp_int &p, const gmp_int &o) { + mpz_sub(t.data(), p.data(), o.data()); } -inline void eval_multiply(gmp_int& t, const gmp_int& p, const gmp_int& o) -{ - mpz_mul(t.data(), p.data(), o.data()); +inline void eval_multiply(gmp_int &t, const gmp_int &p, const gmp_int &o) { + mpz_mul(t.data(), p.data(), o.data()); } -inline void eval_divide(gmp_int& t, const gmp_int& p, const gmp_int& o) -{ - if(eval_is_zero(o)) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpz_tdiv_q(t.data(), p.data(), o.data()); +inline void eval_divide(gmp_int &t, const gmp_int &p, const gmp_int &o) { + if (eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q(t.data(), p.data(), o.data()); } -inline void eval_modulus(gmp_int& t, const gmp_int& p, const gmp_int& o) -{ - mpz_tdiv_r(t.data(), p.data(), o.data()); +inline void eval_modulus(gmp_int &t, const gmp_int &p, const gmp_int &o) { + mpz_tdiv_r(t.data(), p.data(), o.data()); } -inline void eval_add(gmp_int& t, const gmp_int& p, unsigned long i) -{ - mpz_add_ui(t.data(), p.data(), i); +inline void eval_add(gmp_int &t, const gmp_int &p, unsigned long i) { + mpz_add_ui(t.data(), p.data(), i); } -inline void eval_subtract(gmp_int& t, const gmp_int& p, unsigned long i) -{ - mpz_sub_ui(t.data(), p.data(), i); +inline void eval_subtract(gmp_int &t, const gmp_int &p, unsigned long i) { + mpz_sub_ui(t.data(), p.data(), i); } -inline void eval_multiply(gmp_int& t, const gmp_int& p, unsigned long i) -{ - mpz_mul_ui(t.data(), p.data(), i); +inline void eval_multiply(gmp_int &t, const gmp_int &p, unsigned long i) { + mpz_mul_ui(t.data(), p.data(), i); } -inline void eval_modulus(gmp_int& t, const gmp_int& p, unsigned long i) -{ - mpz_tdiv_r_ui(t.data(), p.data(), i); +inline void eval_modulus(gmp_int &t, const gmp_int &p, unsigned long i) { + mpz_tdiv_r_ui(t.data(), p.data(), i); } -inline void eval_divide(gmp_int& t, const gmp_int& p, unsigned long i) -{ - if(i == 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpz_tdiv_q_ui(t.data(), p.data(), i); +inline void eval_divide(gmp_int &t, const gmp_int &p, unsigned long i) { + if (i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q_ui(t.data(), p.data(), i); } -inline void eval_add(gmp_int& t, const gmp_int& p, long i) -{ - if(i > 0) - mpz_add_ui(t.data(), p.data(), i); - else - mpz_sub_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); +inline void eval_add(gmp_int &t, const gmp_int &p, long i) { + if (i > 0) + mpz_add_ui(t.data(), p.data(), i); + else + mpz_sub_ui(t.data(), p.data(), + boost::multiprecision::detail::unsigned_abs(i)); } -inline void eval_subtract(gmp_int& t, const gmp_int& p, long i) -{ - if(i > 0) - mpz_sub_ui(t.data(), p.data(), i); - else - mpz_add_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); +inline void eval_subtract(gmp_int &t, const gmp_int &p, long i) { + if (i > 0) + mpz_sub_ui(t.data(), p.data(), i); + else + mpz_add_ui(t.data(), p.data(), + boost::multiprecision::detail::unsigned_abs(i)); } -inline void eval_multiply(gmp_int& t, const gmp_int& p, long i) -{ - mpz_mul_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); - if(i < 0) - mpz_neg(t.data(), t.data()); +inline void eval_multiply(gmp_int &t, const gmp_int &p, long i) { + mpz_mul_ui(t.data(), p.data(), + boost::multiprecision::detail::unsigned_abs(i)); + if (i < 0) + mpz_neg(t.data(), t.data()); } -inline void eval_modulus(gmp_int& t, const gmp_int& p, long i) -{ - mpz_tdiv_r_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); +inline void eval_modulus(gmp_int &t, const gmp_int &p, long i) { + mpz_tdiv_r_ui(t.data(), p.data(), + boost::multiprecision::detail::unsigned_abs(i)); } -inline void eval_divide(gmp_int& t, const gmp_int& p, long i) -{ - if(i == 0) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpz_tdiv_q_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); - if(i < 0) - mpz_neg(t.data(), t.data()); +inline void eval_divide(gmp_int &t, const gmp_int &p, long i) { + if (i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q_ui(t.data(), p.data(), + boost::multiprecision::detail::unsigned_abs(i)); + if (i < 0) + mpz_neg(t.data(), t.data()); } -inline void eval_bitwise_and(gmp_int& result, const gmp_int& u, const gmp_int& v) -{ - mpz_and(result.data(), u.data(), v.data()); +inline void eval_bitwise_and(gmp_int &result, const gmp_int &u, + const gmp_int &v) { + mpz_and(result.data(), u.data(), v.data()); } -inline void eval_bitwise_or(gmp_int& result, const gmp_int& u, const gmp_int& v) -{ - mpz_ior(result.data(), u.data(), v.data()); +inline void eval_bitwise_or(gmp_int &result, const gmp_int &u, + const gmp_int &v) { + mpz_ior(result.data(), u.data(), v.data()); } -inline void eval_bitwise_xor(gmp_int& result, const gmp_int& u, const gmp_int& v) -{ - mpz_xor(result.data(), u.data(), v.data()); +inline void eval_bitwise_xor(gmp_int &result, const gmp_int &u, + const gmp_int &v) { + mpz_xor(result.data(), u.data(), v.data()); } -inline void eval_complement(gmp_int& result, const gmp_int& u) -{ - mpz_com(result.data(), u.data()); +inline void eval_complement(gmp_int &result, const gmp_int &u) { + mpz_com(result.data(), u.data()); } -inline int eval_get_sign(const gmp_int& val) -{ - return mpz_sgn(val.data()); +inline int eval_get_sign(const gmp_int &val) { return mpz_sgn(val.data()); } +inline void eval_convert_to(unsigned long *result, const gmp_int &val) { + if (mpz_sgn(val.data()) < 0) { + BOOST_THROW_EXCEPTION( + std::range_error("Conversion from negative integer to an unsigned type " + "results in undefined behaviour")); + } else + *result = (unsigned long)mpz_get_ui(val.data()); } -inline void eval_convert_to(unsigned long* result, const gmp_int& val) -{ - if (mpz_sgn(val.data()) < 0) - { - BOOST_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour")); - } - else - *result = (unsigned long)mpz_get_ui(val.data()); -} -inline void eval_convert_to(long* result, const gmp_int& val) -{ - if(0 == mpz_fits_slong_p(val.data())) - { - *result = mpz_sgn(val.data()) < 0 ? (std::numeric_limits::min)() : (std::numeric_limits::max)(); - } - else - *result = (signed long)mpz_get_si(val.data()); -} -inline void eval_convert_to(double* result, const gmp_int& val) -{ - *result = mpz_get_d(val.data()); +inline void eval_convert_to(long *result, const gmp_int &val) { + if (0 == mpz_fits_slong_p(val.data())) { + *result = mpz_sgn(val.data()) < 0 ? (std::numeric_limits::min)() + : (std::numeric_limits::max)(); + } else + *result = (signed long)mpz_get_si(val.data()); +} +inline void eval_convert_to(double *result, const gmp_int &val) { + *result = mpz_get_d(val.data()); } -inline void eval_abs(gmp_int& result, const gmp_int& val) -{ - mpz_abs(result.data(), val.data()); +inline void eval_abs(gmp_int &result, const gmp_int &val) { + mpz_abs(result.data(), val.data()); } -inline void eval_gcd(gmp_int& result, const gmp_int& a, const gmp_int& b) -{ - mpz_gcd(result.data(), a.data(), b.data()); +inline void eval_gcd(gmp_int &result, const gmp_int &a, const gmp_int &b) { + mpz_gcd(result.data(), a.data(), b.data()); } -inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b) -{ - mpz_lcm(result.data(), a.data(), b.data()); +inline void eval_lcm(gmp_int &result, const gmp_int &a, const gmp_int &b) { + mpz_lcm(result.data(), a.data(), b.data()); } template -inline typename enable_if_c<(is_unsigned::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b) -{ - mpz_gcd_ui(result.data(), a.data(), b); +inline typename enable_if_c<(is_unsigned::value && + (sizeof(I) <= sizeof(unsigned long)))>::type +eval_gcd(gmp_int &result, const gmp_int &a, const I b) { + mpz_gcd_ui(result.data(), a.data(), b); } template -inline typename enable_if_c<(is_unsigned::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b) -{ - mpz_lcm_ui(result.data(), a.data(), b); +inline typename enable_if_c<(is_unsigned::value && + (sizeof(I) <= sizeof(unsigned long)))>::type +eval_lcm(gmp_int &result, const gmp_int &a, const I b) { + mpz_lcm_ui(result.data(), a.data(), b); } template -inline typename enable_if_c<(is_signed::value && (sizeof(I) <= sizeof(long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b) -{ - mpz_gcd_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b)); +inline typename enable_if_c<(is_signed::value && + (sizeof(I) <= sizeof(long)))>::type +eval_gcd(gmp_int &result, const gmp_int &a, const I b) { + mpz_gcd_ui(result.data(), a.data(), + boost::multiprecision::detail::unsigned_abs(b)); } template -inline typename enable_if_c::value && ((sizeof(I) <= sizeof(long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b) -{ - mpz_lcm_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b)); +inline typename enable_if_c::value && + ((sizeof(I) <= sizeof(long)))>::type +eval_lcm(gmp_int &result, const gmp_int &a, const I b) { + mpz_lcm_ui(result.data(), a.data(), + boost::multiprecision::detail::unsigned_abs(b)); } -inline void eval_integer_sqrt(gmp_int& s, gmp_int& r, const gmp_int& x) -{ - mpz_sqrtrem(s.data(), r.data(), x.data()); +inline void eval_integer_sqrt(gmp_int &s, gmp_int &r, const gmp_int &x) { + mpz_sqrtrem(s.data(), r.data(), x.data()); } -inline unsigned eval_lsb(const gmp_int& val) -{ - int c = eval_get_sign(val); - if(c == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - if(c < 0) - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - return static_cast(mpz_scan1(val.data(), 0)); -} - -inline unsigned eval_msb(const gmp_int& val) -{ - int c = eval_get_sign(val); - if(c == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - if(c < 0) - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - return static_cast(mpz_sizeinbase(val.data(), 2) - 1); -} - -inline bool eval_bit_test(const gmp_int& val, unsigned index) -{ - return mpz_tstbit(val.data(), index) ? true : false; +inline unsigned eval_lsb(const gmp_int &val) { + int c = eval_get_sign(val); + if (c == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (c < 0) { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + return static_cast(mpz_scan1(val.data(), 0)); } -inline void eval_bit_set(gmp_int& val, unsigned index) -{ - mpz_setbit(val.data(), index); +inline unsigned eval_msb(const gmp_int &val) { + int c = eval_get_sign(val); + if (c == 0) { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if (c < 0) { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + return static_cast(mpz_sizeinbase(val.data(), 2) - 1); } -inline void eval_bit_unset(gmp_int& val, unsigned index) -{ - mpz_clrbit(val.data(), index); +inline bool eval_bit_test(const gmp_int &val, unsigned index) { + return mpz_tstbit(val.data(), index) ? true : false; } -inline void eval_bit_flip(gmp_int& val, unsigned index) -{ - mpz_combit(val.data(), index); +inline void eval_bit_set(gmp_int &val, unsigned index) { + mpz_setbit(val.data(), index); } -inline void eval_qr(const gmp_int& x, const gmp_int& y, - gmp_int& q, gmp_int& r) -{ - mpz_tdiv_qr(q.data(), r.data(), x.data(), y.data()); +inline void eval_bit_unset(gmp_int &val, unsigned index) { + mpz_clrbit(val.data(), index); +} + +inline void eval_bit_flip(gmp_int &val, unsigned index) { + mpz_combit(val.data(), index); +} + +inline void eval_qr(const gmp_int &x, const gmp_int &y, gmp_int &q, + gmp_int &r) { + mpz_tdiv_qr(q.data(), r.data(), x.data(), y.data()); } template -inline typename enable_if, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val) -{ +inline typename enable_if, Integer>::type +eval_integer_modulus(const gmp_int &x, Integer val) { #if defined(__MPIR_VERSION) && (__MPIR_VERSION >= 3) - if((sizeof(Integer) <= sizeof(mpir_ui)) || (val <= (std::numeric_limits::max)())) + if ((sizeof(Integer) <= sizeof(mpir_ui)) || + (val <= (std::numeric_limits::max)())) #else - if((sizeof(Integer) <= sizeof(long)) || (val <= (std::numeric_limits::max)())) + if ((sizeof(Integer) <= sizeof(long)) || + (val <= (std::numeric_limits::max)())) #endif - { - return static_cast(mpz_tdiv_ui(x.data(), val)); - } - else - { - return default_ops::eval_integer_modulus(x, val); - } + { + return static_cast(mpz_tdiv_ui(x.data(), val)); + } else { + return default_ops::eval_integer_modulus(x, val); + } } template -inline typename enable_if, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val) -{ - return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val)); +inline typename enable_if, Integer>::type +eval_integer_modulus(const gmp_int &x, Integer val) { + return eval_integer_modulus(x, + boost::multiprecision::detail::unsigned_abs(val)); } -inline void eval_powm(gmp_int& result, const gmp_int& base, const gmp_int& p, const gmp_int& m) -{ - if(eval_get_sign(p) < 0) - { - BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); - } - mpz_powm(result.data(), base.data(), p.data(), m.data()); +inline void eval_powm(gmp_int &result, const gmp_int &base, const gmp_int &p, + const gmp_int &m) { + if (eval_get_sign(p) < 0) { + BOOST_THROW_EXCEPTION( + std::runtime_error("powm requires a positive exponent.")); + } + mpz_powm(result.data(), base.data(), p.data(), m.data()); } template inline typename enable_if< - mpl::and_< - is_unsigned, - mpl::bool_ - > ->::type eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m) -{ - mpz_powm_ui(result.data(), base.data(), p, m.data()); + mpl::and_, + mpl::bool_>>::type +eval_powm(gmp_int &result, const gmp_int &base, Integer p, const gmp_int &m) { + mpz_powm_ui(result.data(), base.data(), p, m.data()); } template inline typename enable_if< - mpl::and_< - is_signed, - mpl::bool_ - > ->::type eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m) -{ - if(p < 0) - { - BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); - } - mpz_powm_ui(result.data(), base.data(), p, m.data()); -} - -inline std::size_t hash_value(const gmp_int& val) -{ - // We should really use mpz_limbs_read here, but that's unsupported on older versions: - std::size_t result = 0; - for(int i = 0; i < std::abs(val.data()[0]._mp_size); ++i) - boost::hash_combine(result, val.data()[0]._mp_d[i]); - boost::hash_combine(result, val.data()[0]._mp_size); - return result; + mpl::and_, + mpl::bool_>>::type +eval_powm(gmp_int &result, const gmp_int &base, Integer p, const gmp_int &m) { + if (p < 0) { + BOOST_THROW_EXCEPTION( + std::runtime_error("powm requires a positive exponent.")); + } + mpz_powm_ui(result.data(), base.data(), p, m.data()); +} + +inline std::size_t hash_value(const gmp_int &val) { + // We should really use mpz_limbs_read here, but that's unsupported on older + // versions: + std::size_t result = 0; + for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i) + boost::hash_combine(result, val.data()[0]._mp_d[i]); + boost::hash_combine(result, val.data()[0]._mp_size); + return result; } struct gmp_rational; -void eval_add(gmp_rational& t, const gmp_rational& o); +void eval_add(gmp_rational &t, const gmp_rational &o); -struct gmp_rational -{ +struct gmp_rational { #ifdef BOOST_HAS_LONG_LONG - typedef mpl::list signed_types; - typedef mpl::list unsigned_types; + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; #else - typedef mpl::list signed_types; - typedef mpl::list unsigned_types; + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; #endif - typedef mpl::list float_types; - - gmp_rational() - { - mpq_init(this->m_data); - } - gmp_rational(const gmp_rational& o) - { - mpq_init(m_data); - if(o.m_data[0]._mp_num._mp_d) - mpq_set(m_data, o.m_data); - } - gmp_rational(const gmp_int& o) - { - mpq_init(m_data); - mpq_set_z(m_data, o.data()); - } + typedef mpl::list float_types; + + gmp_rational() { mpq_init(this->m_data); } + gmp_rational(const gmp_rational &o) { + mpq_init(m_data); + if (o.m_data[0]._mp_num._mp_d) + mpq_set(m_data, o.m_data); + } + gmp_rational(const gmp_int &o) { + mpq_init(m_data); + mpq_set_z(m_data, o.data()); + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_rational(gmp_rational&& o) BOOST_NOEXCEPT - { - m_data[0] = o.m_data[0]; - o.m_data[0]._mp_num._mp_d = 0; - o.m_data[0]._mp_den._mp_d = 0; - } + gmp_rational(gmp_rational &&o) BOOST_NOEXCEPT { + m_data[0] = o.m_data[0]; + o.m_data[0]._mp_num._mp_d = 0; + o.m_data[0]._mp_den._mp_d = 0; + } #endif - gmp_rational(const mpq_t o) - { + gmp_rational(const mpq_t o) { + mpq_init(m_data); + mpq_set(m_data, o); + } + gmp_rational(const mpz_t o) { + mpq_init(m_data); + mpq_set_z(m_data, o); + } + gmp_rational &operator=(const gmp_rational &o) { + if (m_data[0]._mp_den._mp_d == 0) mpq_init(m_data); - mpq_set(m_data, o); - } - gmp_rational(const mpz_t o) - { - mpq_init(m_data); - mpq_set_z(m_data, o); - } - gmp_rational& operator = (const gmp_rational& o) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - mpq_set(m_data, o.m_data); - return *this; - } + mpq_set(m_data, o.m_data); + return *this; + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - gmp_rational& operator = (gmp_rational&& o) BOOST_NOEXCEPT - { - mpq_swap(m_data, o.m_data); - return *this; - } + gmp_rational &operator=(gmp_rational &&o) BOOST_NOEXCEPT { + mpq_swap(m_data, o.m_data); + return *this; + } #endif #ifdef BOOST_HAS_LONG_LONG #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) - gmp_rational& operator = (boost::ulong_long_type i) - { - *this = static_cast(i); - return *this; - } + gmp_rational &operator=(boost::ulong_long_type i) { + *this = static_cast(i); + return *this; + } #else - gmp_rational& operator = (boost::ulong_long_type i) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - gmp_int zi; - zi = i; - mpq_set_z(m_data, zi.data()); - return *this; - } - gmp_rational& operator = (boost::long_long_type i) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - bool neg = i < 0; - *this = boost::multiprecision::detail::unsigned_abs(i); - if(neg) - mpq_neg(m_data, m_data); - return *this; - } + gmp_rational &operator=(boost::ulong_long_type i) { + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + gmp_int zi; + zi = i; + mpq_set_z(m_data, zi.data()); + return *this; + } + gmp_rational &operator=(boost::long_long_type i) { + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + bool neg = i < 0; + *this = boost::multiprecision::detail::unsigned_abs(i); + if (neg) + mpq_neg(m_data, m_data); + return *this; + } #endif #endif - gmp_rational& operator = (unsigned long i) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - mpq_set_ui(m_data, i, 1); - return *this; - } - gmp_rational& operator = (long i) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - mpq_set_si(m_data, i, 1); - return *this; - } - gmp_rational& operator = (double d) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - mpq_set_d(m_data, d); - return *this; - } - gmp_rational& operator = (long double a) - { - using std::frexp; - using std::ldexp; - using std::floor; - using default_ops::eval_add; - using default_ops::eval_subtract; - - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - - if (a == 0) { - mpq_set_si(m_data, 0, 1); - return *this; - } - - if (a == 1) { - mpq_set_si(m_data, 1, 1); - return *this; - } + gmp_rational &operator=(unsigned long i) { + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_ui(m_data, i, 1); + return *this; + } + gmp_rational &operator=(long i) { + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_si(m_data, i, 1); + return *this; + } + gmp_rational &operator=(double d) { + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_d(m_data, d); + return *this; + } + gmp_rational &operator=(long double a) { + using default_ops::eval_add; + using default_ops::eval_subtract; + using std::floor; + using std::frexp; + using std::ldexp; + + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); - BOOST_ASSERT(!(boost::math::isinf)(a)); - BOOST_ASSERT(!(boost::math::isnan)(a)); - - int e; - long double f, term; - mpq_set_ui(m_data, 0, 1); - mpq_set_ui(m_data, 0u, 1); - gmp_rational t; - - f = frexp(a, &e); - - static const int shift = std::numeric_limits::digits - 1; - - while(f) - { - // extract int sized bits from f: - f = ldexp(f, shift); - term = floor(f); - e -= shift; - mpq_mul_2exp(m_data, m_data, shift); - t = static_cast(term); - eval_add(*this, t); - f -= term; - } - if(e > 0) - mpq_mul_2exp(m_data, m_data, e); - else if(e < 0) - mpq_div_2exp(m_data, m_data, -e); + if (a == 0) { + mpq_set_si(m_data, 0, 1); return *this; - } - gmp_rational& operator = (const char* s) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - if(0 != mpq_set_str(m_data, s, 10)) - BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid rational number."))); - return *this; - } - gmp_rational& operator=(const gmp_int& o) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - mpq_set_z(m_data, o.data()); - return *this; - } - gmp_rational& operator=(const mpq_t o) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - mpq_set(m_data, o); - return *this; - } - gmp_rational& operator=(const mpz_t o) - { - if(m_data[0]._mp_den._mp_d == 0) - mpq_init(m_data); - mpq_set_z(m_data, o); + } + + if (a == 1) { + mpq_set_si(m_data, 1, 1); return *this; - } - void swap(gmp_rational& o) - { - mpq_swap(m_data, o.m_data); - } - std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags /*f*/)const - { - BOOST_ASSERT(m_data[0]._mp_num._mp_d); - // TODO make a better job of this including handling of f!! - void *(*alloc_func_ptr) (size_t); - void *(*realloc_func_ptr) (void *, size_t, size_t); - void (*free_func_ptr) (void *, size_t); - const char* ps = mpq_get_str (0, 10, m_data); - std::string s = ps; - mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); - (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); - return s; - } - ~gmp_rational() - { - if(m_data[0]._mp_num._mp_d || m_data[0]._mp_den._mp_d) - mpq_clear(m_data); - } - void negate() - { - BOOST_ASSERT(m_data[0]._mp_num._mp_d); - mpq_neg(m_data, m_data); - } - int compare(const gmp_rational& o)const - { - BOOST_ASSERT(m_data[0]._mp_num._mp_d && o.m_data[0]._mp_num._mp_d); - return mpq_cmp(m_data, o.m_data); - } - template - int compare(V v)const - { - gmp_rational d; - d = v; - return compare(d); - } - int compare(unsigned long v)const - { - BOOST_ASSERT(m_data[0]._mp_num._mp_d); - return mpq_cmp_ui(m_data, v, 1); - } - int compare(long v)const - { - BOOST_ASSERT(m_data[0]._mp_num._mp_d); - return mpq_cmp_si(m_data, v, 1); - } - mpq_t& data() - { - BOOST_ASSERT(m_data[0]._mp_num._mp_d); - return m_data; - } - const mpq_t& data()const - { - BOOST_ASSERT(m_data[0]._mp_num._mp_d); - return m_data; - } + } + + BOOST_ASSERT(!(boost::math::isinf)(a)); + BOOST_ASSERT(!(boost::math::isnan)(a)); + + int e; + long double f, term; + mpq_set_ui(m_data, 0, 1); + mpq_set_ui(m_data, 0u, 1); + gmp_rational t; + + f = frexp(a, &e); + + static const int shift = std::numeric_limits::digits - 1; + + while (f) { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + mpq_mul_2exp(m_data, m_data, shift); + t = static_cast(term); + eval_add(*this, t); + f -= term; + } + if (e > 0) + mpq_mul_2exp(m_data, m_data, e); + else if (e < 0) + mpq_div_2exp(m_data, m_data, -e); + return *this; + } + gmp_rational &operator=(const char *s) { + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + if (0 != mpq_set_str(m_data, s, 10)) + BOOST_THROW_EXCEPTION(std::runtime_error( + std::string("The string \"") + s + + std::string( + "\"could not be interpreted as a valid rational number."))); + return *this; + } + gmp_rational &operator=(const gmp_int &o) { + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_z(m_data, o.data()); + return *this; + } + gmp_rational &operator=(const mpq_t o) { + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set(m_data, o); + return *this; + } + gmp_rational &operator=(const mpz_t o) { + if (m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_z(m_data, o); + return *this; + } + void swap(gmp_rational &o) { mpq_swap(m_data, o.m_data); } + std::string str(std::streamsize /*digits*/, + std::ios_base::fmtflags /*f*/) const { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + // TODO make a better job of this including handling of f!! + void *(*alloc_func_ptr)(size_t); + void *(*realloc_func_ptr)(void *, size_t, size_t); + void (*free_func_ptr)(void *, size_t); + const char *ps = mpq_get_str(0, 10, m_data); + std::string s = ps; + mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); + (*free_func_ptr)((void *)ps, std::strlen(ps) + 1); + return s; + } + ~gmp_rational() { + if (m_data[0]._mp_num._mp_d || m_data[0]._mp_den._mp_d) + mpq_clear(m_data); + } + void negate() { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + mpq_neg(m_data, m_data); + } + int compare(const gmp_rational &o) const { + BOOST_ASSERT(m_data[0]._mp_num._mp_d && o.m_data[0]._mp_num._mp_d); + return mpq_cmp(m_data, o.m_data); + } + template int compare(V v) const { + gmp_rational d; + d = v; + return compare(d); + } + int compare(unsigned long v) const { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + return mpq_cmp_ui(m_data, v, 1); + } + int compare(long v) const { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + return mpq_cmp_si(m_data, v, 1); + } + mpq_t &data() { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + return m_data; + } + const mpq_t &data() const { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + return m_data; + } + protected: - mpq_t m_data; + mpq_t m_data; }; -inline bool eval_is_zero(const gmp_rational& val) -{ - return mpq_sgn(val.data()) == 0; +inline bool eval_is_zero(const gmp_rational &val) { + return mpq_sgn(val.data()) == 0; } -template -inline bool eval_eq(gmp_rational& a, const T& b) -{ - return a.compare(b) == 0; +template inline bool eval_eq(gmp_rational &a, const T &b) { + return a.compare(b) == 0; } -template -inline bool eval_lt(gmp_rational& a, const T& b) -{ - return a.compare(b) < 0; +template inline bool eval_lt(gmp_rational &a, const T &b) { + return a.compare(b) < 0; } -template -inline bool eval_gt(gmp_rational& a, const T& b) -{ - return a.compare(b) > 0; +template inline bool eval_gt(gmp_rational &a, const T &b) { + return a.compare(b) > 0; } -inline void eval_add(gmp_rational& t, const gmp_rational& o) -{ - mpq_add(t.data(), t.data(), o.data()); +inline void eval_add(gmp_rational &t, const gmp_rational &o) { + mpq_add(t.data(), t.data(), o.data()); } -inline void eval_subtract(gmp_rational& t, const gmp_rational& o) -{ - mpq_sub(t.data(), t.data(), o.data()); +inline void eval_subtract(gmp_rational &t, const gmp_rational &o) { + mpq_sub(t.data(), t.data(), o.data()); } -inline void eval_multiply(gmp_rational& t, const gmp_rational& o) -{ - mpq_mul(t.data(), t.data(), o.data()); +inline void eval_multiply(gmp_rational &t, const gmp_rational &o) { + mpq_mul(t.data(), t.data(), o.data()); } -inline void eval_divide(gmp_rational& t, const gmp_rational& o) -{ - if(eval_is_zero(o)) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpq_div(t.data(), t.data(), o.data()); +inline void eval_divide(gmp_rational &t, const gmp_rational &o) { + if (eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpq_div(t.data(), t.data(), o.data()); } -inline void eval_add(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) -{ - mpq_add(t.data(), p.data(), o.data()); +inline void eval_add(gmp_rational &t, const gmp_rational &p, + const gmp_rational &o) { + mpq_add(t.data(), p.data(), o.data()); } -inline void eval_subtract(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) -{ - mpq_sub(t.data(), p.data(), o.data()); +inline void eval_subtract(gmp_rational &t, const gmp_rational &p, + const gmp_rational &o) { + mpq_sub(t.data(), p.data(), o.data()); } -inline void eval_multiply(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) -{ - mpq_mul(t.data(), p.data(), o.data()); +inline void eval_multiply(gmp_rational &t, const gmp_rational &p, + const gmp_rational &o) { + mpq_mul(t.data(), p.data(), o.data()); } -inline void eval_divide(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) -{ - if(eval_is_zero(o)) - BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); - mpq_div(t.data(), p.data(), o.data()); +inline void eval_divide(gmp_rational &t, const gmp_rational &p, + const gmp_rational &o) { + if (eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpq_div(t.data(), p.data(), o.data()); } -inline int eval_get_sign(const gmp_rational& val) -{ - return mpq_sgn(val.data()); +inline int eval_get_sign(const gmp_rational &val) { + return mpq_sgn(val.data()); } -inline void eval_convert_to(double* result, const gmp_rational& val) -{ - // - // This does not round correctly: - // - //*result = mpq_get_d(val.data()); - // - // This does: - // - boost::multiprecision::detail::generic_convert_rational_to_float(*result, val); +inline void eval_convert_to(double *result, const gmp_rational &val) { + // + // This does not round correctly: + // + //*result = mpq_get_d(val.data()); + // + // This does: + // + boost::multiprecision::detail::generic_convert_rational_to_float(*result, + val); } -inline void eval_convert_to(long* result, const gmp_rational& val) -{ - double r; - eval_convert_to(&r, val); - *result = static_cast(r); +inline void eval_convert_to(long *result, const gmp_rational &val) { + double r; + eval_convert_to(&r, val); + *result = static_cast(r); } -inline void eval_convert_to(unsigned long* result, const gmp_rational& val) -{ - double r; - eval_convert_to(&r, val); - *result = static_cast(r); +inline void eval_convert_to(unsigned long *result, const gmp_rational &val) { + double r; + eval_convert_to(&r, val); + *result = static_cast(r); } -inline void eval_abs(gmp_rational& result, const gmp_rational& val) -{ - mpq_abs(result.data(), val.data()); +inline void eval_abs(gmp_rational &result, const gmp_rational &val) { + mpq_abs(result.data(), val.data()); } -inline void assign_components(gmp_rational& result, unsigned long v1, unsigned long v2) -{ - mpq_set_ui(result.data(), v1, v2); - mpq_canonicalize(result.data()); +inline void assign_components(gmp_rational &result, unsigned long v1, + unsigned long v2) { + mpq_set_ui(result.data(), v1, v2); + mpq_canonicalize(result.data()); } -inline void assign_components(gmp_rational& result, long v1, long v2) -{ - mpq_set_si(result.data(), v1, v2); - mpq_canonicalize(result.data()); +inline void assign_components(gmp_rational &result, long v1, long v2) { + mpq_set_si(result.data(), v1, v2); + mpq_canonicalize(result.data()); } -inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int const& v2) -{ - mpz_set(mpq_numref(result.data()), v1.data()); - mpz_set(mpq_denref(result.data()), v2.data()); - mpq_canonicalize(result.data()); +inline void assign_components(gmp_rational &result, gmp_int const &v1, + gmp_int const &v2) { + mpz_set(mpq_numref(result.data()), v1.data()); + mpz_set(mpq_denref(result.data()), v2.data()); + mpq_canonicalize(result.data()); } -inline std::size_t hash_value(const gmp_rational& val) -{ - std::size_t result = 0; - for(int i = 0; i < std::abs(val.data()[0]._mp_num._mp_size); ++i) - boost::hash_combine(result, val.data()[0]._mp_num._mp_d[i]); - for(int i = 0; i < std::abs(val.data()[0]._mp_den._mp_size); ++i) - boost::hash_combine(result, val.data()[0]._mp_den._mp_d[i]); - boost::hash_combine(result, val.data()[0]._mp_num._mp_size); - return result; +inline std::size_t hash_value(const gmp_rational &val) { + std::size_t result = 0; + for (int i = 0; i < std::abs(val.data()[0]._mp_num._mp_size); ++i) + boost::hash_combine(result, val.data()[0]._mp_num._mp_d[i]); + for (int i = 0; i < std::abs(val.data()[0]._mp_den._mp_size); ++i) + boost::hash_combine(result, val.data()[0]._mp_den._mp_d[i]); + boost::hash_combine(result, val.data()[0]._mp_num._mp_size); + return result; } // @@ -2212,750 +2004,922 @@ inline std::size_t hash_value(const gmp_rational& val) // template template -inline gmp_float::gmp_float(const gmp_float& o, typename enable_if_c::type*) -{ - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); - mpf_set(this->m_data, o.data()); +inline gmp_float::gmp_float( + const gmp_float &o, typename enable_if_c::type *) { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2( + Digits10 ? Digits10 : this->get_default_precision())); + mpf_set(this->m_data, o.data()); } template template -inline gmp_float::gmp_float(const gmp_float& o, typename disable_if_c::type*) -{ - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); - mpf_set(this->m_data, o.data()); +inline gmp_float::gmp_float( + const gmp_float &o, typename disable_if_c::type *) { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2( + Digits10 ? Digits10 : this->get_default_precision())); + mpf_set(this->m_data, o.data()); } template -inline gmp_float::gmp_float(const gmp_int& o) -{ - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); - mpf_set_z(this->data(), o.data()); +inline gmp_float::gmp_float(const gmp_int &o) { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2( + Digits10 ? Digits10 : this->get_default_precision())); + mpf_set_z(this->data(), o.data()); } template -inline gmp_float::gmp_float(const gmp_rational& o) -{ - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); - mpf_set_q(this->data(), o.data()); +inline gmp_float::gmp_float(const gmp_rational &o) { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2( + Digits10 ? Digits10 : this->get_default_precision())); + mpf_set_q(this->data(), o.data()); } template template -inline gmp_float& gmp_float::operator=(const gmp_float& o) -{ - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); - mpf_set(this->m_data, o.data()); - return *this; +inline gmp_float &gmp_float:: +operator=(const gmp_float &o) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2( + Digits10 ? Digits10 : this->get_default_precision())); + mpf_set(this->m_data, o.data()); + return *this; } template -inline gmp_float& gmp_float::operator=(const gmp_int& o) -{ - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); - mpf_set_z(this->data(), o.data()); - return *this; +inline gmp_float &gmp_float::operator=(const gmp_int &o) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2( + Digits10 ? Digits10 : this->get_default_precision())); + mpf_set_z(this->data(), o.data()); + return *this; } template -inline gmp_float& gmp_float::operator=(const gmp_rational& o) -{ - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); - mpf_set_q(this->data(), o.data()); - return *this; -} -inline gmp_float<0>::gmp_float(const gmp_int& o) -{ - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); - mpf_set_z(this->data(), o.data()); -} -inline gmp_float<0>::gmp_float(const gmp_rational& o) -{ - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); - mpf_set_q(this->data(), o.data()); -} -inline gmp_float<0>& gmp_float<0>::operator=(const gmp_int& o) -{ - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(this->get_default_precision())); - mpf_set_z(this->data(), o.data()); - return *this; -} -inline gmp_float<0>& gmp_float<0>::operator=(const gmp_rational& o) -{ - if(this->m_data[0]._mp_d == 0) - mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(this->get_default_precision())); - mpf_set_q(this->data(), o.data()); - return *this; -} -inline gmp_int::gmp_int(const gmp_rational& o) -{ - mpz_init(this->m_data); - mpz_set_q(this->m_data, o.data()); -} -inline gmp_int& gmp_int::operator=(const gmp_rational& o) -{ - if(this->m_data[0]._mp_d == 0) - mpz_init(this->m_data); - mpz_set_q(this->m_data, o.data()); - return *this; +inline gmp_float &gmp_float:: +operator=(const gmp_rational &o) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2( + Digits10 ? Digits10 : this->get_default_precision())); + mpf_set_q(this->data(), o.data()); + return *this; +} +inline gmp_float<0>::gmp_float(const gmp_int &o) { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_z(this->data(), o.data()); +} +inline gmp_float<0>::gmp_float(const gmp_rational &o) { + mpf_init2(this->m_data, + multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_q(this->data(), o.data()); +} +inline gmp_float<0> &gmp_float<0>::operator=(const gmp_int &o) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2( + this->get_default_precision())); + mpf_set_z(this->data(), o.data()); + return *this; +} +inline gmp_float<0> &gmp_float<0>::operator=(const gmp_rational &o) { + if (this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2( + this->get_default_precision())); + mpf_set_q(this->data(), o.data()); + return *this; +} +inline gmp_int::gmp_int(const gmp_rational &o) { + mpz_init(this->m_data); + mpz_set_q(this->m_data, o.data()); +} +inline gmp_int &gmp_int::operator=(const gmp_rational &o) { + if (this->m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_q(this->m_data, o.data()); + return *this; } -} //namespace backends +} // namespace backends +using boost::multiprecision::backends::gmp_float; using boost::multiprecision::backends::gmp_int; using boost::multiprecision::backends::gmp_rational; -using boost::multiprecision::backends::gmp_float; template -struct component_type > -{ - typedef number type; +struct component_type> { + typedef number type; }; template -inline number numerator(const number& val) -{ - number result; - mpz_set(result.backend().data(), (mpq_numref(val.backend().data()))); - return result; +inline number numerator(const number &val) { + number result; + mpz_set(result.backend().data(), (mpq_numref(val.backend().data()))); + return result; } template -inline number denominator(const number& val) -{ - number result; - mpz_set(result.backend().data(), (mpq_denref(val.backend().data()))); - return result; +inline number denominator(const number &val) { + number result; + mpz_set(result.backend().data(), (mpq_denref(val.backend().data()))); + return result; } -namespace detail{ +namespace detail { #ifdef BOOST_NO_SFINAE_EXPR -template<> -struct is_explicitly_convertible::type, gmp_int> : public mpl::true_ {}; -template<> -struct is_explicitly_convertible::type, gmp_int> : public mpl::true_ {}; -template -struct is_explicitly_convertible, gmp_int> : public mpl::true_ {}; -template<> +template <> +struct is_explicitly_convertible::type, gmp_int> + : public mpl::true_ {}; +template <> +struct is_explicitly_convertible::type, gmp_int> + : public mpl::true_ {}; +template +struct is_explicitly_convertible, gmp_int> + : public mpl::true_ {}; +template <> struct is_explicitly_convertible : public mpl::true_ {}; -template -struct is_explicitly_convertible, gmp_float > : public mpl::true_ {}; +template +struct is_explicitly_convertible, gmp_float> + : public mpl::true_ {}; #endif -template <> -struct digits2, et_on> > -{ - static long value() - { - return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision()); - } +template <> struct digits2, et_on>> { + static long value() { + return multiprecision::detail::digits10_2_2( + gmp_float<0>::default_precision()); + } }; -template <> -struct digits2, et_off> > -{ - static long value() - { - return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision()); - } +template <> struct digits2, et_off>> { + static long value() { + return multiprecision::detail::digits10_2_2( + gmp_float<0>::default_precision()); + } }; -template <> -struct digits2 >, et_on> > -{ - static long value() - { - return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision()); - } +template <> struct digits2>, et_on>> { + static long value() { + return multiprecision::detail::digits10_2_2( + gmp_float<0>::default_precision()); + } }; -template <> -struct digits2 >, et_off> > -{ - static long value() - { - return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision()); - } +template <> struct digits2>, et_off>> { + static long value() { + return multiprecision::detail::digits10_2_2( + gmp_float<0>::default_precision()); + } }; -} - -template<> -struct number_category::type> : public mpl::int_{}; -template<> -struct number_category::type> : public mpl::int_{}; -template<> -struct number_category >::type> : public mpl::int_{}; +} // namespace detail -namespace detail -{ - template<> - struct is_variable_precision > : public true_type {}; -} +template <> +struct number_category::type> + : public mpl::int_ {}; +template <> +struct number_category::type> + : public mpl::int_ {}; +template <> +struct number_category>::type> + : public mpl::int_ {}; +namespace detail { +template <> +struct is_variable_precision> : public true_type {}; +} // namespace detail -typedef number > mpf_float_50; -typedef number > mpf_float_100; -typedef number > mpf_float_500; -typedef number > mpf_float_1000; -typedef number > mpf_float; -typedef number mpz_int; -typedef number mpq_rational; +typedef number> mpf_float_50; +typedef number> mpf_float_100; +typedef number> mpf_float_500; +typedef number> mpf_float_1000; +typedef number> mpf_float; +typedef number mpz_int; +typedef number mpq_rational; -} // namespace multiprecision +} // namespace multiprecision -namespace math { namespace tools{ +namespace math { +namespace tools { - template <> - inline int digits() +template <> +inline int digits() #ifdef BOOST_MATH_NOEXCEPT - BOOST_NOEXCEPT + BOOST_NOEXCEPT #endif - { - return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision()); - } - template <> - inline int digits, boost::multiprecision::et_off> >() +{ + return multiprecision::detail::digits10_2_2( + boost::multiprecision::mpf_float::default_precision()); +} +template <> +inline int +digits, + boost::multiprecision::et_off>>() #ifdef BOOST_MATH_NOEXCEPT - BOOST_NOEXCEPT + BOOST_NOEXCEPT #endif - { - return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision()); - } - - template <> - inline boost::multiprecision::mpf_float - max_value() - { - boost::multiprecision::mpf_float result(0.5); - mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits::max)() / 64 + 1); - return result; - } - - template <> - inline boost::multiprecision::mpf_float - min_value() - { - boost::multiprecision::mpf_float result(0.5); - mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits::min)() / 64 + 1); - return result; - } - - template <> - inline boost::multiprecision::number, boost::multiprecision::et_off> - max_value, boost::multiprecision::et_off> >() - { - boost::multiprecision::number, boost::multiprecision::et_off> result(0.5); - mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits::max)() / 64 + 1); - return result; - } - - template <> - inline boost::multiprecision::number, boost::multiprecision::et_off> - min_value, boost::multiprecision::et_off> >() - { - boost::multiprecision::number, boost::multiprecision::et_off> result(0.5); - mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits::max)() / 64 + 1); - return result; - } - - template <> - inline int digits > >() +{ + return multiprecision::detail::digits10_2_2( + boost::multiprecision::mpf_float::default_precision()); +} + +template <> +inline boost::multiprecision::mpf_float +max_value() { + boost::multiprecision::mpf_float result(0.5); + mpf_mul_2exp(result.backend().data(), result.backend().data(), + (std::numeric_limits::max)() / 64 + 1); + return result; +} + +template <> +inline boost::multiprecision::mpf_float +min_value() { + boost::multiprecision::mpf_float result(0.5); + mpf_div_2exp(result.backend().data(), result.backend().data(), + (std::numeric_limits::min)() / 64 + 1); + return result; +} + +template <> +inline boost::multiprecision::number, + boost::multiprecision::et_off> +max_value, + boost::multiprecision::et_off>>() { + boost::multiprecision::number, + boost::multiprecision::et_off> + result(0.5); + mpf_mul_2exp(result.backend().data(), result.backend().data(), + (std::numeric_limits::max)() / 64 + 1); + return result; +} + +template <> +inline boost::multiprecision::number, + boost::multiprecision::et_off> +min_value, + boost::multiprecision::et_off>>() { + boost::multiprecision::number, + boost::multiprecision::et_off> + result(0.5); + mpf_div_2exp(result.backend().data(), result.backend().data(), + (std::numeric_limits::max)() / 64 + 1); + return result; +} + +template <> +inline int +digits>>() #ifdef BOOST_MATH_NOEXCEPT - BOOST_NOEXCEPT + BOOST_NOEXCEPT #endif - { - return multiprecision::detail::digits10_2_2(boost::multiprecision::number >::default_precision()); - } - template <> - inline int digits >, boost::multiprecision::et_off> >() +{ + return multiprecision::detail::digits10_2_2( + boost::multiprecision::number>:: + default_precision()); +} +template <> +inline int digits>, + boost::multiprecision::et_off>>() #ifdef BOOST_MATH_NOEXCEPT - BOOST_NOEXCEPT + BOOST_NOEXCEPT #endif - { - return multiprecision::detail::digits10_2_2(boost::multiprecision::number >::default_precision()); - } - - template <> - inline boost::multiprecision::number > - max_value > >() - { - return max_value().backend(); - } - - template <> - inline boost::multiprecision::number > - min_value > >() - { - return min_value().backend(); - } +{ + return multiprecision::detail::digits10_2_2( + boost::multiprecision::number>:: + default_precision()); +} - template <> - inline boost::multiprecision::number >, boost::multiprecision::et_off> - max_value >, boost::multiprecision::et_off> >() - { - return max_value().backend(); - } +template <> +inline boost::multiprecision::number> +max_value>>() { + return max_value().backend(); +} - template <> - inline boost::multiprecision::number >, boost::multiprecision::et_off> - min_value >, boost::multiprecision::et_off> >() - { - return min_value().backend(); - } +template <> +inline boost::multiprecision::number> +min_value>>() { + return min_value().backend(); +} +template <> +inline boost::multiprecision::number< + boost::multiprecision::debug_adaptor>, + boost::multiprecision::et_off> +max_value>, + boost::multiprecision::et_off>>() { + return max_value().backend(); +} -}} // namespaces math::tools +template <> +inline boost::multiprecision::number< + boost::multiprecision::debug_adaptor>, + boost::multiprecision::et_off> +min_value>, + boost::multiprecision::et_off>>() { + return min_value().backend(); +} +} // namespace tools +} // namespace math -} // namespace boost +} // namespace boost -namespace std{ +namespace std { // -// numeric_limits [partial] specializations for the types declared in this header: +// numeric_limits [partial] specializations for the types declared in this +// header: // -template -class numeric_limits, ExpressionTemplates> > -{ - typedef boost::multiprecision::number, ExpressionTemplates> number_type; +template +class numeric_limits, ExpressionTemplates>> { + typedef boost::multiprecision::number< + boost::multiprecision::gmp_float, ExpressionTemplates> + number_type; + public: - BOOST_STATIC_CONSTEXPR bool is_specialized = true; - // - // min and max values chosen so as to not cause segfaults when calling - // mpf_get_str on 64-bit Linux builds. Possibly we could use larger - // exponent values elsewhere. - // - static number_type (min)() - { - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - value.first = true; - value.second = 1; - mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits::max)() / 64 + 1); - } - return value.second; - } - static number_type (max)() - { - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - value.first = true; - value.second = 1; - mpf_mul_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits::max)() / 64 + 1); - } - return value.second; - } - BOOST_STATIC_CONSTEXPR number_type lowest() - { - return -(max)(); - } - BOOST_STATIC_CONSTEXPR int digits = static_cast((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301L ? 2 : 1)); - BOOST_STATIC_CONSTEXPR int digits10 = Digits10; - // Have to allow for a possible extra limb inside the gmp data structure: - BOOST_STATIC_CONSTEXPR int max_digits10 = Digits10 + 3 + ((GMP_LIMB_BITS * 301L) / 1000L); - BOOST_STATIC_CONSTEXPR bool is_signed = true; - BOOST_STATIC_CONSTEXPR bool is_integer = false; - BOOST_STATIC_CONSTEXPR bool is_exact = false; - BOOST_STATIC_CONSTEXPR int radix = 2; - static number_type epsilon() - { - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - value.first = true; - value.second = 1; - mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits::digits - 1); - } - return value.second; - } - // What value should this be???? - static number_type round_error() - { - // returns epsilon/2 - initializer.do_nothing(); - static std::pair value; - if(!value.first) - { - value.first = true; - value.second = 1; - } - return value.second; - } - BOOST_STATIC_CONSTEXPR long min_exponent = LONG_MIN; - BOOST_STATIC_CONSTEXPR long min_exponent10 = (LONG_MIN / 1000) * 301L; - BOOST_STATIC_CONSTEXPR long max_exponent = LONG_MAX; - BOOST_STATIC_CONSTEXPR long max_exponent10 = (LONG_MAX / 1000) * 301L; - BOOST_STATIC_CONSTEXPR bool has_infinity = false; - BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; - BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; - BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; - BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; - BOOST_STATIC_CONSTEXPR number_type infinity() { return number_type(); } - BOOST_STATIC_CONSTEXPR number_type quiet_NaN() { return number_type(); } - BOOST_STATIC_CONSTEXPR number_type signaling_NaN() { return number_type(); } - BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(); } - BOOST_STATIC_CONSTEXPR bool is_iec559 = false; - BOOST_STATIC_CONSTEXPR bool is_bounded = true; - BOOST_STATIC_CONSTEXPR bool is_modulo = false; - BOOST_STATIC_CONSTEXPR bool traps = true; - BOOST_STATIC_CONSTEXPR bool tinyness_before = false; - BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate; + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + // + // min and max values chosen so as to not cause segfaults when calling + // mpf_get_str on 64-bit Linux builds. Possibly we could use larger + // exponent values elsewhere. + // + static number_type(min)() { + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + value.first = true; + value.second = 1; + mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), + (std::numeric_limits::max)() / 64 + 1); + } + return value.second; + } + static number_type(max)() { + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + value.first = true; + value.second = 1; + mpf_mul_2exp(value.second.backend().data(), value.second.backend().data(), + (std::numeric_limits::max)() / 64 + 1); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR number_type lowest() { return -(max)(); } + BOOST_STATIC_CONSTEXPR int digits = static_cast( + (Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301L ? 2 : 1)); + BOOST_STATIC_CONSTEXPR int digits10 = Digits10; + // Have to allow for a possible extra limb inside the gmp data structure: + BOOST_STATIC_CONSTEXPR int max_digits10 = + Digits10 + 3 + ((GMP_LIMB_BITS * 301L) / 1000L); + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = false; + BOOST_STATIC_CONSTEXPR int radix = 2; + static number_type epsilon() { + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + value.first = true; + value.second = 1; + mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), + std::numeric_limits::digits - 1); + } + return value.second; + } + // What value should this be???? + static number_type round_error() { + // returns epsilon/2 + initializer.do_nothing(); + static std::pair value; + if (!value.first) { + value.first = true; + value.second = 1; + } + return value.second; + } + BOOST_STATIC_CONSTEXPR long min_exponent = LONG_MIN; + BOOST_STATIC_CONSTEXPR long min_exponent10 = (LONG_MIN / 1000) * 301L; + BOOST_STATIC_CONSTEXPR long max_exponent = LONG_MAX; + BOOST_STATIC_CONSTEXPR long max_exponent10 = (LONG_MAX / 1000) * 301L; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + BOOST_STATIC_CONSTEXPR number_type infinity() { return number_type(); } + BOOST_STATIC_CONSTEXPR number_type quiet_NaN() { return number_type(); } + BOOST_STATIC_CONSTEXPR number_type signaling_NaN() { return number_type(); } + BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = true; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = true; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate; private: - struct data_initializer - { - data_initializer() - { - std::numeric_limits > >::epsilon(); - std::numeric_limits > >::round_error(); - (std::numeric_limits > >::min)(); - (std::numeric_limits > >::max)(); - } - void do_nothing()const{} - }; - static const data_initializer initializer; + struct data_initializer { + data_initializer() { + std::numeric_limits>>::epsilon(); + std::numeric_limits>>::round_error(); + (std::numeric_limits>>::min)(); + (std::numeric_limits>>::max)(); + } + void do_nothing() const {} + }; + static const data_initializer initializer; }; -template -const typename numeric_limits, ExpressionTemplates> >::data_initializer numeric_limits, ExpressionTemplates> >::initializer; +template +const typename numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::data_initializer + numeric_limits, + ExpressionTemplates>>::initializer; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; -template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; -template -BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::min_exponent; -template -BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::min_exponent10; -template -BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::max_exponent; -template -BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::max_exponent10; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; -template -BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; -template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; -template -BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::radix; +template +BOOST_CONSTEXPR_OR_CONST long numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST long numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST long numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST long numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::round_style; #endif -template -class numeric_limits, ExpressionTemplates> > -{ - typedef boost::multiprecision::number, ExpressionTemplates> number_type; +template +class numeric_limits, ExpressionTemplates>> { + typedef boost::multiprecision::number, + ExpressionTemplates> + number_type; + public: - BOOST_STATIC_CONSTEXPR bool is_specialized = false; - static number_type (min)() { return number_type(); } - static number_type (max)() { return number_type(); } - static number_type lowest() { return number_type(); } - BOOST_STATIC_CONSTEXPR int digits = 0; - BOOST_STATIC_CONSTEXPR int digits10 = 0; - BOOST_STATIC_CONSTEXPR int max_digits10 = 0; - BOOST_STATIC_CONSTEXPR bool is_signed = false; - BOOST_STATIC_CONSTEXPR bool is_integer = false; - BOOST_STATIC_CONSTEXPR bool is_exact = false; - BOOST_STATIC_CONSTEXPR int radix = 0; - static number_type epsilon() { return number_type(); } - static number_type round_error() { return number_type(); } - BOOST_STATIC_CONSTEXPR int min_exponent = 0; - BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; - BOOST_STATIC_CONSTEXPR int max_exponent = 0; - BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; - BOOST_STATIC_CONSTEXPR bool has_infinity = false; - BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; - BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; - BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; - BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; - static number_type infinity() { return number_type(); } - static number_type quiet_NaN() { return number_type(); } - static number_type signaling_NaN() { return number_type(); } - static number_type denorm_min() { return number_type(); } - BOOST_STATIC_CONSTEXPR bool is_iec559 = false; - BOOST_STATIC_CONSTEXPR bool is_bounded = false; - BOOST_STATIC_CONSTEXPR bool is_modulo = false; - BOOST_STATIC_CONSTEXPR bool traps = false; - BOOST_STATIC_CONSTEXPR bool tinyness_before = false; - BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate; + BOOST_STATIC_CONSTEXPR bool is_specialized = false; + static number_type(min)() { return number_type(); } + static number_type(max)() { return number_type(); } + static number_type lowest() { return number_type(); } + BOOST_STATIC_CONSTEXPR int digits = 0; + BOOST_STATIC_CONSTEXPR int digits10 = 0; + BOOST_STATIC_CONSTEXPR int max_digits10 = 0; + BOOST_STATIC_CONSTEXPR bool is_signed = false; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = false; + BOOST_STATIC_CONSTEXPR int radix = 0; + static number_type epsilon() { return number_type(); } + static number_type round_error() { return number_type(); } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() { return number_type(); } + static number_type quiet_NaN() { return number_type(); } + static number_type signaling_NaN() { return number_type(); } + static number_type denorm_min() { return number_type(); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = false; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate; }; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::digits; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::digits10; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::max_digits10; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::is_signed; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::is_integer; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::is_exact; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::radix; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent; +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::min_exponent; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::min_exponent10; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent; +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::max_exponent; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates>>::max_exponent10; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::has_infinity; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::has_quiet_NaN; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number, + ExpressionTemplates>>::has_signaling_NaN; template -BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; +BOOST_CONSTEXPR_OR_CONST float_denorm_style + numeric_limits, ExpressionTemplates>>::has_denorm; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::has_denorm_loss; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::is_iec559; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::is_bounded; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::is_modulo; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::traps; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates>>::tinyness_before; template -BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; +BOOST_CONSTEXPR_OR_CONST float_round_style + numeric_limits, ExpressionTemplates>>::round_style; #endif -template -class numeric_limits > -{ - typedef boost::multiprecision::number number_type; +template +class numeric_limits> { + typedef boost::multiprecision::number + number_type; + public: - BOOST_STATIC_CONSTEXPR bool is_specialized = true; - // - // Largest and smallest numbers are bounded only by available memory, set - // to zero: - // - static number_type (min)() - { - return number_type(); - } - static number_type (max)() - { - return number_type(); - } - static number_type lowest() { return (min)(); } - BOOST_STATIC_CONSTEXPR int digits = INT_MAX; - BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; - BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 3; - BOOST_STATIC_CONSTEXPR bool is_signed = true; - BOOST_STATIC_CONSTEXPR bool is_integer = true; - BOOST_STATIC_CONSTEXPR bool is_exact = true; - BOOST_STATIC_CONSTEXPR int radix = 2; - static number_type epsilon() { return number_type(); } - static number_type round_error() { return number_type(); } - BOOST_STATIC_CONSTEXPR int min_exponent = 0; - BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; - BOOST_STATIC_CONSTEXPR int max_exponent = 0; - BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; - BOOST_STATIC_CONSTEXPR bool has_infinity = false; - BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; - BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; - BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; - BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; - static number_type infinity() { return number_type(); } - static number_type quiet_NaN() { return number_type(); } - static number_type signaling_NaN() { return number_type(); } - static number_type denorm_min() { return number_type(); } - BOOST_STATIC_CONSTEXPR bool is_iec559 = false; - BOOST_STATIC_CONSTEXPR bool is_bounded = false; - BOOST_STATIC_CONSTEXPR bool is_modulo = false; - BOOST_STATIC_CONSTEXPR bool traps = false; - BOOST_STATIC_CONSTEXPR bool tinyness_before = false; - BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + // + // Largest and smallest numbers are bounded only by available memory, set + // to zero: + // + static number_type(min)() { return number_type(); } + static number_type(max)() { return number_type(); } + static number_type lowest() { return (min)(); } + BOOST_STATIC_CONSTEXPR int digits = INT_MAX; + BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; + BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 3; + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = true; + BOOST_STATIC_CONSTEXPR bool is_exact = true; + BOOST_STATIC_CONSTEXPR int radix = 2; + static number_type epsilon() { return number_type(); } + static number_type round_error() { return number_type(); } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() { return number_type(); } + static number_type quiet_NaN() { return number_type(); } + static number_type signaling_NaN() { return number_type(); } + static number_type denorm_min() { return number_type(); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = false; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; }; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::digits; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::digits10; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_digits10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::max_digits10; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_signed; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_signed; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_integer; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_integer; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_exact; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_exact; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::radix; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::radix; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::min_exponent; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::min_exponent10; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::max_exponent; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::max_exponent10; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_infinity; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::has_infinity; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_quiet_NaN; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::has_quiet_NaN; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_signaling_NaN; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::has_signaling_NaN; template -BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits >::has_denorm; +BOOST_CONSTEXPR_OR_CONST float_denorm_style + numeric_limits>::has_denorm; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_denorm_loss; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::has_denorm_loss; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_iec559; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_iec559; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_bounded; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_bounded; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_modulo; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_modulo; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::traps; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::traps; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::tinyness_before; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::tinyness_before; template -BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits >::round_style; +BOOST_CONSTEXPR_OR_CONST float_round_style + numeric_limits>::round_style; #endif -template -class numeric_limits > -{ - typedef boost::multiprecision::number number_type; +template +class numeric_limits> { + typedef boost::multiprecision::number + number_type; + public: - BOOST_STATIC_CONSTEXPR bool is_specialized = true; - // - // Largest and smallest numbers are bounded only by available memory, set - // to zero: - // - static number_type (min)() - { - return number_type(); - } - static number_type (max)() - { - return number_type(); - } - static number_type lowest() { return (min)(); } - // Digits are unbounded, use zero for now: - BOOST_STATIC_CONSTEXPR int digits = INT_MAX; - BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; - BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 3; - BOOST_STATIC_CONSTEXPR bool is_signed = true; - BOOST_STATIC_CONSTEXPR bool is_integer = false; - BOOST_STATIC_CONSTEXPR bool is_exact = true; - BOOST_STATIC_CONSTEXPR int radix = 2; - static number_type epsilon() { return number_type(); } - static number_type round_error() { return number_type(); } - BOOST_STATIC_CONSTEXPR int min_exponent = 0; - BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; - BOOST_STATIC_CONSTEXPR int max_exponent = 0; - BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; - BOOST_STATIC_CONSTEXPR bool has_infinity = false; - BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; - BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; - BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; - BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; - static number_type infinity() { return number_type(); } - static number_type quiet_NaN() { return number_type(); } - static number_type signaling_NaN() { return number_type(); } - static number_type denorm_min() { return number_type(); } - BOOST_STATIC_CONSTEXPR bool is_iec559 = false; - BOOST_STATIC_CONSTEXPR bool is_bounded = false; - BOOST_STATIC_CONSTEXPR bool is_modulo = false; - BOOST_STATIC_CONSTEXPR bool traps = false; - BOOST_STATIC_CONSTEXPR bool tinyness_before = false; - BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + // + // Largest and smallest numbers are bounded only by available memory, set + // to zero: + // + static number_type(min)() { return number_type(); } + static number_type(max)() { return number_type(); } + static number_type lowest() { return (min)(); } + // Digits are unbounded, use zero for now: + BOOST_STATIC_CONSTEXPR int digits = INT_MAX; + BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; + BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 3; + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = true; + BOOST_STATIC_CONSTEXPR int radix = 2; + static number_type epsilon() { return number_type(); } + static number_type round_error() { return number_type(); } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() { return number_type(); } + static number_type quiet_NaN() { return number_type(); } + static number_type signaling_NaN() { return number_type(); } + static number_type denorm_min() { return number_type(); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = false; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; }; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::digits; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::digits10; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_digits10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::max_digits10; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_signed; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_signed; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_integer; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_integer; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_exact; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_exact; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::radix; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::radix; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::min_exponent; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::min_exponent10; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::max_exponent; template -BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent10; +BOOST_CONSTEXPR_OR_CONST int numeric_limits>::max_exponent10; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_infinity; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::has_infinity; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_quiet_NaN; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::has_quiet_NaN; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_signaling_NaN; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits< + boost::multiprecision::number>::has_signaling_NaN; template -BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits >::has_denorm; +BOOST_CONSTEXPR_OR_CONST float_denorm_style + numeric_limits>::has_denorm; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_denorm_loss; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::has_denorm_loss; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_iec559; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_iec559; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_bounded; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_bounded; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_modulo; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::is_modulo; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::traps; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::traps; template -BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::tinyness_before; +BOOST_CONSTEXPR_OR_CONST bool numeric_limits>::tinyness_before; template -BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits >::round_style; +BOOST_CONSTEXPR_OR_CONST float_round_style + numeric_limits>::round_style; #endif diff --git a/include/boost/multiprecision/integer.hpp b/include/boost/multiprecision/integer.hpp index f2b43c320..5f82224b7 100644 --- a/include/boost/multiprecision/integer.hpp +++ b/include/boost/multiprecision/integer.hpp @@ -9,243 +9,234 @@ #include #include -namespace boost{ -namespace multiprecision{ +namespace boost { +namespace multiprecision { template -typename enable_if_c::value && is_integral::value, Integer&>::type - multiply(Integer& result, const I2& a, const I2& b) -{ - return result = static_cast(a) * static_cast(b); +typename enable_if_c::value && is_integral::value, + Integer &>::type +multiply(Integer &result, const I2 &a, const I2 &b) { + return result = static_cast(a) * static_cast(b); } template -typename enable_if_c::value && is_integral::value, Integer&>::type - add(Integer& result, const I2& a, const I2& b) -{ - return result = static_cast(a) + static_cast(b); +typename enable_if_c::value && is_integral::value, + Integer &>::type +add(Integer &result, const I2 &a, const I2 &b) { + return result = static_cast(a) + static_cast(b); } template -typename enable_if_c::value && is_integral::value, Integer&>::type - subtract(Integer& result, const I2& a, const I2& b) -{ - return result = static_cast(a) - static_cast(b); +typename enable_if_c::value && is_integral::value, + Integer &>::type +subtract(Integer &result, const I2 &a, const I2 &b) { + return result = static_cast(a) - static_cast(b); } template -typename enable_if_c::value>::type divide_qr(const Integer& x, const Integer& y, Integer& q, Integer& r) -{ - q = x / y; - r = x % y; +typename enable_if_c::value>::type +divide_qr(const Integer &x, const Integer &y, Integer &q, Integer &r) { + q = x / y; + r = x % y; } template -typename enable_if_c::value && is_integral::value, I2>::type integer_modulus(const I1& x, I2 val) -{ - return static_cast(x % val); +typename enable_if_c::value && is_integral::value, I2>::type +integer_modulus(const I1 &x, I2 val) { + return static_cast(x % val); } -namespace detail{ +namespace detail { // // Figure out the kind of integer that has twice as many bits as some builtin // integer type I. Use a native type if we can (including types which may not -// be recognised by boost::int_t because they're larger than boost::long_long_type), -// otherwise synthesize a cpp_int to do the job. +// be recognised by boost::int_t because they're larger than +// boost::long_long_type), otherwise synthesize a cpp_int to do the job. // -template -struct double_integer -{ - static const unsigned int_t_digits = - 2 * sizeof(I) <= sizeof(boost::long_long_type) ? std::numeric_limits::digits * 2 : 1; +template struct double_integer { + static const unsigned int_t_digits = + 2 * sizeof(I) <= sizeof(boost::long_long_type) + ? std::numeric_limits::digits * 2 + : 1; - typedef typename mpl::if_c< + typedef typename mpl::if_c< 2 * sizeof(I) <= sizeof(boost::long_long_type), + typename mpl::if_c::value, + typename boost::int_t::least, + typename boost::uint_t::least>::type, typename mpl::if_c< - is_signed::value, - typename boost::int_t::least, - typename boost::uint_t::least - >::type, - typename mpl::if_c< - 2 * sizeof(I) <= sizeof(double_limb_type), - typename mpl::if_c< - is_signed::value, - signed_double_limb_type, - double_limb_type - >::type, - number::value ? signed_magnitude : unsigned_magnitude), unchecked, void> > - >::type - >::type type; + 2 * sizeof(I) <= sizeof(double_limb_type), + typename mpl::if_c::value, signed_double_limb_type, + double_limb_type>::type, + number::value ? signed_magnitude : unsigned_magnitude), + unchecked, void>>>::type>::type type; }; -} +} // namespace detail template -typename enable_if_c::value && is_unsigned::value && is_integral::value, I1>::type - powm(const I1& a, I2 b, I3 c) -{ - typedef typename detail::double_integer::type double_type; - - I1 x(1), y(a); - double_type result; - - while(b > 0) - { - if(b & 1) - { - multiply(result, x, y); - x = integer_modulus(result, c); - } - multiply(result, y, y); - y = integer_modulus(result, c); - b >>= 1; - } - return x % c; +typename enable_if_c::value && is_unsigned::value && + is_integral::value, + I1>::type +powm(const I1 &a, I2 b, I3 c) { + typedef typename detail::double_integer::type double_type; + + I1 x(1), y(a); + double_type result; + + while (b > 0) { + if (b & 1) { + multiply(result, x, y); + x = integer_modulus(result, c); + } + multiply(result, y, y); + y = integer_modulus(result, c); + b >>= 1; + } + return x % c; } template -inline typename enable_if_c::value && is_signed::value && is_integral::value, I1>::type - powm(const I1& a, I2 b, I3 c) -{ - if(b < 0) - { - BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); - } - return powm(a, static_cast::type>(b), c); +inline typename enable_if_c::value && is_signed::value && + is_integral::value, + I1>::type +powm(const I1 &a, I2 b, I3 c) { + if (b < 0) { + BOOST_THROW_EXCEPTION( + std::runtime_error("powm requires a positive exponent.")); + } + return powm(a, static_cast::type>(b), c); } template -typename enable_if_c::value, unsigned>::type lsb(const Integer& val) -{ - if(val <= 0) - { - if(val == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - else - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - } - return detail::find_lsb(val); +typename enable_if_c::value, unsigned>::type +lsb(const Integer &val) { + if (val <= 0) { + if (val == 0) { + BOOST_THROW_EXCEPTION( + std::range_error("No bits were set in the operand.")); + } else { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + } + return detail::find_lsb(val); } template -typename enable_if_c::value, unsigned>::type msb(Integer val) -{ - if(val <= 0) - { - if(val == 0) - { - BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); - } - else - { - BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); - } - } - return detail::find_msb(val); +typename enable_if_c::value, unsigned>::type +msb(Integer val) { + if (val <= 0) { + if (val == 0) { + BOOST_THROW_EXCEPTION( + std::range_error("No bits were set in the operand.")); + } else { + BOOST_THROW_EXCEPTION( + std::range_error("Testing individual bits in negative values is not " + "supported - results are undefined.")); + } + } + return detail::find_msb(val); } template -typename enable_if_c::value, bool>::type bit_test(const Integer& val, unsigned index) -{ - Integer mask = 1; - if(index >= sizeof(Integer) * CHAR_BIT) - return 0; - if(index) - mask <<= index; - return val & mask ? true : false; +typename enable_if_c::value, bool>::type +bit_test(const Integer &val, unsigned index) { + Integer mask = 1; + if (index >= sizeof(Integer) * CHAR_BIT) + return 0; + if (index) + mask <<= index; + return val & mask ? true : false; } template -typename enable_if_c::value, Integer&>::type bit_set(Integer& val, unsigned index) -{ - Integer mask = 1; - if(index >= sizeof(Integer) * CHAR_BIT) - return val; - if(index) - mask <<= index; - val |= mask; - return val; +typename enable_if_c::value, Integer &>::type +bit_set(Integer &val, unsigned index) { + Integer mask = 1; + if (index >= sizeof(Integer) * CHAR_BIT) + return val; + if (index) + mask <<= index; + val |= mask; + return val; } template -typename enable_if_c::value, Integer&>::type bit_unset(Integer& val, unsigned index) -{ - Integer mask = 1; - if(index >= sizeof(Integer) * CHAR_BIT) - return val; - if(index) - mask <<= index; - val &= ~mask; - return val; +typename enable_if_c::value, Integer &>::type +bit_unset(Integer &val, unsigned index) { + Integer mask = 1; + if (index >= sizeof(Integer) * CHAR_BIT) + return val; + if (index) + mask <<= index; + val &= ~mask; + return val; } template -typename enable_if_c::value, Integer&>::type bit_flip(Integer& val, unsigned index) -{ - Integer mask = 1; - if(index >= sizeof(Integer) * CHAR_BIT) - return val; - if(index) - mask <<= index; - val ^= mask; - return val; +typename enable_if_c::value, Integer &>::type +bit_flip(Integer &val, unsigned index) { + Integer mask = 1; + if (index >= sizeof(Integer) * CHAR_BIT) + return val; + if (index) + mask <<= index; + val ^= mask; + return val; } template -typename enable_if_c::value, Integer>::type sqrt(const Integer& x, Integer& r) -{ - // - // This is slow bit-by-bit integer square root, see for example - // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29 - // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf - // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented - // at some point. - // - Integer s = 0; - if(x == 0) - { - r = 0; - return s; - } - int g = msb(x); - if(g == 0) - { - r = 1; - return s; - } - - Integer t = 0; - r = x; - g /= 2; - bit_set(s, g); - bit_set(t, 2 * g); - r = x - t; - --g; - do - { - t = s; - t <<= g + 1; - bit_set(t, 2 * g); - if(t <= r) - { - bit_set(s, g); - r -= t; - } - --g; - } - while(g >= 0); - return s; +typename enable_if_c::value, Integer>::type +sqrt(const Integer &x, Integer &r) { + // + // This is slow bit-by-bit integer square root, see for example + // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29 + // There are better methods such as + // http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf and + // http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be + // implemented at some point. + // + Integer s = 0; + if (x == 0) { + r = 0; + return s; + } + int g = msb(x); + if (g == 0) { + r = 1; + return s; + } + + Integer t = 0; + r = x; + g /= 2; + bit_set(s, g); + bit_set(t, 2 * g); + r = x - t; + --g; + do { + t = s; + t <<= g + 1; + bit_set(t, 2 * g); + if (t <= r) { + bit_set(s, g); + r -= t; + } + --g; + } while (g >= 0); + return s; } template -typename enable_if_c::value, Integer>::type sqrt(const Integer& x) -{ - Integer r; - return sqrt(x, r); +typename enable_if_c::value, Integer>::type +sqrt(const Integer &x) { + Integer r; + return sqrt(x, r); } -}} // namespaces +} // namespace multiprecision +} // namespace boost #endif diff --git a/include/boost/multiprecision/logged_adaptor.hpp b/include/boost/multiprecision/logged_adaptor.hpp index 014a117d3..0be269e62 100644 --- a/include/boost/multiprecision/logged_adaptor.hpp +++ b/include/boost/multiprecision/logged_adaptor.hpp @@ -6,294 +6,297 @@ #ifndef BOOST_MATH_LOGGED_ADAPTER_HPP #define BOOST_MATH_LOGGED_ADAPTER_HPP -#include #include +#include -namespace boost{ -namespace multiprecision{ +namespace boost { +namespace multiprecision { template -inline void log_postfix_event(const Backend&, const char* /*event_description*/) -{ -} +inline void log_postfix_event(const Backend &, + const char * /*event_description*/) {} template -inline void log_postfix_event(const Backend&, const T&, const char* /*event_description*/) -{ -} +inline void log_postfix_event(const Backend &, const T &, + const char * /*event_description*/) {} template -inline void log_prefix_event(const Backend&, const char* /*event_description*/) -{ -} +inline void log_prefix_event(const Backend &, + const char * /*event_description*/) {} template -inline void log_prefix_event(const Backend&, const T&, const char* /*event_description*/) -{ -} +inline void log_prefix_event(const Backend &, const T &, + const char * /*event_description*/) {} template -inline void log_prefix_event(const Backend&, const T&, const U&, const char* /*event_description*/) -{ -} +inline void log_prefix_event(const Backend &, const T &, const U &, + const char * /*event_description*/) {} template -inline void log_prefix_event(const Backend&, const T&, const U&, const V&, const char* /*event_description*/) -{ -} +inline void log_prefix_event(const Backend &, const T &, const U &, const V &, + const char * /*event_description*/) {} -namespace backends{ +namespace backends { -template -struct logged_adaptor -{ - typedef typename Backend::signed_types signed_types; - typedef typename Backend::unsigned_types unsigned_types; - typedef typename Backend::float_types float_types; - typedef typename extract_exponent_type< - Backend, number_category::value>::type exponent_type; +template struct logged_adaptor { + typedef typename Backend::signed_types signed_types; + typedef typename Backend::unsigned_types unsigned_types; + typedef typename Backend::float_types float_types; + typedef typename extract_exponent_type< + Backend, number_category::value>::type exponent_type; private: + Backend m_value; - Backend m_value; public: - logged_adaptor() - { - log_postfix_event(m_value, "Default construct"); - } - logged_adaptor(const logged_adaptor& o) - { - log_prefix_event(m_value, o.value(), "Copy construct"); - m_value = o.m_value; - log_postfix_event(m_value, "Copy construct"); - } + logged_adaptor() { log_postfix_event(m_value, "Default construct"); } + logged_adaptor(const logged_adaptor &o) { + log_prefix_event(m_value, o.value(), "Copy construct"); + m_value = o.m_value; + log_postfix_event(m_value, "Copy construct"); + } #ifndef BOOST_NO_RVALUE_REFERENCES - logged_adaptor(logged_adaptor&& o) - { - log_prefix_event(m_value, o.value(), "Move construct"); - m_value = static_cast(o.m_value); - log_postfix_event(m_value, "Move construct"); - } - logged_adaptor& operator = (logged_adaptor&& o) - { - log_prefix_event(m_value, o.value(), "Move Assignment"); - m_value = static_cast(o.m_value); - log_postfix_event(m_value, "Move construct"); - return *this; - } + logged_adaptor(logged_adaptor &&o) { + log_prefix_event(m_value, o.value(), "Move construct"); + m_value = static_cast(o.m_value); + log_postfix_event(m_value, "Move construct"); + } + logged_adaptor &operator=(logged_adaptor &&o) { + log_prefix_event(m_value, o.value(), "Move Assignment"); + m_value = static_cast(o.m_value); + log_postfix_event(m_value, "Move construct"); + return *this; + } #endif - logged_adaptor& operator = (const logged_adaptor& o) - { - log_prefix_event(m_value, o.value(), "Assignment"); - m_value = o.m_value; - log_postfix_event(m_value, "Copy construct"); - return *this; - } - template - logged_adaptor(const T& i, const typename enable_if_c::value>::type* = 0) - : m_value(i) - { - log_postfix_event(m_value, "construct from arithmetic type"); - } - template - logged_adaptor(const logged_adaptor& i, const typename enable_if_c::value>::type* = 0) - : m_value(i.value()) - { - log_postfix_event(m_value, "construct from arithmetic type"); - } - template - typename enable_if_c::value || is_convertible::value, logged_adaptor&>::type operator = (const T& i) - { - log_prefix_event(m_value, i, "Assignment from arithmetic type"); - m_value = i; - log_postfix_event(m_value, "Assignment from arithmetic type"); - return *this; - } - logged_adaptor& operator = (const char* s) - { - log_prefix_event(m_value, s, "Assignment from string type"); - m_value = s; - log_postfix_event(m_value, "Assignment from string type"); - return *this; - } - void swap(logged_adaptor& o) - { - log_prefix_event(m_value, o.value(), "swap"); - std::swap(m_value, o.value()); - log_postfix_event(m_value, "swap"); - } - std::string str(std::streamsize digits, std::ios_base::fmtflags f)const - { - log_prefix_event(m_value, "Conversion to string"); - std::string s = m_value.str(digits, f); - log_postfix_event(m_value, s, "Conversion to string"); - return s; - } - void negate() - { - log_prefix_event(m_value, "negate"); - m_value.negate(); - log_postfix_event(m_value, "negate"); - } - int compare(const logged_adaptor& o)const - { - log_prefix_event(m_value, o.value(), "compare"); - int r = m_value.compare(o.value()); - log_postfix_event(m_value, r, "compare"); - return r; - } - template - int compare(const T& i)const - { - log_prefix_event(m_value, i, "compare"); - int r = m_value.compare(i); - log_postfix_event(m_value, r, "compare"); - return r; - } - Backend& value() - { - return m_value; - } - const Backend& value()const - { - return m_value; - } - template - void serialize(Archive& ar, const unsigned int /*version*/) - { - log_prefix_event(m_value, "serialize"); - ar & boost::serialization::make_nvp("value", m_value); - log_postfix_event(m_value, "serialize"); - } - static unsigned default_precision() BOOST_NOEXCEPT - { - return Backend::default_precision(); - } - static void default_precision(unsigned v) BOOST_NOEXCEPT - { - Backend::default_precision(v); - } - unsigned precision()const BOOST_NOEXCEPT - { - return value().precision(); - } - void precision(unsigned digits10) BOOST_NOEXCEPT - { - value().precision(digits10); - } + logged_adaptor &operator=(const logged_adaptor &o) { + log_prefix_event(m_value, o.value(), "Assignment"); + m_value = o.m_value; + log_postfix_event(m_value, "Copy construct"); + return *this; + } + template + logged_adaptor( + const T &i, + const typename enable_if_c::value>::type * = 0) + : m_value(i) { + log_postfix_event(m_value, "construct from arithmetic type"); + } + template + logged_adaptor( + const logged_adaptor &i, + const typename enable_if_c::value>::type * = 0) + : m_value(i.value()) { + log_postfix_event(m_value, "construct from arithmetic type"); + } + template + typename enable_if_c::value || + is_convertible::value, + logged_adaptor &>::type + operator=(const T &i) { + log_prefix_event(m_value, i, "Assignment from arithmetic type"); + m_value = i; + log_postfix_event(m_value, "Assignment from arithmetic type"); + return *this; + } + logged_adaptor &operator=(const char *s) { + log_prefix_event(m_value, s, "Assignment from string type"); + m_value = s; + log_postfix_event(m_value, "Assignment from string type"); + return *this; + } + void swap(logged_adaptor &o) { + log_prefix_event(m_value, o.value(), "swap"); + std::swap(m_value, o.value()); + log_postfix_event(m_value, "swap"); + } + std::string str(std::streamsize digits, std::ios_base::fmtflags f) const { + log_prefix_event(m_value, "Conversion to string"); + std::string s = m_value.str(digits, f); + log_postfix_event(m_value, s, "Conversion to string"); + return s; + } + void negate() { + log_prefix_event(m_value, "negate"); + m_value.negate(); + log_postfix_event(m_value, "negate"); + } + int compare(const logged_adaptor &o) const { + log_prefix_event(m_value, o.value(), "compare"); + int r = m_value.compare(o.value()); + log_postfix_event(m_value, r, "compare"); + return r; + } + template int compare(const T &i) const { + log_prefix_event(m_value, i, "compare"); + int r = m_value.compare(i); + log_postfix_event(m_value, r, "compare"); + return r; + } + Backend &value() { return m_value; } + const Backend &value() const { return m_value; } + template + void serialize(Archive &ar, const unsigned int /*version*/) { + log_prefix_event(m_value, "serialize"); + ar &boost::serialization::make_nvp("value", m_value); + log_postfix_event(m_value, "serialize"); + } + static unsigned default_precision() BOOST_NOEXCEPT { + return Backend::default_precision(); + } + static void default_precision(unsigned v) BOOST_NOEXCEPT { + Backend::default_precision(v); + } + unsigned precision() const BOOST_NOEXCEPT { return value().precision(); } + void precision(unsigned digits10) BOOST_NOEXCEPT { + value().precision(digits10); + } }; -template -inline const T& unwrap_logged_type(const T& a) { return a; } +template inline const T &unwrap_logged_type(const T &a) { return a; } template -inline const Backend& unwrap_logged_type(const logged_adaptor& a) { return a.value(); } - -#define NON_MEMBER_OP1(name, str) \ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), str);\ - BOOST_JOIN(eval_, name)(result.value());\ - log_postfix_event(result.value(), str);\ - } - -#define NON_MEMBER_OP2(name, str) \ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const T& a)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a));\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const logged_adaptor& a)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a));\ - log_postfix_event(result.value(), str);\ - } - -#define NON_MEMBER_OP3(name, str) \ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const T& a, const U& b)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b));\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const logged_adaptor& a, const T& b)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b));\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const T& a, const logged_adaptor& b)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b));\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const logged_adaptor& a, const logged_adaptor& b)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b));\ - log_postfix_event(result.value(), str);\ - } - -#define NON_MEMBER_OP4(name, str) \ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const T& a, const U& b, const V& c)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const logged_adaptor& a, const logged_adaptor& b, const T& c)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const logged_adaptor& a, const T& b, const logged_adaptor& c)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const T& a, const logged_adaptor& b, const logged_adaptor& c)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const logged_adaptor& a, const logged_adaptor& b, const logged_adaptor& c)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const logged_adaptor& a, const T& b, const U& c)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);\ - BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));\ - log_postfix_event(result.value(), str);\ - }\ +inline const Backend &unwrap_logged_type(const logged_adaptor &a) { + return a.value(); +} + +#define NON_MEMBER_OP1(name, str) \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), str); \ + BOOST_JOIN(eval_, name)(result.value()); \ + log_postfix_event(result.value(), str); \ + } + +#define NON_MEMBER_OP2(name, str) \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result, \ + const T &a) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), str); \ + BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a)); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result, \ + const logged_adaptor &a) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), str); \ + BOOST_JOIN(eval_, name)(result.value(), unwrap_logged_type(a)); \ + log_postfix_event(result.value(), str); \ + } + +#define NON_MEMBER_OP3(name, str) \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result, \ + const T &a, const U &b) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result, \ + const logged_adaptor &a, \ + const T &b) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result, \ + const T &a, \ + const logged_adaptor &b) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result, \ + const logged_adaptor &a, \ + const logged_adaptor &b) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \ + log_postfix_event(result.value(), str); \ + } + +#define NON_MEMBER_OP4(name, str) \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result, \ + const T &a, const U &b, const V &c) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), unwrap_logged_type(c), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), \ + unwrap_logged_type(c)); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)( \ + logged_adaptor & result, const logged_adaptor &a, \ + const logged_adaptor &b, const T &c) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), unwrap_logged_type(c), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), \ + unwrap_logged_type(c)); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)( \ + logged_adaptor & result, const logged_adaptor &a, \ + const T &b, const logged_adaptor &c) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), unwrap_logged_type(c), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), \ + unwrap_logged_type(c)); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)( \ + logged_adaptor & result, const T &a, \ + const logged_adaptor &b, const logged_adaptor &c) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), unwrap_logged_type(c), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), \ + unwrap_logged_type(c)); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)( \ + logged_adaptor & result, const logged_adaptor &a, \ + const logged_adaptor &b, const logged_adaptor &c) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), unwrap_logged_type(c), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), \ + unwrap_logged_type(c)); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result, \ + const logged_adaptor &a, \ + const T &b, const U &c) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(result.value(), unwrap_logged_type(a), \ + unwrap_logged_type(b), unwrap_logged_type(c), str); \ + BOOST_JOIN(eval_, name) \ + (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), \ + unwrap_logged_type(c)); \ + log_postfix_event(result.value(), str); \ + } NON_MEMBER_OP2(add, "+=") NON_MEMBER_OP2(subtract, "-=") @@ -301,45 +304,44 @@ NON_MEMBER_OP2(multiply, "*=") NON_MEMBER_OP2(divide, "/=") template -inline void eval_convert_to(R* result, const logged_adaptor& val) -{ - using default_ops::eval_convert_to; - log_prefix_event(val.value(), "convert_to"); - eval_convert_to(result, val.value()); - log_postfix_event(val.value(), *result, "convert_to"); +inline void eval_convert_to(R *result, const logged_adaptor &val) { + using default_ops::eval_convert_to; + log_prefix_event(val.value(), "convert_to"); + eval_convert_to(result, val.value()); + log_postfix_event(val.value(), *result, "convert_to"); } template -inline void eval_frexp(logged_adaptor& result, const logged_adaptor& arg, Exp* exp) -{ - log_prefix_event(arg.value(), "frexp"); - eval_frexp(result.value(), arg.value(), exp); - log_postfix_event(result.value(), *exp, "frexp"); +inline void eval_frexp(logged_adaptor &result, + const logged_adaptor &arg, Exp *exp) { + log_prefix_event(arg.value(), "frexp"); + eval_frexp(result.value(), arg.value(), exp); + log_postfix_event(result.value(), *exp, "frexp"); } template -inline void eval_ldexp(logged_adaptor& result, const logged_adaptor& arg, Exp exp) -{ - log_prefix_event(arg.value(), "ldexp"); - eval_ldexp(result.value(), arg.value(), exp); - log_postfix_event(result.value(), exp, "ldexp"); +inline void eval_ldexp(logged_adaptor &result, + const logged_adaptor &arg, Exp exp) { + log_prefix_event(arg.value(), "ldexp"); + eval_ldexp(result.value(), arg.value(), exp); + log_postfix_event(result.value(), exp, "ldexp"); } template -inline void eval_scalbn(logged_adaptor& result, const logged_adaptor& arg, Exp exp) -{ - log_prefix_event(arg.value(), "scalbn"); - eval_scalbn(result.value(), arg.value(), exp); - log_postfix_event(result.value(), exp, "scalbn"); +inline void eval_scalbn(logged_adaptor &result, + const logged_adaptor &arg, Exp exp) { + log_prefix_event(arg.value(), "scalbn"); + eval_scalbn(result.value(), arg.value(), exp); + log_postfix_event(result.value(), exp, "scalbn"); } template -inline typename Backend::exponent_type eval_ilogb(const logged_adaptor& arg) -{ - log_prefix_event(arg.value(), "ilogb"); - typename Backend::exponent_type r = eval_ilogb(arg.value()); - log_postfix_event(arg.value(), "ilogb"); - return r; +inline typename Backend::exponent_type +eval_ilogb(const logged_adaptor &arg) { + log_prefix_event(arg.value(), "ilogb"); + typename Backend::exponent_type r = eval_ilogb(arg.value()); + log_postfix_event(arg.value(), "ilogb"); + return r; } NON_MEMBER_OP2(floor, "floor") @@ -347,20 +349,19 @@ NON_MEMBER_OP2(ceil, "ceil") NON_MEMBER_OP2(sqrt, "sqrt") template -inline int eval_fpclassify(const logged_adaptor& arg) -{ - using default_ops::eval_fpclassify; - log_prefix_event(arg.value(), "fpclassify"); - int r = eval_fpclassify(arg.value()); - log_postfix_event(arg.value(), r, "fpclassify"); - return r; +inline int eval_fpclassify(const logged_adaptor &arg) { + using default_ops::eval_fpclassify; + log_prefix_event(arg.value(), "fpclassify"); + int r = eval_fpclassify(arg.value()); + log_postfix_event(arg.value(), r, "fpclassify"); + return r; } /********************************************************************* -* -* Optional arithmetic operations come next: -* -*********************************************************************/ + * + * Optional arithmetic operations come next: + * + *********************************************************************/ NON_MEMBER_OP3(add, "+") NON_MEMBER_OP3(subtract, "-") @@ -375,10 +376,10 @@ NON_MEMBER_OP1(increment, "increment") NON_MEMBER_OP1(decrement, "decrement") /********************************************************************* -* -* Optional integer operations come next: -* -*********************************************************************/ + * + * Optional integer operations come next: + * + *********************************************************************/ NON_MEMBER_OP2(modulus, "%=") NON_MEMBER_OP3(modulus, "%") @@ -392,101 +393,93 @@ NON_MEMBER_OP4(qr, "quotient-and-remainder") NON_MEMBER_OP2(complement, "~") template -inline void eval_left_shift(logged_adaptor& arg, std::size_t a) -{ - using default_ops::eval_left_shift; - log_prefix_event(arg.value(), a, "<<="); - eval_left_shift(arg.value(), a); - log_postfix_event(arg.value(), "<<="); +inline void eval_left_shift(logged_adaptor &arg, std::size_t a) { + using default_ops::eval_left_shift; + log_prefix_event(arg.value(), a, "<<="); + eval_left_shift(arg.value(), a); + log_postfix_event(arg.value(), "<<="); } template -inline void eval_left_shift(logged_adaptor& arg, const logged_adaptor& a, std::size_t b) -{ - using default_ops::eval_left_shift; - log_prefix_event(arg.value(), a, b, "<<"); - eval_left_shift(arg.value(), a.value(), b); - log_postfix_event(arg.value(), "<<"); +inline void eval_left_shift(logged_adaptor &arg, + const logged_adaptor &a, std::size_t b) { + using default_ops::eval_left_shift; + log_prefix_event(arg.value(), a, b, "<<"); + eval_left_shift(arg.value(), a.value(), b); + log_postfix_event(arg.value(), "<<"); } template -inline void eval_right_shift(logged_adaptor& arg, std::size_t a) -{ - using default_ops::eval_right_shift; - log_prefix_event(arg.value(), a, ">>="); - eval_right_shift(arg.value(), a); - log_postfix_event(arg.value(), ">>="); +inline void eval_right_shift(logged_adaptor &arg, std::size_t a) { + using default_ops::eval_right_shift; + log_prefix_event(arg.value(), a, ">>="); + eval_right_shift(arg.value(), a); + log_postfix_event(arg.value(), ">>="); } template -inline void eval_right_shift(logged_adaptor& arg, const logged_adaptor& a, std::size_t b) -{ - using default_ops::eval_right_shift; - log_prefix_event(arg.value(), a, b, ">>"); - eval_right_shift(arg.value(), a.value(), b); - log_postfix_event(arg.value(), ">>"); +inline void eval_right_shift(logged_adaptor &arg, + const logged_adaptor &a, std::size_t b) { + using default_ops::eval_right_shift; + log_prefix_event(arg.value(), a, b, ">>"); + eval_right_shift(arg.value(), a.value(), b); + log_postfix_event(arg.value(), ">>"); } template -inline unsigned eval_integer_modulus(const logged_adaptor& arg, const T& a) -{ - using default_ops::eval_integer_modulus; - log_prefix_event(arg.value(), a, "integer-modulus"); - unsigned r = eval_integer_modulus(arg.value(), a); - log_postfix_event(arg.value(), r, "integer-modulus"); - return r; +inline unsigned eval_integer_modulus(const logged_adaptor &arg, + const T &a) { + using default_ops::eval_integer_modulus; + log_prefix_event(arg.value(), a, "integer-modulus"); + unsigned r = eval_integer_modulus(arg.value(), a); + log_postfix_event(arg.value(), r, "integer-modulus"); + return r; } template -inline unsigned eval_lsb(const logged_adaptor& arg) -{ - using default_ops::eval_lsb; - log_prefix_event(arg.value(), "least-significant-bit"); - unsigned r = eval_lsb(arg.value()); - log_postfix_event(arg.value(), r, "least-significant-bit"); - return r; +inline unsigned eval_lsb(const logged_adaptor &arg) { + using default_ops::eval_lsb; + log_prefix_event(arg.value(), "least-significant-bit"); + unsigned r = eval_lsb(arg.value()); + log_postfix_event(arg.value(), r, "least-significant-bit"); + return r; } template -inline unsigned eval_msb(const logged_adaptor& arg) -{ - using default_ops::eval_msb; - log_prefix_event(arg.value(), "most-significant-bit"); - unsigned r = eval_msb(arg.value()); - log_postfix_event(arg.value(), r, "most-significant-bit"); - return r; +inline unsigned eval_msb(const logged_adaptor &arg) { + using default_ops::eval_msb; + log_prefix_event(arg.value(), "most-significant-bit"); + unsigned r = eval_msb(arg.value()); + log_postfix_event(arg.value(), r, "most-significant-bit"); + return r; } template -inline bool eval_bit_test(const logged_adaptor& arg, unsigned a) -{ - using default_ops::eval_bit_test; - log_prefix_event(arg.value(), a, "bit-test"); - bool r = eval_bit_test(arg.value(), a); - log_postfix_event(arg.value(), r, "bit-test"); - return r; +inline bool eval_bit_test(const logged_adaptor &arg, unsigned a) { + using default_ops::eval_bit_test; + log_prefix_event(arg.value(), a, "bit-test"); + bool r = eval_bit_test(arg.value(), a); + log_postfix_event(arg.value(), r, "bit-test"); + return r; } template -inline void eval_bit_set(const logged_adaptor& arg, unsigned a) -{ - using default_ops::eval_bit_set; - log_prefix_event(arg.value(), a, "bit-set"); - eval_bit_set(arg.value(), a); - log_postfix_event(arg.value(), arg, "bit-set"); +inline void eval_bit_set(const logged_adaptor &arg, unsigned a) { + using default_ops::eval_bit_set; + log_prefix_event(arg.value(), a, "bit-set"); + eval_bit_set(arg.value(), a); + log_postfix_event(arg.value(), arg, "bit-set"); } template -inline void eval_bit_unset(const logged_adaptor& arg, unsigned a) -{ - using default_ops::eval_bit_unset; - log_prefix_event(arg.value(), a, "bit-unset"); - eval_bit_unset(arg.value(), a); - log_postfix_event(arg.value(), arg, "bit-unset"); +inline void eval_bit_unset(const logged_adaptor &arg, unsigned a) { + using default_ops::eval_bit_unset; + log_prefix_event(arg.value(), a, "bit-unset"); + eval_bit_unset(arg.value(), a); + log_postfix_event(arg.value(), arg, "bit-unset"); } template -inline void eval_bit_flip(const logged_adaptor& arg, unsigned a) -{ - using default_ops::eval_bit_flip; - log_prefix_event(arg.value(), a, "bit-flip"); - eval_bit_flip(arg.value(), a); - log_postfix_event(arg.value(), arg, "bit-flip"); +inline void eval_bit_flip(const logged_adaptor &arg, unsigned a) { + using default_ops::eval_bit_flip; + log_prefix_event(arg.value(), a, "bit-flip"); + eval_bit_flip(arg.value(), a); + log_postfix_event(arg.value(), arg, "bit-flip"); } NON_MEMBER_OP3(gcd, "gcd") @@ -494,19 +487,19 @@ NON_MEMBER_OP3(lcm, "lcm") NON_MEMBER_OP4(powm, "powm") /********************************************************************* -* -* abs/fabs: -* -*********************************************************************/ + * + * abs/fabs: + * + *********************************************************************/ NON_MEMBER_OP2(abs, "abs") NON_MEMBER_OP2(fabs, "fabs") /********************************************************************* -* -* Floating point functions: -* -*********************************************************************/ + * + * Floating point functions: + * + *********************************************************************/ NON_MEMBER_OP2(trunc, "trunc") NON_MEMBER_OP2(round, "round") @@ -527,91 +520,111 @@ NON_MEMBER_OP3(fmod, "fmod") NON_MEMBER_OP3(pow, "pow") NON_MEMBER_OP3(atan2, "atan2") -template -int eval_signbit(const logged_adaptor& val) -{ - using default_ops::eval_signbit; - return eval_signbit(val.value()); +template int eval_signbit(const logged_adaptor &val) { + using default_ops::eval_signbit; + return eval_signbit(val.value()); } template -std::size_t hash_value(const logged_adaptor& val) -{ - return hash_value(val.value()); +std::size_t hash_value(const logged_adaptor &val) { + return hash_value(val.value()); } -#define NON_MEMBER_COMPLEX_TO_REAL(name, str) \ - template \ - inline void BOOST_JOIN(eval_, name)(logged_adaptor& result, const logged_adaptor& a)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(a.value(), a.value(), str);\ - BOOST_JOIN(eval_, name)(result.value(), a.value());\ - log_postfix_event(result.value(), str);\ - }\ - template \ - inline void BOOST_JOIN(eval_, name)(B1& result, const logged_adaptor& a)\ - {\ - using default_ops::BOOST_JOIN(eval_, name);\ - log_prefix_event(a.value(), a.value(), str);\ - BOOST_JOIN(eval_, name)(result, a.value());\ - log_postfix_event(result, str);\ - } +#define NON_MEMBER_COMPLEX_TO_REAL(name, str) \ + template \ + inline void BOOST_JOIN(eval_, name)(logged_adaptor & result, \ + const logged_adaptor &a) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(a.value(), a.value(), str); \ + BOOST_JOIN(eval_, name)(result.value(), a.value()); \ + log_postfix_event(result.value(), str); \ + } \ + template \ + inline void BOOST_JOIN(eval_, name)(B1 & result, \ + const logged_adaptor &a) { \ + using default_ops::BOOST_JOIN(eval_, name); \ + log_prefix_event(a.value(), a.value(), str); \ + BOOST_JOIN(eval_, name)(result, a.value()); \ + log_postfix_event(result, str); \ + } NON_MEMBER_COMPLEX_TO_REAL(real, "real") NON_MEMBER_COMPLEX_TO_REAL(imag, "imag") template -inline void assign_components(logged_adaptor& result, const V& v1, const U& v2) -{ - assign_components(result.value(), v1, v2); +inline void assign_components(logged_adaptor &result, const V &v1, + const U &v2) { + assign_components(result.value(), v1, v2); } - - } // namespace backends using backends::logged_adaptor; -template -struct number_category > : public number_category {}; - -}} // namespaces - -namespace std{ +template +struct number_category> + : public number_category {}; + +} // namespace multiprecision +} // namespace boost + +namespace std { + +template +class numeric_limits, + ExpressionTemplates>> + : public std::numeric_limits< + boost::multiprecision::number> { + typedef std::numeric_limits< + boost::multiprecision::number> + base_type; + typedef boost::multiprecision::number< + boost::multiprecision::backends::logged_adaptor, + ExpressionTemplates> + number_type; -template -class numeric_limits, ExpressionTemplates> > - : public std::numeric_limits > -{ - typedef std::numeric_limits > base_type; - typedef boost::multiprecision::number, ExpressionTemplates> number_type; public: - static number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); } - static number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); } - static number_type lowest() BOOST_NOEXCEPT { return -(max)(); } - static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } - static number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; } - static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); } - static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); } - static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); } - static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); } + static number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); } + static number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); } + static number_type lowest() BOOST_NOEXCEPT { return -(max)(); } + static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } + static number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; } + static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); } + static number_type quiet_NaN() BOOST_NOEXCEPT { + return base_type::quiet_NaN(); + } + static number_type signaling_NaN() BOOST_NOEXCEPT { + return base_type::signaling_NaN(); + } + static number_type denorm_min() BOOST_NOEXCEPT { + return base_type::denorm_min(); + } }; } // namespace std -namespace boost{ namespace math{ +namespace boost { +namespace math { -namespace policies{ +namespace policies { -template -struct precision< boost::multiprecision::number, ExpressionTemplates>, Policy> - : public precision, Policy> -{}; +template +struct precision< + boost::multiprecision::number< + boost::multiprecision::logged_adaptor, ExpressionTemplates>, + Policy> + : public precision< + boost::multiprecision::number, Policy> { +}; } // namespace policies -}} // namespaces boost::math +} // namespace math +} // namespace boost #undef NON_MEMBER_OP1 #undef NON_MEMBER_OP2 diff --git a/include/boost/multiprecision/modular_adaptor.hpp b/include/boost/multiprecision/modular_adaptor.hpp index ed7aa5230..923d0df8a 100644 --- a/include/boost/multiprecision/modular_adaptor.hpp +++ b/include/boost/multiprecision/modular_adaptor.hpp @@ -12,240 +12,228 @@ #ifndef BOOST_MULTIPRECISION_MODULAR_ADAPTOR_HPP #define BOOST_MULTIPRECISION_MODULAR_ADAPTOR_HPP -#include -#include #include -#include #include +#include +#include +#include #include -#include #include +#include #include namespace boost { - namespace multiprecision { - namespace backends { - - template - struct modular_adaptor { - protected: - BackendBase m_base; - montgomery_params m_mod; - public: - BackendBase &base_data() { - return m_base; - } - - const BackendBase &base_data() const { - return m_base; - } - - montgomery_params &mod_data() { - return m_mod; - } - - const montgomery_params &mod_data() const { - return m_mod; - } - - //typedef typename Backend::signed_types signed_types; - //typedef typename Backend::unsigned_types unsigned_types; - //typedef typename Backend::float_types float_types; - //typedef typename Backend::exponent_type exponent_type; - - modular_adaptor() { - } - - modular_adaptor(const modular_adaptor &o) : m_base(o.base_data()), m_mod(o.mod_data()) { - } +namespace multiprecision { +namespace backends { + +template struct modular_adaptor { +protected: + BackendBase m_base; + montgomery_params m_mod; + +public: + BackendBase &base_data() { return m_base; } + + const BackendBase &base_data() const { return m_base; } + + montgomery_params &mod_data() { return m_mod; } + + const montgomery_params &mod_data() const { return m_mod; } + + // typedef typename Backend::signed_types signed_types; + // typedef typename Backend::unsigned_types unsigned_types; + // typedef typename Backend::float_types float_types; + // typedef typename Backend::exponent_type exponent_type; + + modular_adaptor() {} + + modular_adaptor(const modular_adaptor &o) + : m_base(o.base_data()), m_mod(o.mod_data()) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - modular_adaptor(modular_adaptor &&o) : m_base(std::move(o.base_data())), - m_mod(std::move(o.mod_data())) { - } + modular_adaptor(modular_adaptor &&o) + : m_base(std::move(o.base_data())), m_mod(std::move(o.mod_data())) {} #endif - modular_adaptor(const BackendBase &val) : m_base(val) { - } + modular_adaptor(const BackendBase &val) : m_base(val) {} - modular_adaptor(const BackendBase &val, const montgomery_params &mod) : m_base(val), - m_mod(mod) { - } + modular_adaptor(const BackendBase &val, + const montgomery_params &mod) + : m_base(val), m_mod(mod) {} - modular_adaptor(const montgomery_params &mod) : m_base(0), m_mod(mod) { - } + modular_adaptor(const montgomery_params &mod) + : m_base(0), m_mod(mod) {} - modular_adaptor &operator=(const modular_adaptor &o) { - m_base = o.base_data(); - m_mod = o.mod_data(); - return *this; - } + modular_adaptor &operator=(const modular_adaptor &o) { + m_base = o.base_data(); + m_mod = o.mod_data(); + return *this; + } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - modular_adaptor &operator=(modular_adaptor &&o) + modular_adaptor &operator=(modular_adaptor &&o) - BOOST_NOEXCEPT - { - m_base = std::move(o.base_data()); - m_mod = std::move(o.mod_data()); - return *this; - } + BOOST_NOEXCEPT { + m_base = std::move(o.base_data()); + m_mod = std::move(o.mod_data()); + return *this; + } #endif - int compare(const modular_adaptor &o) const { - // They are either equal or not: - return (m_base.compare(o.base_data()) == 0) && (m_mod.compare(o.mod_data()) == 0) ? 0 : 1; - } - - template - int compare(const T &val) const { - using default_ops::eval_lt; - return (m_base.compare(val) == 0) && eval_lt(m_mod, val) ? 0 : 1; - } - - void swap(modular_adaptor &o) { - base_data().swap(o.base_data()); - mod_data().swap(o.mod_data()); - } - - std::string str(std::streamsize dig, std::ios_base::fmtflags f) const { - modular_adaptor> - tmp = this; - redc(tmp); - return str(tmp.base_data()); - } - - }; - - template inline typename enable_if, bool> - - ::type eval_eq(const modular_adaptor &a, const T &b) - - BOOST_NOEXCEPT { - return a. - compare(b) - == 0; - } - - template - inline void eval_add(modular_adaptor &result, - const modular_adaptor &o) { - eval_add(result.base_data(), o.base_data()); - redc(result); - } - - template - inline void eval_subtract(modular_adaptor &result, - const modular_adaptor &o) { - BackendBase tmp = result.base_data(); - eval_subtract(tmp, o.base_data()); - if (eval_lt(tmp, 0)) { - BOOST_THROW_EXCEPTION(std::range_error("Montgomery less than zero")); - } - result.base_data() = tmp; - } - - template - inline void eval_multiply(modular_adaptor &result, - const modular_adaptor &o) { - eval_multiply(result.base_data(), o.base_data()); - redc(result); - } - - template - inline void eval_divide(modular_adaptor &result, - const modular_adaptor &o) { - eval_divide(result.base_data(), o.base_data()); - } - - template - inline bool eval_is_zero(const modular_adaptor &val) + int compare(const modular_adaptor &o) const { + // They are either equal or not: + return (m_base.compare(o.base_data()) == 0) && + (m_mod.compare(o.mod_data()) == 0) + ? 0 + : 1; + } + + template int compare(const T &val) const { + using default_ops::eval_lt; + return (m_base.compare(val) == 0) && eval_lt(m_mod, val) ? 0 : 1; + } + + void swap(modular_adaptor &o) { + base_data().swap(o.base_data()); + mod_data().swap(o.mod_data()); + } + + std::string str(std::streamsize dig, std::ios_base::fmtflags f) const { + modular_adaptor> tmp = this; + redc(tmp); + return str(tmp.base_data()); + } +}; + +template +inline typename enable_if, bool> + + ::type eval_eq(const modular_adaptor &a, + const T &b) BOOST_NOEXCEPT { - using default_ops::eval_is_zero; - return - eval_is_zero(val - . - - base_data() - - ); - } - - template - inline int eval_get_sign(const modular_adaptor &) { - return 1; - } - - template - inline typename disable_if_c::value>::type eval_convert_to(Result *result, - const modular_adaptor &val) { - using default_ops::eval_is_zero; - using default_ops::eval_convert_to; - if (!eval_is_zero(val.imag_data())) { - BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar.")); - } - eval_convert_to(result, val.real_data()); - } - - template - inline void assign_components(modular_adaptor &result, const T &a, - const montgomery_params &b) { - result.base_data() = a; - result.mod_data() = b; - } - - template - inline void eval_sqrt(modular_adaptor &result, - const modular_adaptor &val) { - eval_sqrt(result.base_data(), val.base_data()); - } - - template - inline void eval_abs(modular_adaptor &result, - const modular_adaptor &val) { - result = val; - } - - template - inline void eval_pow(modular_adaptor &result, - const modular_adaptor &b, - const modular_adaptor &e) { - using default_ops::eval_acos; - using default_ops::eval_exp; - modular_adaptor t; - eval_log(t, b); - eval_multiply(t, e); - eval_exp(result, t); - redc(result); - } - - template - inline void eval_exp(modular_adaptor &result, - const modular_adaptor &arg) { - using default_ops::eval_exp; - - eval_exp(result.base_data(), arg.base_data()); - result.mod_data() = arg.mod_data(); - redc(result); - } - - template - inline void eval_log(modular_adaptor &result, - const modular_adaptor &arg) { - using default_ops::eval_log; - - eval_log(result.base_data(), arg.base_data()); - result.mod_data() = arg.mod_data(); - redc(result); - } + return a.compare(b) == 0; +} + +template +inline void eval_add(modular_adaptor &result, + const modular_adaptor &o) { + eval_add(result.base_data(), o.base_data()); + redc(result); +} + +template +inline void eval_subtract(modular_adaptor &result, + const modular_adaptor &o) { + BackendBase tmp = result.base_data(); + eval_subtract(tmp, o.base_data()); + if (eval_lt(tmp, 0)) { + BOOST_THROW_EXCEPTION(std::range_error("Montgomery less than zero")); + } + result.base_data() = tmp; +} + +template +inline void eval_multiply(modular_adaptor &result, + const modular_adaptor &o) { + eval_multiply(result.base_data(), o.base_data()); + redc(result); +} + +template +inline void eval_divide(modular_adaptor &result, + const modular_adaptor &o) { + eval_divide(result.base_data(), o.base_data()); +} + +template +inline bool eval_is_zero(const modular_adaptor &val) + + BOOST_NOEXCEPT { + using default_ops::eval_is_zero; + return eval_is_zero(val. + + base_data() + + ); +} + +template +inline int eval_get_sign(const modular_adaptor &) { + return 1; +} + +template +inline typename disable_if_c::value>::type +eval_convert_to(Result *result, + const modular_adaptor &val) { + using default_ops::eval_convert_to; + using default_ops::eval_is_zero; + if (!eval_is_zero(val.imag_data())) { + BOOST_THROW_EXCEPTION( + std::runtime_error("Could not convert imaginary number to scalar.")); + } + eval_convert_to(result, val.real_data()); +} + +template +inline void assign_components(modular_adaptor &result, + const T &a, const montgomery_params &b) { + result.base_data() = a; + result.mod_data() = b; +} + +template +inline void eval_sqrt(modular_adaptor &result, + const modular_adaptor &val) { + eval_sqrt(result.base_data(), val.base_data()); +} + +template +inline void eval_abs(modular_adaptor &result, + const modular_adaptor &val) { + result = val; +} + +template +inline void eval_pow(modular_adaptor &result, + const modular_adaptor &b, + const modular_adaptor &e) { + using default_ops::eval_acos; + using default_ops::eval_exp; + modular_adaptor t; + eval_log(t, b); + eval_multiply(t, e); + eval_exp(result, t); + redc(result); +} + +template +inline void eval_exp(modular_adaptor &result, + const modular_adaptor &arg) { + using default_ops::eval_exp; + + eval_exp(result.base_data(), arg.base_data()); + result.mod_data() = arg.mod_data(); + redc(result); +} + +template +inline void eval_log(modular_adaptor &result, + const modular_adaptor &arg) { + using default_ops::eval_log; + + eval_log(result.base_data(), arg.base_data()); + result.mod_data() = arg.mod_data(); + redc(result); +} + +} // namespace backends } // namespace multiprecision -} // namespaces - #endif diff --git a/include/boost/multiprecision/modular_inverse.hpp b/include/boost/multiprecision/modular_inverse.hpp index 11c8edb76..7c6acf984 100644 --- a/include/boost/multiprecision/modular_inverse.hpp +++ b/include/boost/multiprecision/modular_inverse.hpp @@ -8,172 +8,185 @@ #include namespace nil { - namespace crypto3 { - using namespace boost::multiprecision; - - template - inline Backend eval_ct_inverse_mod_odd_modulus(const Backend &n, const Backend &mod) { - - typedef typename default_ops::double_precision_type::type double_type; - typedef typename boost::multiprecision::detail::canonical::type ui_type; - - using default_ops::eval_is_zero; - using default_ops::eval_lt; - using default_ops::eval_eq; - using default_ops::eval_get_sign; - using default_ops::eval_integer_modulus; - using default_ops::eval_msb; - using default_ops::eval_add; - using default_ops::eval_multiply; - using default_ops::eval_multiply_add; - using default_ops::eval_multiply_subtract; - using default_ops::eval_right_shift; - - typedef cpp_int_backend<0, 0, Backend::integer_type, Backend::checked_type, - secure_allocator> secure_cpp_int_backend; - - if (eval_get_sign(n) < 0 || eval_get_sign(mod) < 0) { - BOOST_THROW_EXCEPTION(std::invalid_argument("ct_inverse_mod_odd_modulus: arguments must be " - "non-negative")); - } - - if (eval_lt(mod, 3) || !eval_integer_modulus(mod, 2)) { - BOOST_THROW_EXCEPTION(std::invalid_argument("Bad modulus to ct_inverse_mod_odd_modulus")); - } - if (!eval_lt(n, mod)) { - BOOST_THROW_EXCEPTION(std::invalid_argument("ct_inverse_mod_odd_modulus n >= mod not supported")); - } - - /* - This uses a modular inversion algorithm designed by Niels Möller - and implemented in Nettle. The same algorithm was later also - adapted to GMP in mpn_sec_invert. - - It can be easily implemented in a way that does not depend on - secret branches or memory lookups, providing resistance against - some forms of side channel attack. - - There is also a description of the algorithm in Appendix 5 of "Fast - Software Polynomial Multiplication on ARM Processors using the NEON Engine" - by Danilo Câmara, Conrado P. L. Gouvêa, Julio López, and Ricardo - Dahab in LNCS 8182 - https://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf - - Thanks to Niels for creating the algorithm, explaining some things - about it, and the reference to the paper. - */ - - secure_cpp_int_backend mp1, mp1o2; - eval_add(mod, 1); - eval_right_shift(mp1o2, mp1, 1); - - // todo allow this to be pre-calculated and passed in as arg - - const size_t mod_words = mod.size(); - CRYPTO3_ASSERT(mod_words > 0, "Not empty"); - - secure_cpp_int_backend a = n; - secure_cpp_int_backend b = mod; - secure_cpp_int_backend u = 1, v = 0; - - ct::poison(a.limbs(), a.size()); - ct::poison(b.limbs(), b.size()); - ct::poison(u.limbs(), u.size()); - ct::poison(v.limbs(), v.size()); - - // Only n.bits() + mod.bits() iterations are required, but avoid leaking the size of n - ui_type bits = 2ul * eval_msb(mod); - - while (bits--) { - const bool odd = eval_integer_modulus(a, 2); - eval_multiply_subtract(a, odd, b); - - const bool underflow = eval_get_sign(a) < 0; - eval_multiply_add(b, a, underflow); - - if (eval_get_sign(a) < 0) { - eval_multiply(a, -1); - } - - eval_right_shift(a, 1); - - if (underflow) { - std::swap(u, v); - } - - eval_multiply_subtract(u, odd, v); - eval_multiply_add(u, eval_get_sign(u) < 0, mod); - - eval_right_shift(u, 1); - eval_multiply_add(u, mp1o2, eval_integer_modulus(u, 2)); - } - - ct::unpoison(a.limbs(), a.size()); - ct::unpoison(b.limbs(), b.size()); - ct::unpoison(u.limbs(), u.size()); - ct::unpoison(v.limbs(), v.size()); - - CRYPTO3_ASSERT(eval_is_zero(a), "A is zero"); - - if (!eval_eq(b, 1)) { - return 0; - } - - return v; - } - - template - inline Backend eval_inverse_mod(const Backend &x, const Backend &mod) { - using default_ops::eval_is_zero; - using default_ops::eval_lt; - using default_ops::eval_get_sign; - - if (eval_is_zero(mod)) { - BOOST_THROW_EXCEPTION(std::invalid_argument("eval_inverse_mod: zero division")); - } - if (eval_get_sign(mod) < 0 || eval_get_sign(x) < 0) { - BOOST_THROW_EXCEPTION(std::invalid_argument("eval_inverse_mod: arguments must be non-negative")); - } - - if (eval_is_zero(x) || - (!eval_is_zero(eval_integer_modulus(x, 2)) && !eval_is_zero(eval_integer_modulus(mod, 2)))) { - return 0; - } // fast fail checks - - if (!eval_is_zero(eval_integer_modulus(mod, 2)) && eval_lt(x, mod)) { - return ct_inverse_mod_odd_modulus(x, mod); - } - - return eval_inverse_euclid(x, mod); - } - - /** - * @brief Modular inversion - * @param x a positive integer - * @param mod a positive integer - * @return y st (x*y) % modulus == 1 or 0 if no such value - * @note Non-const time - */ - template - inline number inverse_mod(const number &x, - const number &mod) { - return eval_inverse_mod(x.backend(), mod.backend()); - } - - /** - * @brief Const time modular inversion - * - * @param n - * @param mod - * - * @note Requires the modulus be odd - */ - template - inline number ct_inverse_mod_odd_modulus( - const number &n, const number &mod) { - return number(eval_ct_inverse_mod_odd_modulus(n.backend(), mod.backend())); - } +namespace crypto3 { +using namespace boost::multiprecision; + +template +inline Backend eval_ct_inverse_mod_odd_modulus(const Backend &n, + const Backend &mod) { + + typedef + typename default_ops::double_precision_type::type double_type; + typedef typename boost::multiprecision::detail::canonical< + unsigned int, double_type>::type ui_type; + + using default_ops::eval_add; + using default_ops::eval_eq; + using default_ops::eval_get_sign; + using default_ops::eval_integer_modulus; + using default_ops::eval_is_zero; + using default_ops::eval_lt; + using default_ops::eval_msb; + using default_ops::eval_multiply; + using default_ops::eval_multiply_add; + using default_ops::eval_multiply_subtract; + using default_ops::eval_right_shift; + + typedef cpp_int_backend<0, 0, Backend::integer_type, Backend::checked_type, + secure_allocator> + secure_cpp_int_backend; + + if (eval_get_sign(n) < 0 || eval_get_sign(mod) < 0) { + BOOST_THROW_EXCEPTION( + std::invalid_argument("ct_inverse_mod_odd_modulus: arguments must be " + "non-negative")); + } + + if (eval_lt(mod, 3) || !eval_integer_modulus(mod, 2)) { + BOOST_THROW_EXCEPTION( + std::invalid_argument("Bad modulus to ct_inverse_mod_odd_modulus")); + } + if (!eval_lt(n, mod)) { + BOOST_THROW_EXCEPTION(std::invalid_argument( + "ct_inverse_mod_odd_modulus n >= mod not supported")); + } + + /* + This uses a modular inversion algorithm designed by Niels Möller + and implemented in Nettle. The same algorithm was later also + adapted to GMP in mpn_sec_invert. + + It can be easily implemented in a way that does not depend on + secret branches or memory lookups, providing resistance against + some forms of side channel attack. + + There is also a description of the algorithm in Appendix 5 of "Fast + Software Polynomial Multiplication on ARM Processors using the NEON Engine" + by Danilo Câmara, Conrado P. L. Gouvêa, Julio López, and Ricardo + Dahab in LNCS 8182 + https://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf + + Thanks to Niels for creating the algorithm, explaining some things + about it, and the reference to the paper. + */ + + secure_cpp_int_backend mp1, mp1o2; + eval_add(mod, 1); + eval_right_shift(mp1o2, mp1, 1); + + // todo allow this to be pre-calculated and passed in as arg + + const size_t mod_words = mod.size(); + CRYPTO3_ASSERT(mod_words > 0, "Not empty"); + + secure_cpp_int_backend a = n; + secure_cpp_int_backend b = mod; + secure_cpp_int_backend u = 1, v = 0; + + ct::poison(a.limbs(), a.size()); + ct::poison(b.limbs(), b.size()); + ct::poison(u.limbs(), u.size()); + ct::poison(v.limbs(), v.size()); + + // Only n.bits() + mod.bits() iterations are required, but avoid leaking the + // size of n + ui_type bits = 2ul * eval_msb(mod); + + while (bits--) { + const bool odd = eval_integer_modulus(a, 2); + eval_multiply_subtract(a, odd, b); + + const bool underflow = eval_get_sign(a) < 0; + eval_multiply_add(b, a, underflow); + + if (eval_get_sign(a) < 0) { + eval_multiply(a, -1); } + + eval_right_shift(a, 1); + + if (underflow) { + std::swap(u, v); + } + + eval_multiply_subtract(u, odd, v); + eval_multiply_add(u, eval_get_sign(u) < 0, mod); + + eval_right_shift(u, 1); + eval_multiply_add(u, mp1o2, eval_integer_modulus(u, 2)); + } + + ct::unpoison(a.limbs(), a.size()); + ct::unpoison(b.limbs(), b.size()); + ct::unpoison(u.limbs(), u.size()); + ct::unpoison(v.limbs(), v.size()); + + CRYPTO3_ASSERT(eval_is_zero(a), "A is zero"); + + if (!eval_eq(b, 1)) { + return 0; + } + + return v; +} + +template +inline Backend eval_inverse_mod(const Backend &x, const Backend &mod) { + using default_ops::eval_get_sign; + using default_ops::eval_is_zero; + using default_ops::eval_lt; + + if (eval_is_zero(mod)) { + BOOST_THROW_EXCEPTION( + std::invalid_argument("eval_inverse_mod: zero division")); + } + if (eval_get_sign(mod) < 0 || eval_get_sign(x) < 0) { + BOOST_THROW_EXCEPTION(std::invalid_argument( + "eval_inverse_mod: arguments must be non-negative")); + } + + if (eval_is_zero(x) || (!eval_is_zero(eval_integer_modulus(x, 2)) && + !eval_is_zero(eval_integer_modulus(mod, 2)))) { + return 0; + } // fast fail checks + + if (!eval_is_zero(eval_integer_modulus(mod, 2)) && eval_lt(x, mod)) { + return ct_inverse_mod_odd_modulus(x, mod); + } + + return eval_inverse_euclid(x, mod); +} + +/** + * @brief Modular inversion + * @param x a positive integer + * @param mod a positive integer + * @return y st (x*y) % modulus == 1 or 0 if no such value + * @note Non-const time + */ +template +inline number +inverse_mod(const number &x, + const number &mod) { + return eval_inverse_mod(x.backend(), mod.backend()); +} + +/** + * @brief Const time modular inversion + * + * @param n + * @param mod + * + * @note Requires the modulus be odd + */ +template +inline number +ct_inverse_mod_odd_modulus(const number &n, + const number &mod) { + return number( + eval_ct_inverse_mod_odd_modulus(n.backend(), mod.backend())); } +} // namespace crypto3 +} // namespace nil -#endif //CRYPTO3_MOD_INVERSE_HPP +#endif // CRYPTO3_MOD_INVERSE_HPP diff --git a/include/boost/multiprecision/montgomery_int/bitwise.hpp b/include/boost/multiprecision/montgomery_int/bitwise.hpp index 52e52704a..ea34585f7 100644 --- a/include/boost/multiprecision/montgomery_int/bitwise.hpp +++ b/include/boost/multiprecision/montgomery_int/bitwise.hpp @@ -3,600 +3,890 @@ #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4319) +#pragma warning(disable : 4319) #endif namespace boost { - namespace multiprecision { - namespace backends { - - template - void is_valid_bitwise_op(montgomery_int_backend &result, - const montgomery_int_backend &o, - const mpl::int_ &) { - if (result.sign() || o.sign()) { - BOOST_THROW_EXCEPTION( - std::range_error("Bitwise operations on negative values results in undefined behavior.")); - } - } - - template - void is_valid_bitwise_op(montgomery_int_backend &, - const montgomery_int_backend &, - const mpl::int_ &) { - } - - template - void is_valid_bitwise_op( - const montgomery_int_backend &result, - const mpl::int_ &) { - if (result.sign()) { - BOOST_THROW_EXCEPTION( - std::range_error("Bitwise operations on negative values results in undefined behavior.")); - } - } - - template - void is_valid_bitwise_op( - const montgomery_int_backend &, - const mpl::int_ &) { - } - - template - void is_valid_bitwise_op(montgomery_int_backend &, - const mpl::int_ &) { - } - - template - BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_montgomery_int >::value && - !is_trivial_montgomery_int >::value> - - ::type eval_bitwise_and(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - bitwise_op(result, o, bit_and(), mpl::bool_ > >::is_signed || - std::numeric_limits< - number>>::is_signed>()); - } - - template - BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_montgomery_int >::value && - !is_trivial_montgomery_int >::value> - - ::type eval_bitwise_or(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - bitwise_op(result, o, bit_or(), mpl::bool_ > >::is_signed || - std::numeric_limits< - number>>::is_signed>()); - } - - template - BOOST_MP_FORCEINLINE typename enable_if_c< - !is_trivial_montgomery_int >::value && - !is_trivial_montgomery_int >::value> - - ::type eval_bitwise_xor(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - bitwise_op(result, o, bit_xor(), mpl::bool_ > >::is_signed || - std::numeric_limits< - number>>::is_signed>()); - } +namespace multiprecision { +namespace backends { + +template +void is_valid_bitwise_op( + montgomery_int_backend &result, + const montgomery_int_backend &o, + const mpl::int_ &) { + if (result.sign() || o.sign()) { + BOOST_THROW_EXCEPTION( + std::range_error("Bitwise operations on negative values results in " + "undefined behavior.")); + } +} + +template +void is_valid_bitwise_op( + montgomery_int_backend &, + const montgomery_int_backend &, + const mpl::int_ &) {} + +template +void is_valid_bitwise_op( + const montgomery_int_backend &result, + const mpl::int_ &) { + if (result.sign()) { + BOOST_THROW_EXCEPTION( + std::range_error("Bitwise operations on negative values results in " + "undefined behavior.")); + } +} + +template +void is_valid_bitwise_op( + const montgomery_int_backend &, + const mpl::int_ &) {} + +template +void is_valid_bitwise_op( + montgomery_int_backend &, + const mpl::int_ &) {} + +template +BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int< + montgomery_int_backend>::value && + !is_trivial_montgomery_int< + montgomery_int_backend>::value> + + ::type eval_bitwise_and( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + bitwise_op( + result, o, bit_and(), + mpl::bool_ < std::numeric_limits>>::is_signed || + std::numeric_limits< + number>>::is_signed > + ()); +} + +template +BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int< + montgomery_int_backend>::value && + !is_trivial_montgomery_int< + montgomery_int_backend>::value> + + ::type eval_bitwise_or( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + bitwise_op(result, o, bit_or(), + mpl::bool_ < std::numeric_limits>>::is_signed || + std::numeric_limits>>::is_signed > ()); +} + +template +BOOST_MP_FORCEINLINE typename enable_if_c< + !is_trivial_montgomery_int< + montgomery_int_backend>::value && + !is_trivial_montgomery_int< + montgomery_int_backend>::value> + + ::type eval_bitwise_xor( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + bitwise_op( + result, o, bit_xor(), + mpl::bool_ < std::numeric_limits>>::is_signed || + std::numeric_limits< + number>>::is_signed > + ()); +} // // Again for operands which are single limbs: // - template - BOOST_MP_FORCEINLINE typename enable_if_c >::value> - ::type eval_bitwise_and( - montgomery_int_backend &result, limb_type - l) BOOST_NOEXCEPT { - result.limbs()[0] &= l; - result.resize(1, 1); - } - - template - BOOST_MP_FORCEINLINE typename enable_if_c >::value> - - ::type eval_bitwise_or( - montgomery_int_backend &result, limb_type l) - - BOOST_NOEXCEPT { - result.limbs()[0] |= l; - } - - template - BOOST_MP_FORCEINLINE typename enable_if_c >::value> - - ::type eval_bitwise_xor( - montgomery_int_backend &result, limb_type l) - - BOOST_NOEXCEPT { - result.limbs()[0] ^= l; - } - - template - BOOST_MP_FORCEINLINE typename enable_if_c< - is_signed_number >::value && - !is_trivial_montgomery_int >::value && - !is_trivial_montgomery_int >::value> - - ::type eval_complement(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), - "Attempt to take the complement of a signed type results in undefined behavior."); -// Increment and negate: - result = o; - eval_increment(result); - result.negate(); - } - - template - BOOST_MP_FORCEINLINE typename enable_if_c< - is_unsigned_number >::value && - !is_trivial_montgomery_int >::value && - !is_trivial_montgomery_int >::value> - - ::type eval_complement(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - unsigned os = o.size(); - result.resize(UINT_MAX, os); - for (unsigned i = 0; i < os; ++i) { - result.limbs()[i] = ~o.limbs()[i]; - } - - for (unsigned i = os; i < result.size(); ++i) { - result.limbs()[i] = ~static_cast(0); - } - - result.normalize(); - } - - template - inline typename enable_if_c< - !is_trivial_montgomery_int >::value> - - ::type eval_left_shift(montgomery_int_backend &result, - double_limb_type s) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - is_valid_bitwise_op(result, - - typename montgomery_int_backend::checked_type() - - ); - if (!s) { - return; - } +template +BOOST_MP_FORCEINLINE typename enable_if_c>::value>::type +eval_bitwise_and( + montgomery_int_backend &result, + limb_type l) BOOST_NOEXCEPT { + result.limbs()[0] &= l; + result.resize(1, 1); +} + +template +BOOST_MP_FORCEINLINE typename enable_if_c>::value> + + ::type eval_bitwise_or( + montgomery_int_backend &result, + limb_type l) + + BOOST_NOEXCEPT { + result.limbs()[0] |= l; +} + +template +BOOST_MP_FORCEINLINE typename enable_if_c>::value> + + ::type eval_bitwise_xor( + montgomery_int_backend &result, + limb_type l) + + BOOST_NOEXCEPT { + result.limbs()[0] ^= l; +} + +template +BOOST_MP_FORCEINLINE typename enable_if_c< + is_signed_number< + montgomery_int_backend>::value && + !is_trivial_montgomery_int< + montgomery_int_backend>::value && + !is_trivial_montgomery_int< + montgomery_int_backend>::value> + + ::type eval_complement( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), + "Attempt to take the complement of a signed type " + "results in undefined behavior."); + // Increment and negate: + result = o; + eval_increment(result); + result.negate(); +} + +template +BOOST_MP_FORCEINLINE typename enable_if_c< + is_unsigned_number< + montgomery_int_backend>::value && + !is_trivial_montgomery_int< + montgomery_int_backend>::value && + !is_trivial_montgomery_int< + montgomery_int_backend>::value> + + ::type eval_complement( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + unsigned os = o.size(); + result.resize(UINT_MAX, os); + for (unsigned i = 0; i < os; ++i) { + result.limbs()[i] = ~o.limbs()[i]; + } + + for (unsigned i = os; i < result.size(); ++i) { + result.limbs()[i] = ~static_cast(0); + } + + result.normalize(); +} + +template +inline typename enable_if_c>::value> + + ::type eval_left_shift( + montgomery_int_backend &result, + double_limb_type s) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + is_valid_bitwise_op( + result, + + typename montgomery_int_backend::checked_type() + + ); + if (!s) { + return; + } #if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT) - static const limb_type limb_shift_mask = montgomery_int_backend::limb_bits - 1; - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if((s & limb_shift_mask) == 0) - { - left_shift_limb(result, s); - } - else if((s & byte_shift_mask) == 0) - { - left_shift_byte(result, s); - } + static const limb_type limb_shift_mask = + montgomery_int_backend::limb_bits - + 1; + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & limb_shift_mask) == 0) { + left_shift_limb(result, s); + } else if ((s & byte_shift_mask) == 0) { + left_shift_byte(result, s); + } #elif defined(BOOST_LITTLE_ENDIAN) - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if ((s & byte_shift_mask) == 0) { - left_shift_byte(result, s); - } + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & byte_shift_mask) == 0) { + left_shift_byte(result, s); + } #else - static const limb_type limb_shift_mask = - montgomery_int_backend::limb_bits - 1; - if (( - s &limb_shift_mask - ) == 0) - { - left_shift_limb(result, s - ); - } + static const limb_type limb_shift_mask = + montgomery_int_backend::limb_bits - + 1; + if ((s & limb_shift_mask) == 0) { + left_shift_limb(result, s); + } #endif - else { - left_shift_generic(result, s); - } -// -// We may have shifted off the end and have leading zeros: -// - result.normalize(); - } - template - inline typename enable_if_c >::value> - - ::type eval_right_shift( - montgomery_int_backend &result, - double_limb_type s) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - is_valid_bitwise_op(result, - - typename montgomery_int_backend::checked_type() - - ); - if (!s) { - return; - } + else { + left_shift_generic(result, s); + } + // + // We may have shifted off the end and have leading zeros: + // + result.normalize(); +} +template +inline typename enable_if_c>::value> + + ::type eval_right_shift( + montgomery_int_backend &result, + double_limb_type s) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + is_valid_bitwise_op( + result, + + typename montgomery_int_backend::checked_type() + + ); + if (!s) { + return; + } #if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT) - static const limb_type limb_shift_mask = montgomery_int_backend::limb_bits - 1; - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if((s & limb_shift_mask) == 0) - right_shift_limb(result, s); - else if((s & byte_shift_mask) == 0) - right_shift_byte(result, s); + static const limb_type limb_shift_mask = + montgomery_int_backend::limb_bits - + 1; + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & limb_shift_mask) == 0) + right_shift_limb(result, s); + else if ((s & byte_shift_mask) == 0) + right_shift_byte(result, s); #elif defined(BOOST_LITTLE_ENDIAN) - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if ((s & byte_shift_mask) == 0) { - right_shift_byte(result, s); - } + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & byte_shift_mask) == 0) { + right_shift_byte(result, s); + } #else - static const limb_type limb_shift_mask = - montgomery_int_backend::limb_bits - 1; - if ((s &limb_shift_mask) == 0) { - right_shift_limb(result, s); - } + static const limb_type limb_shift_mask = + montgomery_int_backend::limb_bits - + 1; + if ((s & limb_shift_mask) == 0) { + right_shift_limb(result, s); + } #endif - else { - right_shift_generic(result, s); - } - } - - template - inline typename enable_if_c >::value> - - ::type eval_right_shift(montgomery_int_backend &result, - double_limb_type s) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - is_valid_bitwise_op(result, typename montgomery_int_backend::checked_type()); - if (!s) { - return; - } - - bool is_neg = result.sign(); - if (is_neg) { - eval_increment(result); - } + else { + right_shift_generic(result, s); + } +} + +template +inline typename enable_if_c>::value> + + ::type eval_right_shift( + montgomery_int_backend &result, + double_limb_type s) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int>::value)) { + is_valid_bitwise_op( + result, + typename montgomery_int_backend::checked_type()); + if (!s) { + return; + } + + bool is_neg = result.sign(); + if (is_neg) { + eval_increment(result); + } #if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT) - static const limb_type limb_shift_mask = montgomery_int_backend::limb_bits - 1; - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if((s & limb_shift_mask) == 0) - right_shift_limb(result, s); - else if((s & byte_shift_mask) == 0) - right_shift_byte(result, s); + static const limb_type limb_shift_mask = + montgomery_int_backend::limb_bits - + 1; + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & limb_shift_mask) == 0) + right_shift_limb(result, s); + else if ((s & byte_shift_mask) == 0) + right_shift_byte(result, s); #elif defined(BOOST_LITTLE_ENDIAN) - static const limb_type byte_shift_mask = CHAR_BIT - 1; - if ((s & byte_shift_mask) == 0) { - right_shift_byte(result, s); - } + static const limb_type byte_shift_mask = CHAR_BIT - 1; + if ((s & byte_shift_mask) == 0) { + right_shift_byte(result, s); + } #else - static const limb_type limb_shift_mask = - montgomery_int_backend::limb_bits - 1; - if ((s &limb_shift_mask) == 0) { - right_shift_limb(result, s); - } + static const limb_type limb_shift_mask = + montgomery_int_backend::limb_bits - + 1; + if ((s & limb_shift_mask) == 0) { + right_shift_limb(result, s); + } #endif - else { - right_shift_generic(result, s); - } - if (is_neg) { - eval_decrement(result); - } - } + else { + right_shift_generic(result, s); + } + if (is_neg) { + eval_decrement(result); + } +} // // Over again for trivial cpp_int's: // - template BOOST_MP_FORCEINLINE typename enable_if< - is_trivial_montgomery_int < montgomery_int_backend > > - - ::type eval_left_shift(montgomery_int_backend &result, T s) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - is_valid_bitwise_op(result,typename montgomery_int_backend::checked_type()); - *result.limbs() = detail::checked_left_shift(*result.limbs(), s, - typename montgomery_int_backend::checked_type()); - - result.normalize(); - } - - template BOOST_MP_FORCEINLINE typename enable_if< - is_trivial_montgomery_int < montgomery_int_backend > > - - ::type eval_right_shift(montgomery_int_backend &result, T s) - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { -// Nothing to check here... just make sure we don't invoke undefined behavior: - is_valid_bitwise_op(result, typename montgomery_int_backend::checked_type()); - *result.limbs() = (static_cast(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign - () ? ((--*result.limbs()) >> s) + 1 : *result.limbs()>> s); - - if (result.sign() && (*result.limbs() == 0)) { - result = static_cast(-1); - } - } - - template - inline typename enable_if_c< - is_trivial_montgomery_int >::value && - is_trivial_montgomery_int >::value && - (is_signed_number >::value || - is_signed_number >::value)> - - ::type eval_complement(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), - "Attempt to take the complement of a signed type results in undefined behavior."); -// -// If we're not checked then emulate 2's complement behavior: -// - if (o.sign()) { - *result.limbs() = *o.limbs() - 1; - - result.sign(false); - } else { - *result.limbs() = 1 + *o.limbs(); - - result.sign(true); - } - result.normalize(); - } - - template - inline typename enable_if_c< - is_trivial_montgomery_int >::value && - is_trivial_montgomery_int >::value && - is_unsigned_number >::value && - is_unsigned_number >::value> - - ::type eval_complement(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - *result.limbs() = ~*o.limbs(); - - result.normalize(); - } - - template - inline typename enable_if_c< - is_trivial_montgomery_int >::value && - is_trivial_montgomery_int >::value && - is_unsigned_number >::value && - is_unsigned_number >::value> - - ::type eval_bitwise_and(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - *result.limbs() &= *o.limbs(); - } - - template - inline typename enable_if_c< - is_trivial_montgomery_int >::value && - is_trivial_montgomery_int >::value && - (is_signed_number >::value || - is_signed_number >::value)> - - ::type eval_bitwise_and(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - is_valid_bitwise_op(result, o, - - typename montgomery_int_backend::checked_type() - - ); - - using default_ops::eval_bit_test; - using default_ops::eval_increment; - - if (result.sign() || o.sign()) { - static const unsigned m = static_unsigned_max::value, - static_unsigned_max::value>::value; - montgomery_int_backend t1(result); - montgomery_int_backend t2(o); - eval_bitwise_and(t1, t2); - bool s = eval_bit_test(t1, m + 1); - if (s) { - eval_complement(t1, t1); - eval_increment(t1); - } - result = t1; - result.sign(s); - } else { - *result.limbs() &= *o.limbs(); - } - } - - template - inline typename enable_if_c< - is_trivial_montgomery_int >::value && - is_trivial_montgomery_int >::value && - is_unsigned_number >::value && - is_unsigned_number >::value> - - ::type eval_bitwise_or(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - *result.limbs() |= *o.limbs(); - } - - template - inline typename enable_if_c< - is_trivial_montgomery_int >::value && - is_trivial_montgomery_int >::value && - (is_signed_number >::value || - is_signed_number >::value)> - - ::type eval_bitwise_or(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - is_valid_bitwise_op(result, o, - - typename montgomery_int_backend::checked_type() - - ); - - using default_ops::eval_bit_test; - using default_ops::eval_increment; - - if (result.sign() || o.sign()) { - static const unsigned m = static_unsigned_max::value, - static_unsigned_max::value>::value; - montgomery_int_backend t1(result); - montgomery_int_backend t2(o); - eval_bitwise_or(t1, t2); - bool s = eval_bit_test(t1, m + 1); - if (s) { - eval_complement(t1, t1); - eval_increment(t1); - } - result = t1; - result.sign(s); - } else { - *result.limbs() |= *o.limbs(); - result.normalize(); - } - } - - template - inline typename enable_if_c< - is_trivial_montgomery_int >::value && - is_trivial_montgomery_int >::value && - is_unsigned_number >::value && - is_unsigned_number >::value> - - ::type eval_bitwise_xor(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - *result.limbs() ^= *o.limbs(); - } - - template - inline typename enable_if_c< - is_trivial_montgomery_int >::value && - is_trivial_montgomery_int >::value && - (is_signed_number >::value || - is_signed_number >::value)> - - ::type eval_bitwise_xor(montgomery_int_backend &result, - const montgomery_int_backend &o) - - BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int< - montgomery_int_backend >::value)) { - is_valid_bitwise_op(result, o, typename montgomery_int_backend::checked_type()); - - using default_ops::eval_bit_test; - using default_ops::eval_increment; - - if (result.sign() || o.sign()) { - static const unsigned m = static_unsigned_max::value, - static_unsigned_max::value>::value; - montgomery_int_backend t1(result); - montgomery_int_backend t2(o); - eval_bitwise_xor(t1, t2); - bool s = eval_bit_test(t1, m + 1); - if (s) { - eval_complement(t1, t1); - eval_increment(t1); - } - result = t1; - result.sign(s); - } else { - *result.limbs() ^= *o.limbs(); - } - } - } +template +BOOST_MP_FORCEINLINE + typename enable_if>> + + ::type eval_left_shift( + montgomery_int_backend &result, + T s) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + is_valid_bitwise_op( + result, typename montgomery_int_backend::checked_type()); + *result.limbs() = detail::checked_left_shift( + *result.limbs(), s, + typename montgomery_int_backend::checked_type()); + + result.normalize(); +} + +template +BOOST_MP_FORCEINLINE + typename enable_if>> + + ::type eval_right_shift( + montgomery_int_backend &result, + T s) + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + // Nothing to check here... just make sure we don't invoke undefined behavior: + is_valid_bitwise_op( + result, + typename montgomery_int_backend::checked_type()); + *result.limbs() = + (static_cast(s) >= sizeof(*result.limbs()) * CHAR_BIT) + ? 0 + : (result.sign() ? ((--*result.limbs()) >> s) + 1 + : *result.limbs() >> s); + + if (result.sign() && (*result.limbs() == 0)) { + result = static_cast(-1); + } +} + +template +inline typename enable_if_c< + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_trivial_montgomery_int< + montgomery_int_backend>::value && + (is_signed_number< + montgomery_int_backend>::value || + is_signed_number< + montgomery_int_backend>::value)> + + ::type eval_complement( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), + "Attempt to take the complement of a signed type " + "results in undefined behavior."); + // + // If we're not checked then emulate 2's complement behavior: + // + if (o.sign()) { + *result.limbs() = *o.limbs() - 1; + + result.sign(false); + } else { + *result.limbs() = 1 + *o.limbs(); + + result.sign(true); + } + result.normalize(); +} + +template +inline typename enable_if_c< + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_unsigned_number< + montgomery_int_backend>::value && + is_unsigned_number< + montgomery_int_backend>::value> + + ::type eval_complement( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + *result.limbs() = ~*o.limbs(); + + result.normalize(); +} + +template +inline typename enable_if_c< + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_unsigned_number< + montgomery_int_backend>::value && + is_unsigned_number< + montgomery_int_backend>::value> + + ::type eval_bitwise_and( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + *result.limbs() &= *o.limbs(); +} + +template +inline typename enable_if_c< + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_trivial_montgomery_int< + montgomery_int_backend>::value && + (is_signed_number< + montgomery_int_backend>::value || + is_signed_number< + montgomery_int_backend>::value)> + + ::type eval_bitwise_and( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + is_valid_bitwise_op( + result, o, + + typename montgomery_int_backend::checked_type() + + ); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if (result.sign() || o.sign()) { + static const unsigned m = static_unsigned_max< + static_unsigned_max::value, + static_unsigned_max::value>::value; + montgomery_int_backend + t1(result); + montgomery_int_backend + t2(o); + eval_bitwise_and(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if (s) { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } else { + *result.limbs() &= *o.limbs(); + } +} + +template +inline typename enable_if_c< + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_unsigned_number< + montgomery_int_backend>::value && + is_unsigned_number< + montgomery_int_backend>::value> + + ::type eval_bitwise_or( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + *result.limbs() |= *o.limbs(); +} + +template +inline typename enable_if_c< + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_trivial_montgomery_int< + montgomery_int_backend>::value && + (is_signed_number< + montgomery_int_backend>::value || + is_signed_number< + montgomery_int_backend>::value)> + + ::type eval_bitwise_or( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + is_valid_bitwise_op( + result, o, + + typename montgomery_int_backend::checked_type() + + ); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if (result.sign() || o.sign()) { + static const unsigned m = static_unsigned_max< + static_unsigned_max::value, + static_unsigned_max::value>::value; + montgomery_int_backend + t1(result); + montgomery_int_backend + t2(o); + eval_bitwise_or(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if (s) { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } else { + *result.limbs() |= *o.limbs(); + result.normalize(); + } +} + +template +inline typename enable_if_c< + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_unsigned_number< + montgomery_int_backend>::value && + is_unsigned_number< + montgomery_int_backend>::value> + + ::type eval_bitwise_xor( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + *result.limbs() ^= *o.limbs(); +} + +template +inline typename enable_if_c< + is_trivial_montgomery_int< + montgomery_int_backend>::value && + is_trivial_montgomery_int< + montgomery_int_backend>::value && + (is_signed_number< + montgomery_int_backend>::value || + is_signed_number< + montgomery_int_backend>::value)> + + ::type eval_bitwise_xor( + montgomery_int_backend &result, + const montgomery_int_backend &o) + + BOOST_MP_NOEXCEPT_IF( + (is_non_throwing_cpp_int< + montgomery_int_backend>::value)) { + is_valid_bitwise_op( + result, o, + typename montgomery_int_backend::checked_type()); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if (result.sign() || o.sign()) { + static const unsigned m = static_unsigned_max< + static_unsigned_max::value, + static_unsigned_max::value>::value; + montgomery_int_backend + t1(result); + montgomery_int_backend + t2(o); + eval_bitwise_xor(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if (s) { + eval_complement(t1, t1); + eval_increment(t1); } -} // namespaces + result = t1; + result.sign(s); + } else { + *result.limbs() ^= *o.limbs(); + } +} +} // namespace backends +} // namespace multiprecision +} // namespace boost #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/multiprecision/montgomery_int/comparison.hpp b/include/boost/multiprecision/montgomery_int/comparison.hpp index b02c1cf80..1175b7d6e 100644 --- a/include/boost/multiprecision/montgomery_int/comparison.hpp +++ b/include/boost/multiprecision/montgomery_int/comparison.hpp @@ -4,476 +4,710 @@ #include namespace boost { - namespace multiprecision { +namespace multiprecision { - namespace backends { +namespace backends { #ifdef BOOST_MSVC #pragma warning(push) -#pragma warning(disable:4018 4389 4996) +#pragma warning(disable : 4018 4389 4996) #endif // // Start with non-trivial cpp_int's: // - template class Backend, - unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, typename ParamsBackend> - BOOST_MP_FORCEINLINE typename enable_if_c >::value && - !is_trivial_montgomery_int< - Backend >::value && - is_equal_montgomery_int_backend>::value> - - ::type eval_eq(const montgomery_int_backend &a, - const Backend &b) BOOST_NOEXCEPT { +template