aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2022-09-12 00:13:01 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2022-09-12 00:13:01 +0300
commite0ae8d5ab7319ecad6846cd9d49483d87025060e (patch)
tree9440940f11cdc0bb7a0cafd33d54b3ec15d37414
parent8ee3a632d2efcea08c59920dab8aa7b5c29c5e25 (diff)
downloadydb-e0ae8d5ab7319ecad6846cd9d49483d87025060e.tar.gz
Update boost/multiprecision and boost/math to 1.80.0
-rw-r--r--contrib/restricted/boost/boost/coroutine/all.hpp21
-rw-r--r--contrib/restricted/boost/boost/coroutine/asymmetric_coroutine.hpp2416
-rw-r--r--contrib/restricted/boost/boost/coroutine/attributes.hpp58
-rw-r--r--contrib/restricted/boost/boost/coroutine/coroutine.hpp13
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/flags.hpp47
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/parameters.hpp102
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_impl.hpp335
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_object.hpp310
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_synthesized.hpp80
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/push_coroutine_impl.hpp282
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/push_coroutine_object.hpp322
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/push_coroutine_synthesized.hpp78
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/setup.hpp75
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_call.hpp811
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_impl.hpp449
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_object.hpp267
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_yield.hpp307
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/trampoline.hpp69
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/trampoline_pull.hpp50
-rw-r--r--contrib/restricted/boost/boost/coroutine/detail/trampoline_push.hpp79
-rw-r--r--contrib/restricted/boost/boost/coroutine/flags.hpp21
-rw-r--r--contrib/restricted/boost/boost/coroutine/posix/protected_stack_allocator.hpp106
-rw-r--r--contrib/restricted/boost/boost/coroutine/posix/segmented_stack_allocator.hpp69
-rw-r--r--contrib/restricted/boost/boost/coroutine/protected_stack_allocator.hpp13
-rw-r--r--contrib/restricted/boost/boost/coroutine/segmented_stack_allocator.hpp15
-rw-r--r--contrib/restricted/boost/boost/coroutine/stack_allocator.hpp37
-rw-r--r--contrib/restricted/boost/boost/coroutine/standard_stack_allocator.hpp75
-rw-r--r--contrib/restricted/boost/boost/coroutine/symmetric_coroutine.hpp43
-rw-r--r--contrib/restricted/boost/boost/coroutine/windows/protected_stack_allocator.hpp87
-rw-r--r--contrib/restricted/boost/config/include/boost/config/no_tr1/complex.hpp28
-rw-r--r--contrib/restricted/boost/core/include/boost/non_type.hpp27
-rw-r--r--contrib/restricted/boost/coroutine/README.md14
-rw-r--r--contrib/restricted/boost/coroutine/include/boost/coroutine/detail/config.hpp (renamed from contrib/restricted/boost/boost/coroutine/detail/config.hpp)4
-rw-r--r--contrib/restricted/boost/coroutine/include/boost/coroutine/detail/coroutine_context.hpp (renamed from contrib/restricted/boost/boost/coroutine/detail/coroutine_context.hpp)0
-rw-r--r--contrib/restricted/boost/coroutine/include/boost/coroutine/detail/data.hpp (renamed from contrib/restricted/boost/boost/coroutine/detail/data.hpp)0
-rw-r--r--contrib/restricted/boost/coroutine/include/boost/coroutine/detail/preallocated.hpp (renamed from contrib/restricted/boost/boost/coroutine/detail/preallocated.hpp)0
-rw-r--r--contrib/restricted/boost/coroutine/include/boost/coroutine/exceptions.hpp (renamed from contrib/restricted/boost/boost/coroutine/exceptions.hpp)0
-rw-r--r--contrib/restricted/boost/coroutine/include/boost/coroutine/stack_context.hpp (renamed from contrib/restricted/boost/boost/coroutine/stack_context.hpp)0
-rw-r--r--contrib/restricted/boost/coroutine/include/boost/coroutine/stack_traits.hpp (renamed from contrib/restricted/boost/boost/coroutine/stack_traits.hpp)0
-rw-r--r--contrib/restricted/boost/coroutine/src/detail/coroutine_context.cpp (renamed from contrib/restricted/boost/libs/coroutine/src/detail/coroutine_context.cpp)0
-rw-r--r--contrib/restricted/boost/coroutine/src/exceptions.cpp (renamed from contrib/restricted/boost/libs/coroutine/src/exceptions.cpp)0
-rw-r--r--contrib/restricted/boost/coroutine/src/posix/stack_traits.cpp (renamed from contrib/restricted/boost/libs/coroutine/src/posix/stack_traits.cpp)0
-rw-r--r--contrib/restricted/boost/integer/include/boost/integer/static_min_max.hpp52
-rw-r--r--contrib/restricted/boost/math/LICENSE23
-rw-r--r--contrib/restricted/boost/math/README.md148
-rw-r--r--contrib/restricted/boost/math/include/boost/cstdfloat.hpp58
-rw-r--r--contrib/restricted/boost/math/include/boost/math/constants/calculate_constants.hpp1110
-rw-r--r--contrib/restricted/boost/math/include/boost/math/constants/constants.hpp345
-rw-r--r--contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_cmath.hpp1057
-rw-r--r--contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_complex.hpp38
-rw-r--r--contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp813
-rw-r--r--contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_iostream.hpp774
-rw-r--r--contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_limits.hpp86
-rw-r--r--contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_types.hpp441
-rw-r--r--contrib/restricted/boost/math/include/boost/math/policies/error_handling.hpp141
-rw-r--r--contrib/restricted/boost/math/include/boost/math/policies/policy.hpp822
-rw-r--r--contrib/restricted/boost/math/include/boost/math/special_functions/detail/fp_traits.hpp170
-rw-r--r--contrib/restricted/boost/math/include/boost/math/special_functions/detail/round_fwd.hpp21
-rw-r--r--contrib/restricted/boost/math/include/boost/math/special_functions/fpclassify.hpp74
-rw-r--r--contrib/restricted/boost/math/include/boost/math/special_functions/hypot.hpp82
-rw-r--r--contrib/restricted/boost/math/include/boost/math/special_functions/math_fwd.hpp265
-rw-r--r--contrib/restricted/boost/math/include/boost/math/special_functions/next.hpp176
-rw-r--r--contrib/restricted/boost/math/include/boost/math/special_functions/sign.hpp16
-rw-r--r--contrib/restricted/boost/math/include/boost/math/special_functions/trunc.hpp79
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/assert.hpp34
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/complex.hpp76
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/config.hpp267
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/convert_from_string.hpp54
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/cxx03_warn.hpp95
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/is_detected.hpp56
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/is_standalone.hpp18
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/mp.hpp439
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/precision.hpp144
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/promotion.hpp108
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/real_cast.hpp2
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/throw_exception.hpp22
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/traits.hpp128
-rw-r--r--contrib/restricted/boost/math/include/boost/math/tools/user.hpp4
-rw-r--r--contrib/restricted/boost/multiprecision/LICENSE23
-rw-r--r--contrib/restricted/boost/multiprecision/README.md65
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int.hpp2244
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/add.hpp486
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/add_unsigned.hpp387
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/bitwise.hpp693
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/checked.hpp99
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/comparison.hpp435
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/cpp_int_config.hpp207
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/divide.hpp462
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/import_export.hpp447
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/intel_intrinsics.hpp138
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/limits.hpp330
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/literals.hpp281
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/misc.hpp1470
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/multiply.hpp752
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/serialize.hpp132
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/value_pack.hpp32
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/assert.hpp29
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/bitscan.hpp309
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/check_cpp11_config.hpp64
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/constexpr.hpp88
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/default_ops.hpp3600
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/digits.hpp49
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/empty_value.hpp87
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/endian.hpp35
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/et_ops.hpp1666
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/float128_functions.hpp93
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/fpclassify.hpp101
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/constants.hpp198
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/pow.hpp579
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/trig.hpp740
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/trunc.hpp76
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/generic_interconvert.hpp508
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/hash.hpp56
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/integer_ops.hpp317
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/min_max.hpp72
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/no_et_ops.hpp1241
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/no_exceptions_support.hpp55
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_base.hpp1729
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_compare.hpp676
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/precision.hpp313
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/rebind.hpp19
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/standalone_config.hpp114
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/ublas_interop.hpp54
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/integer.hpp363
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/number.hpp1747
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/rational_adaptor.hpp1359
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/explicit_conversion.hpp111
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_backend.hpp124
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_byte_container.hpp50
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_complex.hpp22
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_convertible_arithmetic.hpp51
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_restricted_conversion.hpp53
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_variable_precision.hpp25
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/max_digits10.hpp79
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/std_integer_traits.hpp72
-rw-r--r--contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/transcendental_reduction_type.hpp21
136 files changed, 24217 insertions, 16359 deletions
diff --git a/contrib/restricted/boost/boost/coroutine/all.hpp b/contrib/restricted/boost/boost/coroutine/all.hpp
deleted file mode 100644
index 42f63a0a73..0000000000
--- a/contrib/restricted/boost/boost/coroutine/all.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_ALL_H
-#define BOOST_COROUTINES_ALL_H
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/coroutine.hpp>
-#include <boost/coroutine/exceptions.hpp>
-#include <boost/coroutine/flags.hpp>
-#include <boost/coroutine/protected_stack_allocator.hpp>
-#include <boost/coroutine/segmented_stack_allocator.hpp>
-#include <boost/coroutine/stack_allocator.hpp>
-#include <boost/coroutine/stack_context.hpp>
-#include <boost/coroutine/stack_traits.hpp>
-#include <boost/coroutine/standard_stack_allocator.hpp>
-
-#endif // BOOST_COROUTINES_ALL_H
diff --git a/contrib/restricted/boost/boost/coroutine/asymmetric_coroutine.hpp b/contrib/restricted/boost/boost/coroutine/asymmetric_coroutine.hpp
deleted file mode 100644
index 18ab43f761..0000000000
--- a/contrib/restricted/boost/boost/coroutine/asymmetric_coroutine.hpp
+++ /dev/null
@@ -1,2416 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_ASYMMETRIC_COROUTINE_H
-#define BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H
-
-#ifndef BOOST_COROUTINES_NO_DEPRECATION_WARNING
-# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
-//# pragma message ("Warning: Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING.")
-# elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
-//# warning "Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING."
-# endif
-#endif
-
-#include <cstddef>
-#include <iterator>
-#include <memory>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-#include <boost/range.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/utility/explicit_operator_bool.hpp>
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/parameters.hpp>
-#include <boost/coroutine/exceptions.hpp>
-#include <boost/coroutine/stack_allocator.hpp>
-#include <boost/coroutine/detail/pull_coroutine_impl.hpp>
-#include <boost/coroutine/detail/pull_coroutine_object.hpp>
-#include <boost/coroutine/detail/pull_coroutine_synthesized.hpp>
-#include <boost/coroutine/detail/push_coroutine_impl.hpp>
-#include <boost/coroutine/detail/push_coroutine_object.hpp>
-#include <boost/coroutine/detail/push_coroutine_synthesized.hpp>
-#include <boost/coroutine/stack_context.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-template< typename R >
-class pull_coroutine;
-
-template< typename Arg >
-class push_coroutine
-{
-private:
- template< typename V, typename X, typename Y, typename Z >
- friend class detail::pull_coroutine_object;
-
- typedef detail::push_coroutine_impl< Arg > impl_type;
- typedef detail::push_coroutine_synthesized< Arg > synth_type;
- typedef detail::parameters< Arg > param_type;
-
- struct dummy {};
-
- impl_type * impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
-
- explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
- impl_( & impl)
- { BOOST_ASSERT( impl_); }
-
-public:
- push_coroutine() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- typedef void ( * coroutine_fn)( pull_coroutine< Arg > &);
-
- explicit push_coroutine( coroutine_fn,
- attributes const& = attributes() );
-
- template< typename StackAllocator >
- explicit push_coroutine( coroutine_fn,
- attributes const&,
- StackAllocator);
-# endif
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const& = attributes() );
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const&,
- StackAllocator);
-#else
- template< typename Fn >
- explicit push_coroutine( Fn fn,
- attributes const& = attributes() );
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( Fn fn,
- attributes const&,
- StackAllocator);
-
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const& = attributes() );
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const&,
- StackAllocator);
-#endif
-
- ~push_coroutine()
- {
- if ( 0 != impl_)
- {
- impl_->destroy();
- impl_ = 0;
- }
- }
-
- push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
- {
- push_coroutine tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_ || impl_->is_complete(); }
-
- void swap( push_coroutine & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- push_coroutine & operator()( Arg arg)
- {
- BOOST_ASSERT( * this);
-
- impl_->push( arg);
- return * this;
- }
-
- class iterator
- {
- private:
- push_coroutine< Arg > * c_;
-
- public:
- typedef std::output_iterator_tag iterator_category;
- typedef void value_type;
- typedef void difference_type;
- typedef void pointer;
- typedef void reference;
-
- iterator() :
- c_( 0)
- {}
-
- explicit iterator( push_coroutine< Arg > * c) :
- c_( c)
- {}
-
- iterator & operator=( Arg a)
- {
- BOOST_ASSERT( c_);
- if ( ! ( * c_)( a) ) c_ = 0;
- return * this;
- }
-
- bool operator==( iterator const& other) const
- { return other.c_ == c_; }
-
- bool operator!=( iterator const& other) const
- { return other.c_ != c_; }
-
- iterator & operator*()
- { return * this; }
-
- iterator & operator++()
- { return * this; }
- };
-
- struct const_iterator;
-};
-
-template< typename Arg >
-class push_coroutine< Arg & >
-{
-private:
- template< typename V, typename X, typename Y, typename Z >
- friend class detail::pull_coroutine_object;
-
- typedef detail::push_coroutine_impl< Arg & > impl_type;
- typedef detail::push_coroutine_synthesized< Arg & > synth_type;
- typedef detail::parameters< Arg & > param_type;
-
- struct dummy {};
-
- impl_type * impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
-
- explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
- impl_( & impl)
- { BOOST_ASSERT( impl_); }
-
-public:
- push_coroutine() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- typedef void ( * coroutine_fn)( pull_coroutine< Arg & > &);
-
- explicit push_coroutine( coroutine_fn,
- attributes const& = attributes() );
-
- template< typename StackAllocator >
- explicit push_coroutine( coroutine_fn,
- attributes const&,
- StackAllocator);
-# endif
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const& = attributes() );
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const&,
- StackAllocator);
-#else
- template< typename Fn >
- explicit push_coroutine( Fn,
- attributes const& = attributes() );
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( Fn,
- attributes const&,
- StackAllocator);
-
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const& = attributes() );
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const&,
- StackAllocator);
-#endif
-
- ~push_coroutine()
- {
- if ( 0 != impl_)
- {
- impl_->destroy();
- impl_ = 0;
- }
- }
-
- push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
- {
- push_coroutine tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_ || impl_->is_complete(); }
-
- void swap( push_coroutine & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- push_coroutine & operator()( Arg & arg)
- {
- BOOST_ASSERT( * this);
-
- impl_->push( arg);
- return * this;
- }
-
- class iterator
- {
- private:
- push_coroutine< Arg & > * c_;
-
- public:
- typedef std::output_iterator_tag iterator_category;
- typedef void value_type;
- typedef void difference_type;
- typedef void pointer;
- typedef void reference;
-
- iterator() :
- c_( 0)
- {}
-
- explicit iterator( push_coroutine< Arg & > * c) :
- c_( c)
- {}
-
- iterator & operator=( Arg & a)
- {
- BOOST_ASSERT( c_);
- if ( ! ( * c_)( a) ) c_ = 0;
- return * this;
- }
-
- bool operator==( iterator const& other) const
- { return other.c_ == c_; }
-
- bool operator!=( iterator const& other) const
- { return other.c_ != c_; }
-
- iterator & operator*()
- { return * this; }
-
- iterator & operator++()
- { return * this; }
- };
-
- struct const_iterator;
-};
-
-template<>
-class push_coroutine< void >
-{
-private:
- template< typename V, typename X, typename Y, typename Z >
- friend class detail::pull_coroutine_object;
-
- typedef detail::push_coroutine_impl< void > impl_type;
- typedef detail::push_coroutine_synthesized< void > synth_type;
- typedef detail::parameters< void > param_type;
-
- struct dummy {};
-
- impl_type * impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
-
- explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
- impl_( & impl)
- { BOOST_ASSERT( impl_); }
-
-public:
- push_coroutine() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- typedef void ( * coroutine_fn)( pull_coroutine< void > &);
-
- explicit push_coroutine( coroutine_fn,
- attributes const& = attributes() );
-
- template< typename StackAllocator >
- explicit push_coroutine( coroutine_fn,
- attributes const&,
- StackAllocator);
-# endif
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const& = attributes() );
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const&,
- StackAllocator);
-#else
- template< typename Fn >
- explicit push_coroutine( Fn,
- attributes const& = attributes() );
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( Fn,
- attributes const&,
- StackAllocator);
-
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const& = attributes() );
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn),
- attributes const&,
- StackAllocator);
-#endif
-
- ~push_coroutine()
- {
- if ( 0 != impl_)
- {
- impl_->destroy();
- impl_ = 0;
- }
- }
-
- inline push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- inline push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
- {
- push_coroutine tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- inline bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_ || impl_->is_complete(); }
-
- inline void swap( push_coroutine & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- inline push_coroutine & operator()()
- {
- BOOST_ASSERT( * this);
-
- impl_->push();
- return * this;
- }
-
- struct iterator;
- struct const_iterator;
-};
-
-
-
-template< typename R >
-class pull_coroutine
-{
-private:
- template< typename V, typename X, typename Y, typename Z >
- friend class detail::push_coroutine_object;
-
- typedef detail::pull_coroutine_impl< R > impl_type;
- typedef detail::pull_coroutine_synthesized< R > synth_type;
- typedef detail::parameters< R > param_type;
-
- struct dummy {};
-
- impl_type * impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
-
- explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
- impl_( & impl)
- { BOOST_ASSERT( impl_); }
-
-public:
- pull_coroutine() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- typedef void ( * coroutine_fn)( push_coroutine< R > &);
-
- explicit pull_coroutine( coroutine_fn fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R >, R, coroutine_fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename StackAllocator >
- explicit pull_coroutine( coroutine_fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R >, R, coroutine_fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-# endif
- template< typename Fn >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R >, R, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R >, R, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-#else
- template< typename Fn >
- explicit pull_coroutine( Fn fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R >, R, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( Fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R >, R, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R >, R, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R >, R, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-#endif
-
- ~pull_coroutine()
- {
- if ( 0 != impl_)
- {
- impl_->destroy();
- impl_ = 0;
- }
- }
-
- pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
- {
- pull_coroutine tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_ || impl_->is_complete(); }
-
- void swap( pull_coroutine & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- pull_coroutine & operator()()
- {
- BOOST_ASSERT( * this);
-
- impl_->pull();
- return * this;
- }
-
- R get() const
- {
- BOOST_ASSERT( 0 != impl_);
-
- return impl_->get();
- }
-
- class iterator
- {
- private:
- pull_coroutine< R > * c_;
- R * val_;
-
- void fetch_()
- {
- BOOST_ASSERT( c_);
-
- if ( ! ( * c_) )
- {
- c_ = 0;
- val_ = 0;
- return;
- }
- val_ = c_->impl_->get_pointer();
- }
-
- void increment_()
- {
- BOOST_ASSERT( c_);
- BOOST_ASSERT( * c_);
-
- ( * c_)();
- fetch_();
- }
-
- public:
- typedef std::input_iterator_tag iterator_category;
- typedef typename remove_reference< R >::type value_type;
- typedef std::ptrdiff_t difference_type;
- typedef value_type * pointer;
- typedef value_type & reference;
-
- typedef pointer pointer_t;
- typedef reference reference_t;
-
- iterator() :
- c_( 0), val_( 0)
- {}
-
- explicit iterator( pull_coroutine< R > * c) :
- c_( c), val_( 0)
- { fetch_(); }
-
- iterator( iterator const& other) :
- c_( other.c_), val_( other.val_)
- {}
-
- iterator & operator=( iterator const& other)
- {
- if ( this == & other) return * this;
- c_ = other.c_;
- val_ = other.val_;
- return * this;
- }
-
- bool operator==( iterator const& other) const
- { return other.c_ == c_ && other.val_ == val_; }
-
- bool operator!=( iterator const& other) const
- { return other.c_ != c_ || other.val_ != val_; }
-
- iterator & operator++()
- {
- increment_();
- return * this;
- }
-
- iterator operator++( int);
-
- reference_t operator*() const
- {
- if ( ! val_)
- boost::throw_exception(
- invalid_result() );
- return * val_;
- }
-
- pointer_t operator->() const
- {
- if ( ! val_)
- boost::throw_exception(
- invalid_result() );
- return val_;
- }
- };
-
- class const_iterator
- {
- private:
- pull_coroutine< R > * c_;
- R * val_;
-
- void fetch_()
- {
- BOOST_ASSERT( c_);
-
- if ( ! ( * c_) )
- {
- c_ = 0;
- val_ = 0;
- return;
- }
- val_ = c_->impl_->get_pointer();
- }
-
- void increment_()
- {
- BOOST_ASSERT( c_);
- BOOST_ASSERT( * c_);
-
- ( * c_)();
- fetch_();
- }
-
- public:
- typedef std::input_iterator_tag iterator_category;
- typedef const typename remove_reference< R >::type value_type;
- typedef std::ptrdiff_t difference_type;
- typedef value_type * pointer;
- typedef value_type & reference;
-
- typedef pointer pointer_t;
- typedef reference reference_t;
-
- const_iterator() :
- c_( 0), val_( 0)
- {}
-
- explicit const_iterator( pull_coroutine< R > const* c) :
- c_( const_cast< pull_coroutine< R > * >( c) ),
- val_( 0)
- { fetch_(); }
-
- const_iterator( const_iterator const& other) :
- c_( other.c_), val_( other.val_)
- {}
-
- const_iterator & operator=( const_iterator const& other)
- {
- if ( this == & other) return * this;
- c_ = other.c_;
- val_ = other.val_;
- return * this;
- }
-
- bool operator==( const_iterator const& other) const
- { return other.c_ == c_ && other.val_ == val_; }
-
- bool operator!=( const_iterator const& other) const
- { return other.c_ != c_ || other.val_ != val_; }
-
- const_iterator & operator++()
- {
- increment_();
- return * this;
- }
-
- const_iterator operator++( int);
-
- reference_t operator*() const
- {
- if ( ! val_)
- boost::throw_exception(
- invalid_result() );
- return * val_;
- }
-
- pointer_t operator->() const
- {
- if ( ! val_)
- boost::throw_exception(
- invalid_result() );
- return val_;
- }
- };
-
- friend class iterator;
- friend class const_iterator;
-};
-
-template< typename R >
-class pull_coroutine< R & >
-{
-private:
- template< typename V, typename X, typename Y, typename Z >
- friend class detail::push_coroutine_object;
-
- typedef detail::pull_coroutine_impl< R & > impl_type;
- typedef detail::pull_coroutine_synthesized< R & > synth_type;
- typedef detail::parameters< R & > param_type;
-
- struct dummy {};
-
- impl_type * impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
-
- explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
- impl_( & impl)
- { BOOST_ASSERT( impl_); }
-
-public:
- pull_coroutine() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- typedef void ( * coroutine_fn)( push_coroutine< R & > &);
-
- explicit pull_coroutine( coroutine_fn fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R & >, R &, coroutine_fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename StackAllocator >
- explicit pull_coroutine( coroutine_fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R & >, R &, coroutine_fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-# endif
- template< typename Fn >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R & >, R &, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R & >, R &, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-#else
- template< typename Fn >
- explicit pull_coroutine( Fn fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R & >, R &, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( Fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R & >, R &, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R & >, R &, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< R & >, R &, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-#endif
-
- ~pull_coroutine()
- {
- if ( 0 != impl_)
- {
- impl_->destroy();
- impl_ = 0;
- }
- }
-
- pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
- {
- pull_coroutine tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_ || impl_->is_complete(); }
-
- void swap( pull_coroutine & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- pull_coroutine & operator()()
- {
- BOOST_ASSERT( * this);
-
- impl_->pull();
- return * this;
- }
-
- R & get() const
- { return impl_->get(); }
-
- class iterator
- {
- private:
- pull_coroutine< R & > * c_;
- R * val_;
-
- void fetch_()
- {
- BOOST_ASSERT( c_);
-
- if ( ! ( * c_) )
- {
- c_ = 0;
- val_ = 0;
- return;
- }
- val_ = c_->impl_->get_pointer();
- }
-
- void increment_()
- {
- BOOST_ASSERT( c_);
- BOOST_ASSERT( * c_);
-
- ( * c_)();
- fetch_();
- }
-
- public:
- typedef std::input_iterator_tag iterator_category;
- typedef typename remove_reference< R >::type value_type;
- typedef std::ptrdiff_t difference_type;
- typedef value_type * pointer;
- typedef value_type & reference;
-
- typedef pointer pointer_t;
- typedef reference reference_t;
-
- iterator() :
- c_( 0), val_( 0)
- {}
-
- explicit iterator( pull_coroutine< R & > * c) :
- c_( c), val_( 0)
- { fetch_(); }
-
- iterator( iterator const& other) :
- c_( other.c_), val_( other.val_)
- {}
-
- iterator & operator=( iterator const& other)
- {
- if ( this == & other) return * this;
- c_ = other.c_;
- val_ = other.val_;
- return * this;
- }
-
- bool operator==( iterator const& other) const
- { return other.c_ == c_ && other.val_ == val_; }
-
- bool operator!=( iterator const& other) const
- { return other.c_ != c_ || other.val_ != val_; }
-
- iterator & operator++()
- {
- increment_();
- return * this;
- }
-
- iterator operator++( int);
-
- reference_t operator*() const
- {
- if ( ! val_)
- boost::throw_exception(
- invalid_result() );
- return * val_;
- }
-
- pointer_t operator->() const
- {
- if ( ! val_)
- boost::throw_exception(
- invalid_result() );
- return val_;
- }
- };
-
- class const_iterator
- {
- private:
- pull_coroutine< R & > * c_;
- R * val_;
-
- void fetch_()
- {
- BOOST_ASSERT( c_);
-
- if ( ! ( * c_) )
- {
- c_ = 0;
- val_ = 0;
- return;
- }
- val_ = c_->impl_->get_pointer();
- }
-
- void increment_()
- {
- BOOST_ASSERT( c_);
- BOOST_ASSERT( * c_);
-
- ( * c_)();
- fetch_();
- }
-
- public:
- typedef std::input_iterator_tag iterator_category;
- typedef const typename remove_reference< R >::type value_type;
- typedef std::ptrdiff_t difference_type;
- typedef value_type * pointer;
- typedef value_type & reference;
-
- typedef pointer pointer_t;
- typedef reference reference_t;
-
- const_iterator() :
- c_( 0), val_( 0)
- {}
-
- explicit const_iterator( pull_coroutine< R & > const* c) :
- c_( const_cast< pull_coroutine< R & > * >( c) ),
- val_( 0)
- { fetch_(); }
-
- const_iterator( const_iterator const& other) :
- c_( other.c_), val_( other.val_)
- {}
-
- const_iterator & operator=( const_iterator const& other)
- {
- if ( this == & other) return * this;
- c_ = other.c_;
- val_ = other.val_;
- return * this;
- }
-
- bool operator==( const_iterator const& other) const
- { return other.c_ == c_ && other.val_ == val_; }
-
- bool operator!=( const_iterator const& other) const
- { return other.c_ != c_ || other.val_ != val_; }
-
- const_iterator & operator++()
- {
- increment_();
- return * this;
- }
-
- const_iterator operator++( int);
-
- reference_t operator*() const
- {
- if ( ! val_)
- boost::throw_exception(
- invalid_result() );
- return * val_;
- }
-
- pointer_t operator->() const
- {
- if ( ! val_)
- boost::throw_exception(
- invalid_result() );
- return val_;
- }
- };
-
- friend class iterator;
- friend class const_iterator;
-};
-
-template<>
-class pull_coroutine< void >
-{
-private:
- template< typename V, typename X, typename Y, typename Z >
- friend class detail::push_coroutine_object;
-
- typedef detail::pull_coroutine_impl< void > impl_type;
- typedef detail::pull_coroutine_synthesized< void > synth_type;
- typedef detail::parameters< void > param_type;
-
- struct dummy {};
-
- impl_type * impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
-
- explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
- impl_( & impl)
- { BOOST_ASSERT( impl_); }
-
-public:
- pull_coroutine() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- typedef void ( * coroutine_fn)( push_coroutine< void > &);
-
- explicit pull_coroutine( coroutine_fn fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< void >, void, coroutine_fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename StackAllocator >
- explicit pull_coroutine( coroutine_fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< void >, void, coroutine_fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-# endif
- template< typename Fn >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< void >, void, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< void >, void, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-#else
- template< typename Fn >
- explicit pull_coroutine( Fn fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< void >, void, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( Fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< void >, void, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< void >, void, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::pull_coroutine_object<
- push_coroutine< void >, void, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- impl_->pull();
- }
-#endif
-
- ~pull_coroutine()
- {
- if ( 0 != impl_)
- {
- impl_->destroy();
- impl_ = 0;
- }
- }
-
- inline pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- inline pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
- {
- pull_coroutine tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- inline bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_ || impl_->is_complete(); }
-
- inline void swap( pull_coroutine & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- inline pull_coroutine & operator()()
- {
- BOOST_ASSERT( * this);
-
- impl_->pull();
- return * this;
- }
-
- struct iterator;
- struct const_iterator;
-};
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
-template< typename Arg >
-push_coroutine< Arg >::push_coroutine( coroutine_fn fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg >, Arg, coroutine_fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename StackAllocator >
-push_coroutine< Arg >::push_coroutine( coroutine_fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg >, Arg, coroutine_fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-push_coroutine< Arg & >::push_coroutine( coroutine_fn fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg & >, Arg &, coroutine_fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename StackAllocator >
-push_coroutine< Arg & >::push_coroutine( coroutine_fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg & >, Arg &, coroutine_fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-inline push_coroutine< void >::push_coroutine( coroutine_fn fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< void >, void, coroutine_fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename StackAllocator >
-push_coroutine< void >::push_coroutine( coroutine_fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< void >, void, coroutine_fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-# endif
-template< typename Arg >
-template< typename Fn >
-push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg >, Arg, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator >
-push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg >, Arg, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn >
-push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator >
-push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Fn >
-push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< void >, void, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Fn, typename StackAllocator >
-push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< void >, void, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-#else
-template< typename Arg >
-template< typename Fn >
-push_coroutine< Arg >::push_coroutine( Fn fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg >, Arg, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator >
-push_coroutine< Arg >::push_coroutine( Fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg >, Arg, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn >
-push_coroutine< Arg & >::push_coroutine( Fn fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator >
-push_coroutine< Arg & >::push_coroutine( Fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Fn >
-push_coroutine< void >::push_coroutine( Fn fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< void >, void, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Fn, typename StackAllocator >
-push_coroutine< void >::push_coroutine( Fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< void >, void, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn >
-push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg >, Arg, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator >
-push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg >, Arg, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn >
-push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator >
-push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Fn >
-push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- stack_allocator stack_alloc;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< void >, void, Fn, stack_allocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-
-template< typename Fn, typename StackAllocator >
-push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
-{
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef detail::push_coroutine_object<
- pull_coroutine< void >, void, Fn, StackAllocator
- > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
-}
-#endif
-
-template< typename R >
-void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT
-{ l.swap( r); }
-
-template< typename Arg >
-void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT
-{ l.swap( r); }
-
-template< typename R >
-typename pull_coroutine< R >::iterator
-range_begin( pull_coroutine< R > & c)
-{ return typename pull_coroutine< R >::iterator( & c); }
-
-template< typename R >
-typename pull_coroutine< R >::const_iterator
-range_begin( pull_coroutine< R > const& c)
-{ return typename pull_coroutine< R >::const_iterator( & c); }
-
-template< typename R >
-typename pull_coroutine< R >::iterator
-range_end( pull_coroutine< R > &)
-{ return typename pull_coroutine< R >::iterator(); }
-
-template< typename R >
-typename pull_coroutine< R >::const_iterator
-range_end( pull_coroutine< R > const&)
-{ return typename pull_coroutine< R >::const_iterator(); }
-
-template< typename Arg >
-typename push_coroutine< Arg >::iterator
-range_begin( push_coroutine< Arg > & c)
-{ return typename push_coroutine< Arg >::iterator( & c); }
-
-template< typename Arg >
-typename push_coroutine< Arg >::iterator
-range_end( push_coroutine< Arg > &)
-{ return typename push_coroutine< Arg >::iterator(); }
-
-template< typename T >
-struct asymmetric_coroutine
-{
- typedef push_coroutine< T > push_type;
- typedef pull_coroutine< T > pull_type;
-};
-
-// deprecated
-template< typename T >
-struct coroutine
-{
- typedef push_coroutine< T > push_type;
- typedef pull_coroutine< T > pull_type;
-};
-
-template< typename R >
-typename pull_coroutine< R >::iterator
-begin( pull_coroutine< R > & c)
-{ return boost::begin( c); }
-
-template< typename R >
-typename pull_coroutine< R >::const_iterator
-begin( pull_coroutine< R > const& c)
-{ return boost::begin( c); }
-
-template< typename R >
-typename pull_coroutine< R >::iterator
-end( pull_coroutine< R > & c)
-{ return boost::end( c); }
-
-template< typename R >
-typename pull_coroutine< R >::const_iterator
-end( pull_coroutine< R > const& c)
-{ return boost::end( c); }
-
-template< typename R >
-typename push_coroutine< R >::iterator
-begin( push_coroutine< R > & c)
-{ return boost::begin( c); }
-
-template< typename R >
-typename push_coroutine< R >::iterator
-end( push_coroutine< R > & c)
-{ return boost::end( c); }
-
-}
-
-template< typename Arg >
-struct range_mutable_iterator< coroutines::push_coroutine< Arg > >
-{ typedef typename coroutines::push_coroutine< Arg >::iterator type; };
-
-template< typename R >
-struct range_mutable_iterator< coroutines::pull_coroutine< R > >
-{ typedef typename coroutines::pull_coroutine< R >::iterator type; };
-
-}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H
diff --git a/contrib/restricted/boost/boost/coroutine/attributes.hpp b/contrib/restricted/boost/boost/coroutine/attributes.hpp
deleted file mode 100644
index ca712ee68d..0000000000
--- a/contrib/restricted/boost/boost/coroutine/attributes.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_ATTRIBUTES_H
-#define BOOST_COROUTINES_ATTRIBUTES_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-
-#include <boost/coroutine/flags.hpp>
-#include <boost/coroutine/stack_allocator.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-struct attributes
-{
- std::size_t size;
- flag_unwind_t do_unwind;
-
- attributes() BOOST_NOEXCEPT :
- size( stack_allocator::traits_type::default_size() ),
- do_unwind( stack_unwind)
- {}
-
- explicit attributes( std::size_t size_) BOOST_NOEXCEPT :
- size( size_),
- do_unwind( stack_unwind)
- {}
-
- explicit attributes( flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
- size( stack_allocator::traits_type::default_size() ),
- do_unwind( do_unwind_)
- {}
-
- explicit attributes(
- std::size_t size_,
- flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
- size( size_),
- do_unwind( do_unwind_)
- {}
-};
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_ATTRIBUTES_H
diff --git a/contrib/restricted/boost/boost/coroutine/coroutine.hpp b/contrib/restricted/boost/boost/coroutine/coroutine.hpp
deleted file mode 100644
index 076ffd26ea..0000000000
--- a/contrib/restricted/boost/boost/coroutine/coroutine.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_COROUTINE_H
-#define BOOST_COROUTINES_COROUTINE_H
-
-#include <boost/coroutine/asymmetric_coroutine.hpp>
-#include <boost/coroutine/symmetric_coroutine.hpp>
-
-#endif // BOOST_COROUTINES_COROUTINE_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/flags.hpp b/contrib/restricted/boost/boost/coroutine/detail/flags.hpp
deleted file mode 100644
index 2078b62362..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/flags.hpp
+++ /dev/null
@@ -1,47 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_FLAGS_H
-#define BOOST_COROUTINES_DETAIL_FLAGS_H
-
-#include <boost/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-enum flag_t
-{
- flag_started = 1 << 1,
- flag_running = 1 << 2,
- flag_complete = 1 << 3,
- flag_unwind_stack = 1 << 4,
- flag_force_unwind = 1 << 5
-};
-
-struct unwind_t
-{
- enum flag_t
- { force_unwind = 1 };
-};
-
-struct synthesized_t
-{
- enum flag_t
- { syntesized = 1 };
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_FLAGS_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/parameters.hpp b/contrib/restricted/boost/boost/coroutine/detail/parameters.hpp
deleted file mode 100644
index 8bad3910a9..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/parameters.hpp
+++ /dev/null
@@ -1,102 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_PARAMETERS_H
-#define BOOST_COROUTINES_DETAIL_PARAMETERS_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/coroutine/detail/flags.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename Data >
-struct parameters
-{
- Data * data;
- bool do_unwind;
- void * coro;
-
- parameters() :
- data( 0), do_unwind( false), coro( 0)
- {}
-
- explicit parameters( void * coro_) :
- data( 0), do_unwind( false), coro( coro_)
- { BOOST_ASSERT( 0 != coro); }
-
- explicit parameters( Data * data_, void * coro_) :
- data( data_), do_unwind( false), coro( coro_)
- {
- BOOST_ASSERT( 0 != data);
- BOOST_ASSERT( 0 != coro);
- }
-
- explicit parameters( unwind_t::flag_t) :
- data( 0), do_unwind( true)
- {}
-};
-
-template< typename Data >
-struct parameters< Data & >
-{
- Data * data;
- bool do_unwind;
- void * coro;
-
- parameters() :
- data( 0), do_unwind( false), coro( 0)
- {}
-
- explicit parameters( void * coro_) :
- data( 0), do_unwind( false), coro( coro_)
- { BOOST_ASSERT( 0 != coro); }
-
- explicit parameters( Data * data_, void * coro_) :
- data( data_), do_unwind( false), coro( coro_)
- {
- BOOST_ASSERT( 0 != data);
- BOOST_ASSERT( 0 != coro);
- }
-
- explicit parameters( unwind_t::flag_t) :
- data( 0), do_unwind( true), coro( 0)
- {}
-};
-
-template<>
-struct parameters< void >
-{
- bool do_unwind;
- void * coro;
-
- parameters() :
- do_unwind( false), coro(0)
- {}
-
- parameters( void * coro_) :
- do_unwind( false), coro( coro_)
- { BOOST_ASSERT( 0 != coro); }
-
- explicit parameters( unwind_t::flag_t) :
- do_unwind( true), coro( 0)
- {}
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_PARAMETERS_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_impl.hpp b/contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_impl.hpp
deleted file mode 100644
index e35b7894e2..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_impl.hpp
+++ /dev/null
@@ -1,335 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
-#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/exception_ptr.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-#include <boost/coroutine/detail/parameters.hpp>
-#include <boost/coroutine/detail/trampoline_pull.hpp>
-#include <boost/coroutine/exceptions.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-struct stack_context;
-
-namespace detail {
-
-template< typename R >
-class pull_coroutine_impl : private noncopyable
-{
-protected:
- int flags_;
- exception_ptr except_;
- coroutine_context * caller_;
- coroutine_context * callee_;
- R * result_;
-
-public:
- typedef parameters< R > param_type;
-
- pull_coroutine_impl( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- flags_( 0),
- except_(),
- caller_( caller),
- callee_( callee),
- result_( 0)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- pull_coroutine_impl( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind,
- R * result) :
- flags_( 0),
- except_(),
- caller_( caller),
- callee_( callee),
- result_( result)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- virtual ~pull_coroutine_impl() {}
-
- bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- bool is_started() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_started); }
-
- bool is_running() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_running); }
-
- bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- void unwind_stack() BOOST_NOEXCEPT
- {
- if ( is_started() && ! is_complete() && force_unwind() )
- {
- flags_ |= flag_unwind_stack;
- param_type to( unwind_t::force_unwind);
- caller_->jump(
- * callee_,
- & to);
- flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( is_complete() );
- }
- }
-
- void pull()
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ |= flag_running;
- param_type to( this);
- param_type * from(
- static_cast< param_type * >(
- caller_->jump(
- * callee_,
- & to) ) );
- flags_ &= ~flag_running;
- result_ = from->data;
- if ( from->do_unwind) throw forced_unwind();
- if ( except_) rethrow_exception( except_);
- }
-
- bool has_result() const
- { return 0 != result_; }
-
- R get() const
- {
- if ( ! has_result() )
- boost::throw_exception(
- invalid_result() );
- return * result_;
- }
-
- R * get_pointer() const
- {
- if ( ! has_result() )
- boost::throw_exception(
- invalid_result() );
- return result_;
- }
-
- virtual void destroy() = 0;
-};
-
-template< typename R >
-class pull_coroutine_impl< R & > : private noncopyable
-{
-protected:
- int flags_;
- exception_ptr except_;
- coroutine_context * caller_;
- coroutine_context * callee_;
- R * result_;
-
-public:
- typedef parameters< R & > param_type;
-
- pull_coroutine_impl( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- flags_( 0),
- except_(),
- caller_( caller),
- callee_( callee),
- result_( 0)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- pull_coroutine_impl( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind,
- R * result) :
- flags_( 0),
- except_(),
- caller_( caller),
- callee_( callee),
- result_( result)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- virtual ~pull_coroutine_impl() {}
-
- bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- bool is_started() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_started); }
-
- bool is_running() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_running); }
-
- bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- void unwind_stack() BOOST_NOEXCEPT
- {
- if ( is_started() && ! is_complete() && force_unwind() )
- {
- flags_ |= flag_unwind_stack;
- param_type to( unwind_t::force_unwind);
- caller_->jump(
- * callee_,
- & to);
- flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( is_complete() );
- }
- }
-
- void pull()
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ |= flag_running;
- param_type to( this);
- param_type * from(
- static_cast< param_type * >(
- caller_->jump(
- * callee_,
- & to) ) );
- flags_ &= ~flag_running;
- result_ = from->data;
- if ( from->do_unwind) throw forced_unwind();
- if ( except_) rethrow_exception( except_);
- }
-
- bool has_result() const
- { return 0 != result_; }
-
- R & get() const
- {
- if ( ! has_result() )
- boost::throw_exception(
- invalid_result() );
- return * result_;
- }
-
- R * get_pointer() const
- {
- if ( ! has_result() )
- boost::throw_exception(
- invalid_result() );
- return result_;
- }
-
- virtual void destroy() = 0;
-};
-
-template<>
-class pull_coroutine_impl< void > : private noncopyable
-{
-protected:
- int flags_;
- exception_ptr except_;
- coroutine_context * caller_;
- coroutine_context * callee_;
-
-public:
- typedef parameters< void > param_type;
-
- pull_coroutine_impl( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- flags_( 0),
- except_(),
- caller_( caller),
- callee_( callee)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- virtual ~pull_coroutine_impl() {}
-
- inline bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- inline bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- inline bool is_started() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_started); }
-
- inline bool is_running() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_running); }
-
- inline bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- inline void unwind_stack() BOOST_NOEXCEPT
- {
- if ( is_started() && ! is_complete() && force_unwind() )
- {
- flags_ |= flag_unwind_stack;
- param_type to( unwind_t::force_unwind);
- caller_->jump(
- * callee_,
- & to);
- flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( is_complete() );
- }
- }
-
- inline void pull()
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ |= flag_running;
- param_type to( this);
- param_type * from(
- static_cast< param_type * >(
- caller_->jump(
- * callee_,
- & to) ) );
- flags_ &= ~flag_running;
- if ( from->do_unwind) throw forced_unwind();
- if ( except_) rethrow_exception( except_);
- }
-
- virtual void destroy() = 0;
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_object.hpp b/contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_object.hpp
deleted file mode 100644
index 36918489de..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_object.hpp
+++ /dev/null
@@ -1,310 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
-#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/exception_ptr.hpp>
-#include <boost/move/move.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-#include <boost/coroutine/detail/preallocated.hpp>
-#include <boost/coroutine/detail/pull_coroutine_impl.hpp>
-#include <boost/coroutine/detail/trampoline_pull.hpp>
-#include <boost/coroutine/exceptions.hpp>
-#include <boost/coroutine/flags.hpp>
-#include <boost/coroutine/stack_context.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-#if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable:4355)
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-struct pull_coroutine_context
-{
- coroutine_context caller;
- coroutine_context callee;
-
- template< typename Coro >
- pull_coroutine_context( preallocated const& palloc, Coro *) :
- caller(),
- callee( trampoline_pull< Coro >, palloc)
- {}
-};
-
-template< typename PushCoro, typename R, typename Fn, typename StackAllocator >
-class pull_coroutine_object : private pull_coroutine_context,
- public pull_coroutine_impl< R >
-{
-private:
- typedef pull_coroutine_context ctx_t;
- typedef pull_coroutine_impl< R > base_t;
- typedef pull_coroutine_object< PushCoro, R, Fn, StackAllocator > obj_t;
-
- Fn fn_;
- stack_context stack_ctx_;
- StackAllocator stack_alloc_;
-
- static void deallocate_( obj_t * obj)
- {
- stack_context stack_ctx( obj->stack_ctx_);
- StackAllocator stack_alloc( obj->stack_alloc_);
- obj->unwind_stack();
- obj->~obj_t();
- stack_alloc.deallocate( stack_ctx);
- }
-
-public:
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- pull_coroutine_object( Fn fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
- fn_( fn),
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-#endif
-
- pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn_( fn),
-#else
- fn_( boost::forward< Fn >( fn) ),
-#endif
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-
- void run()
- {
- BOOST_ASSERT( ! base_t::unwind_requested() );
-
- base_t::flags_ |= flag_started;
- base_t::flags_ |= flag_running;
-
- // create push_coroutine
- typename PushCoro::synth_type b( & this->callee, & this->caller, false);
- PushCoro push_coro( synthesized_t::syntesized, b);
- try
- { fn_( push_coro); }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { base_t::except_ = current_exception(); }
-
- base_t::flags_ |= flag_complete;
- base_t::flags_ &= ~flag_running;
- typename base_t::param_type to;
- this->callee.jump(
- this->caller,
- & to);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }
-
- void destroy()
- { deallocate_( this); }
-};
-
-template< typename PushCoro, typename R, typename Fn, typename StackAllocator >
-class pull_coroutine_object< PushCoro, R &, Fn, StackAllocator > : private pull_coroutine_context,
- public pull_coroutine_impl< R & >
-{
-private:
- typedef pull_coroutine_context ctx_t;
- typedef pull_coroutine_impl< R & > base_t;
- typedef pull_coroutine_object< PushCoro, R &, Fn, StackAllocator > obj_t;
-
- Fn fn_;
- stack_context stack_ctx_;
- StackAllocator stack_alloc_;
-
- static void deallocate_( obj_t * obj)
- {
- stack_context stack_ctx( obj->stack_ctx_);
- StackAllocator stack_alloc( obj->stack_alloc_);
- obj->unwind_stack();
- obj->~obj_t();
- stack_alloc.deallocate( stack_ctx);
- }
-
-public:
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- pull_coroutine_object( Fn fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
- fn_( fn),
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-#endif
-
- pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn_( fn),
-#else
- fn_( boost::forward< Fn >( fn) ),
-#endif
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-
- void run()
- {
- BOOST_ASSERT( ! base_t::unwind_requested() );
-
- base_t::flags_ |= flag_started;
- base_t::flags_ |= flag_running;
-
- // create push_coroutine
- typename PushCoro::synth_type b( & this->callee, & this->caller, false);
- PushCoro push_coro( synthesized_t::syntesized, b);
- try
- { fn_( push_coro); }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { base_t::except_ = current_exception(); }
-
- base_t::flags_ |= flag_complete;
- base_t::flags_ &= ~flag_running;
- typename base_t::param_type to;
- this->callee.jump(
- this->caller,
- & to);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }
-
- void destroy()
- { deallocate_( this); }
-};
-
-template< typename PushCoro, typename Fn, typename StackAllocator >
-class pull_coroutine_object< PushCoro, void, Fn, StackAllocator > : private pull_coroutine_context,
- public pull_coroutine_impl< void >
-{
-private:
- typedef pull_coroutine_context ctx_t;
- typedef pull_coroutine_impl< void > base_t;
- typedef pull_coroutine_object< PushCoro, void, Fn, StackAllocator > obj_t;
-
- Fn fn_;
- stack_context stack_ctx_;
- StackAllocator stack_alloc_;
-
- static void deallocate_( obj_t * obj)
- {
- stack_context stack_ctx( obj->stack_ctx_);
- StackAllocator stack_alloc( obj->stack_alloc_);
- obj->unwind_stack();
- obj->~obj_t();
- stack_alloc.deallocate( stack_ctx);
- }
-
-public:
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- pull_coroutine_object( Fn fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
- fn_( fn),
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-#endif
-
- pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn_( fn),
-#else
- fn_( boost::forward< Fn >( fn) ),
-#endif
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-
- void run()
- {
- BOOST_ASSERT( ! base_t::unwind_requested() );
-
- base_t::flags_ |= flag_started;
- base_t::flags_ |= flag_running;
-
- // create push_coroutine
- typename PushCoro::synth_type b( & this->callee, & this->caller, false);
- PushCoro push_coro( synthesized_t::syntesized, b);
- try
- { fn_( push_coro); }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { base_t::except_ = current_exception(); }
-
- base_t::flags_ |= flag_complete;
- base_t::flags_ &= ~flag_running;
- typename base_t::param_type to;
- this->callee.jump(
- this->caller,
- & to);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }
-
- void destroy()
- { deallocate_( this); }
-};
-
-}}}
-
-#if defined(BOOST_MSVC)
-# pragma warning(pop)
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_synthesized.hpp b/contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_synthesized.hpp
deleted file mode 100644
index 313de3c2dd..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/pull_coroutine_synthesized.hpp
+++ /dev/null
@@ -1,80 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_PULL_COROUTINE_SYNTHESIZED_H
-#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_SYNTHESIZED_H
-
-#include <boost/config.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/pull_coroutine_impl.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename R >
-class pull_coroutine_synthesized : public pull_coroutine_impl< R >
-{
-private:
- typedef pull_coroutine_impl< R > impl_t;
-
-public:
- pull_coroutine_synthesized( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind,
- R * result) :
- impl_t( caller, callee, unwind, result)
- {}
-
- void destroy() {}
-};
-
-template< typename R >
-class pull_coroutine_synthesized< R & > : public pull_coroutine_impl< R & >
-{
-private:
- typedef pull_coroutine_impl< R & > impl_t;
-
-public:
- pull_coroutine_synthesized( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind,
- R * result) :
- impl_t( caller, callee, unwind, result)
- {}
-
- void destroy() {}
-};
-
-template<>
-class pull_coroutine_synthesized< void > : public pull_coroutine_impl< void >
-{
-private:
- typedef pull_coroutine_impl< void > impl_t;
-
-public:
- pull_coroutine_synthesized( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- impl_t( caller, callee, unwind)
- {}
-
- inline void destroy() {}
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_SYNTHESIZED_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/push_coroutine_impl.hpp b/contrib/restricted/boost/boost/coroutine/detail/push_coroutine_impl.hpp
deleted file mode 100644
index 21c1df469e..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/push_coroutine_impl.hpp
+++ /dev/null
@@ -1,282 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H
-#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/exception_ptr.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-#include <boost/coroutine/detail/parameters.hpp>
-#include <boost/coroutine/detail/trampoline_push.hpp>
-#include <boost/coroutine/exceptions.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-struct stack_context;
-
-namespace detail {
-
-template< typename Arg >
-class push_coroutine_impl : private noncopyable
-{
-protected:
- int flags_;
- exception_ptr except_;
- coroutine_context * caller_;
- coroutine_context * callee_;
-
-public:
- typedef parameters< Arg > param_type;
-
- push_coroutine_impl( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- flags_( 0),
- except_(),
- caller_( caller),
- callee_( callee)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- virtual ~push_coroutine_impl() {}
-
- bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- bool is_started() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_started); }
-
- bool is_running() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_running); }
-
- bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- void unwind_stack() BOOST_NOEXCEPT
- {
- if ( is_started() && ! is_complete() && force_unwind() )
- {
- flags_ |= flag_unwind_stack;
- param_type to( unwind_t::force_unwind);
- caller_->jump(
- * callee_,
- & to);
- flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( is_complete() );
- }
- }
-
- void push( Arg const& arg)
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ |= flag_running;
- param_type to( const_cast< Arg * >( & arg), this);
- param_type * from(
- static_cast< param_type * >(
- caller_->jump(
- * callee_,
- & to) ) );
- flags_ &= ~flag_running;
- if ( from->do_unwind) throw forced_unwind();
- if ( except_) rethrow_exception( except_);
- }
-
- void push( BOOST_RV_REF( Arg) arg)
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ |= flag_running;
- param_type to( const_cast< Arg * >( & arg), this);
- param_type * from(
- static_cast< param_type * >(
- caller_->jump(
- * callee_,
- & to) ) );
- flags_ &= ~flag_running;
- if ( from->do_unwind) throw forced_unwind();
- if ( except_) rethrow_exception( except_);
- }
-
- virtual void destroy() = 0;
-};
-
-template< typename Arg >
-class push_coroutine_impl< Arg & > : private noncopyable
-{
-protected:
- int flags_;
- exception_ptr except_;
- coroutine_context * caller_;
- coroutine_context * callee_;
-
-public:
- typedef parameters< Arg & > param_type;
-
- push_coroutine_impl( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- flags_( 0),
- except_(),
- caller_( caller),
- callee_( callee)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- virtual ~push_coroutine_impl() {}
-
- bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- bool is_started() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_started); }
-
- bool is_running() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_running); }
-
- bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- void unwind_stack() BOOST_NOEXCEPT
- {
- if ( is_started() && ! is_complete() && force_unwind() )
- {
- flags_ |= flag_unwind_stack;
- param_type to( unwind_t::force_unwind);
- caller_->jump(
- * callee_,
- & to);
- flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( is_complete() );
- }
- }
-
- void push( Arg & arg)
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ |= flag_running;
- param_type to( & arg, this);
- param_type * from(
- static_cast< param_type * >(
- caller_->jump(
- * callee_,
- & to) ) );
- flags_ &= ~flag_running;
- if ( from->do_unwind) throw forced_unwind();
- if ( except_) rethrow_exception( except_);
- }
-
- virtual void destroy() = 0;
-};
-
-template<>
-class push_coroutine_impl< void > : private noncopyable
-{
-protected:
- int flags_;
- exception_ptr except_;
- coroutine_context * caller_;
- coroutine_context * callee_;
-
-public:
- typedef parameters< void > param_type;
-
- push_coroutine_impl( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- flags_( 0),
- except_(),
- caller_( caller),
- callee_( callee)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- virtual ~push_coroutine_impl() {}
-
- inline bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- inline bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- inline bool is_started() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_started); }
-
- inline bool is_running() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_running); }
-
- inline bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- inline void unwind_stack() BOOST_NOEXCEPT
- {
- if ( is_started() && ! is_complete() && force_unwind() )
- {
- flags_ |= flag_unwind_stack;
- param_type to( unwind_t::force_unwind);
- caller_->jump(
- * callee_,
- & to);
- flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( is_complete() );
- }
- }
-
- inline void push()
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ |= flag_running;
- param_type to( this);
- param_type * from(
- static_cast< param_type * >(
- caller_->jump(
- * callee_,
- & to) ) );
- flags_ &= ~flag_running;
- if ( from->do_unwind) throw forced_unwind();
- if ( except_) rethrow_exception( except_);
- }
-
- virtual void destroy() = 0;
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/push_coroutine_object.hpp b/contrib/restricted/boost/boost/coroutine/detail/push_coroutine_object.hpp
deleted file mode 100644
index 9dc87077c2..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/push_coroutine_object.hpp
+++ /dev/null
@@ -1,322 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
-#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/exception_ptr.hpp>
-#include <boost/move/move.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-#include <boost/coroutine/detail/preallocated.hpp>
-#include <boost/coroutine/detail/push_coroutine_impl.hpp>
-#include <boost/coroutine/detail/trampoline_push.hpp>
-#include <boost/coroutine/exceptions.hpp>
-#include <boost/coroutine/flags.hpp>
-#include <boost/coroutine/stack_context.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-#if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable:4355)
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-struct push_coroutine_context
-{
- coroutine_context caller;
- coroutine_context callee;
-
- template< typename Coro >
- push_coroutine_context( preallocated const& palloc, Coro *) :
- caller(),
- callee( trampoline_push< Coro >, palloc)
- {}
-};
-
-struct push_coroutine_context_void
-{
- coroutine_context caller;
- coroutine_context callee;
-
- template< typename Coro >
- push_coroutine_context_void( preallocated const& palloc, Coro *) :
- caller(),
- callee( trampoline_push_void< Coro >, palloc)
- {}
-};
-
-template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
-class push_coroutine_object : private push_coroutine_context,
- public push_coroutine_impl< R >
-{
-private:
- typedef push_coroutine_context ctx_t;
- typedef push_coroutine_impl< R > base_t;
- typedef push_coroutine_object< PullCoro, R, Fn, StackAllocator > obj_t;
-
- Fn fn_;
- stack_context stack_ctx_;
- StackAllocator stack_alloc_;
-
- static void deallocate_( obj_t * obj)
- {
- stack_context stack_ctx( obj->stack_ctx_);
- StackAllocator stack_alloc( obj->stack_alloc_);
- obj->unwind_stack();
- obj->~obj_t();
- stack_alloc.deallocate( stack_ctx);
- }
-
-public:
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- push_coroutine_object( Fn fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
- fn_( fn),
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-#endif
-
- push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn_( fn),
-#else
- fn_( boost::forward< Fn >( fn) ),
-#endif
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-
- void run( R * result)
- {
- BOOST_ASSERT( ! base_t::unwind_requested() );
-
- base_t::flags_ |= flag_started;
- base_t::flags_ |= flag_running;
-
- // create push_coroutine
- typename PullCoro::synth_type b( & this->callee, & this->caller, false, result);
- PullCoro pull_coro( synthesized_t::syntesized, b);
- try
- { fn_( pull_coro); }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { base_t::except_ = current_exception(); }
-
- base_t::flags_ |= flag_complete;
- base_t::flags_ &= ~flag_running;
- typename base_t::param_type to;
- this->callee.jump(
- this->caller,
- & to);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }
-
- void destroy()
- { deallocate_( this); }
-};
-
-template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
-class push_coroutine_object< PullCoro, R &, Fn, StackAllocator > : private push_coroutine_context,
- public push_coroutine_impl< R & >
-{
-private:
- typedef push_coroutine_context ctx_t;
- typedef push_coroutine_impl< R & > base_t;
- typedef push_coroutine_object< PullCoro, R &, Fn, StackAllocator > obj_t;
-
- Fn fn_;
- stack_context stack_ctx_;
- StackAllocator stack_alloc_;
-
- static void deallocate_( obj_t * obj)
- {
- stack_context stack_ctx( obj->stack_ctx_);
- StackAllocator stack_alloc( obj->stack_alloc_);
- obj->unwind_stack();
- obj->~obj_t();
- stack_alloc.deallocate( stack_ctx);
- }
-
-public:
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- push_coroutine_object( Fn fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
- fn_( fn),
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-#endif
-
- push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn_( fn),
-#else
- fn_( boost::forward< Fn >( fn) ),
-#endif
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-
- void run( R * result)
- {
- BOOST_ASSERT( ! base_t::unwind_requested() );
-
- base_t::flags_ |= flag_started;
- base_t::flags_ |= flag_running;
-
- // create push_coroutine
- typename PullCoro::synth_type b( & this->callee, & this->caller, false, result);
- PullCoro push_coro( synthesized_t::syntesized, b);
- try
- { fn_( push_coro); }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { base_t::except_ = current_exception(); }
-
- base_t::flags_ |= flag_complete;
- base_t::flags_ &= ~flag_running;
- typename base_t::param_type to;
- this->callee.jump(
- this->caller,
- & to);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }
-
- void destroy()
- { deallocate_( this); }
-};
-
-template< typename PullCoro, typename Fn, typename StackAllocator >
-class push_coroutine_object< PullCoro, void, Fn, StackAllocator > final : private push_coroutine_context_void,
- public push_coroutine_impl< void >
-{
-private:
- typedef push_coroutine_context_void ctx_t;
- typedef push_coroutine_impl< void > base_t;
- typedef push_coroutine_object< PullCoro, void, Fn, StackAllocator > obj_t;
-
- Fn fn_;
- stack_context stack_ctx_;
- StackAllocator stack_alloc_;
-
- static void deallocate_( obj_t * obj)
- {
- stack_context stack_ctx( obj->stack_ctx_);
- StackAllocator stack_alloc( obj->stack_alloc_);
- obj->unwind_stack();
- obj->~obj_t();
- stack_alloc.deallocate( stack_ctx);
- }
-
-public:
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- push_coroutine_object( Fn fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
- fn_( fn),
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-#endif
-
- push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- ctx_t( palloc, this),
- base_t( & this->caller,
- & this->callee,
- stack_unwind == attrs.do_unwind),
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn_( fn),
-#else
- fn_( boost::forward< Fn >( fn) ),
-#endif
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-
- void run()
- {
- BOOST_ASSERT( ! base_t::unwind_requested() );
-
- base_t::flags_ |= flag_started;
- base_t::flags_ |= flag_running;
-
- // create push_coroutine
- typename PullCoro::synth_type b( & this->callee, & this->caller, false);
- PullCoro push_coro( synthesized_t::syntesized, b);
- try
- { fn_( push_coro); }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { base_t::except_ = current_exception(); }
-
- base_t::flags_ |= flag_complete;
- base_t::flags_ &= ~flag_running;
- typename base_t::param_type to;
- this->callee.jump(
- this->caller,
- & to);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }
-
- void destroy()
- { deallocate_( this); }
-};
-
-}}}
-
-#if defined(BOOST_MSVC)
-# pragma warning(pop)
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/push_coroutine_synthesized.hpp b/contrib/restricted/boost/boost/coroutine/detail/push_coroutine_synthesized.hpp
deleted file mode 100644
index c10a468b9b..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/push_coroutine_synthesized.hpp
+++ /dev/null
@@ -1,78 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_PUSH_COROUTINE_SYNTHESIZED_H
-#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_SYNTHESIZED_H
-
-#include <boost/config.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/push_coroutine_impl.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename R >
-class push_coroutine_synthesized : public push_coroutine_impl< R >
-{
-private:
- typedef push_coroutine_impl< R > impl_t;
-
-public:
- push_coroutine_synthesized( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- impl_t( caller, callee, unwind)
- {}
-
- void destroy() {}
-};
-
-template< typename R >
-class push_coroutine_synthesized< R & > : public push_coroutine_impl< R & >
-{
-private:
- typedef push_coroutine_impl< R & > impl_t;
-
-public:
- push_coroutine_synthesized( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- impl_t( caller, callee, unwind)
- {}
-
- void destroy() {}
-};
-
-template<>
-class push_coroutine_synthesized< void > : public push_coroutine_impl< void >
-{
-private:
- typedef push_coroutine_impl< void > impl_t;
-
-public:
- push_coroutine_synthesized( coroutine_context * caller,
- coroutine_context * callee,
- bool unwind) :
- impl_t( caller, callee, unwind)
- {}
-
- inline void destroy() {}
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_SYNTHESIZED_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/setup.hpp b/contrib/restricted/boost/boost/coroutine/detail/setup.hpp
deleted file mode 100644
index 35f601a779..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/setup.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_SETUP_H
-#define BOOST_COROUTINES_DETAIL_SETUP_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-#include <boost/type_traits/decay.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/is_same.hpp>
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename Fn >
-struct setup
-{
- struct dummy {};
-
- Fn fn;
- coroutine_context * caller;
- coroutine_context * callee;
- attributes attr;
-
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- setup( Fn fn_,
- coroutine_context * caller_,
- coroutine_context * callee_,
- attributes const& attr_) :
- fn( boost::forward< Fn >( fn_) ),
- caller( caller_),
- callee( callee_),
- attr( attr_)
- {}
-#endif
- setup( BOOST_RV_REF( Fn) fn_,
- coroutine_context * caller_,
- coroutine_context * callee_,
- attributes const& attr_,
- typename disable_if<
- is_same< typename decay< Fn >::type, setup >,
- dummy*
- >::type = 0) :
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn( fn_),
-#else
- fn( boost::forward< Fn >( fn_) ),
-#endif
- caller( caller_),
- callee( callee_),
- attr( attr_)
- {}
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_SETUP_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_call.hpp b/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_call.hpp
deleted file mode 100644
index 3a9e4e6f9f..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_call.hpp
+++ /dev/null
@@ -1,811 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H
-#define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-#include <boost/utility/explicit_operator_bool.hpp>
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/preallocated.hpp>
-#include <boost/coroutine/detail/symmetric_coroutine_impl.hpp>
-#include <boost/coroutine/detail/symmetric_coroutine_object.hpp>
-#include <boost/coroutine/detail/symmetric_coroutine_yield.hpp>
-#include <boost/coroutine/stack_allocator.hpp>
-#include <boost/coroutine/stack_context.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename Arg >
-class symmetric_coroutine_call
-{
-private:
- template< typename X >
- friend class symmetric_coroutine_yield;
-
- typedef symmetric_coroutine_impl< Arg > impl_type;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
-
- struct dummy {};
-
- impl_type * impl_;
-
-public:
- typedef Arg value_type;
- typedef symmetric_coroutine_yield< Arg > yield_type;
-
- symmetric_coroutine_call() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- typedef void ( * coroutine_fn)( yield_type &);
-
- explicit symmetric_coroutine_call( coroutine_fn fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg, coroutine_fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename StackAllocator >
- explicit symmetric_coroutine_call( coroutine_fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg, coroutine_fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-# endif
- template< typename Fn >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn, typename StackAllocator >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-#else
- template< typename Fn >
- explicit symmetric_coroutine_call( Fn fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn, typename StackAllocator >
- explicit symmetric_coroutine_call( Fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn, typename StackAllocator >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-#endif
-
- ~symmetric_coroutine_call()
- {
- if ( 0 != impl_)
- {
- impl_->destroy();
- impl_ = 0;
- }
- }
-
- symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
- {
- symmetric_coroutine_call tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
-
- void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- symmetric_coroutine_call & operator()( Arg arg) BOOST_NOEXCEPT
- {
- BOOST_ASSERT( * this);
-
- impl_->resume( arg);
- return * this;
- }
-};
-
-template< typename Arg >
-class symmetric_coroutine_call< Arg & >
-{
-private:
- template< typename X >
- friend class symmetric_coroutine_yield;
-
- typedef symmetric_coroutine_impl< Arg & > impl_type;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
-
- struct dummy {};
-
- impl_type * impl_;
-
-public:
- typedef Arg value_type;
- typedef symmetric_coroutine_yield< Arg & > yield_type;
-
- symmetric_coroutine_call() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- typedef void ( * coroutine_fn)( yield_type &);
-
- explicit symmetric_coroutine_call( coroutine_fn fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg &, coroutine_fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename StackAllocator >
- explicit symmetric_coroutine_call( coroutine_fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg &, coroutine_fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-# endif
- template< typename Fn >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn, typename StackAllocator >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-#else
- template< typename Fn >
- explicit symmetric_coroutine_call( Fn fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn, typename StackAllocator >
- explicit symmetric_coroutine_call( Fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn, typename StackAllocator >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-#endif
-
- ~symmetric_coroutine_call()
- {
- if ( 0 != impl_)
- {
- impl_->destroy();
- impl_ = 0;
- }
- }
-
- symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
- {
- symmetric_coroutine_call tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
-
- void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- symmetric_coroutine_call & operator()( Arg & arg) BOOST_NOEXCEPT
- {
- BOOST_ASSERT( * this);
-
- impl_->resume( arg);
- return * this;
- }
-};
-
-template<>
-class symmetric_coroutine_call< void >
-{
-private:
- template< typename X >
- friend class symmetric_coroutine_yield;
-
- typedef symmetric_coroutine_impl< void > impl_type;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
-
- struct dummy {};
-
- impl_type * impl_;
-
-public:
- typedef void value_type;
- typedef symmetric_coroutine_yield< void > yield_type;
-
- symmetric_coroutine_call() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- typedef void ( * coroutine_fn)( yield_type &);
-
- explicit symmetric_coroutine_call( coroutine_fn fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< void, coroutine_fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename StackAllocator >
- explicit symmetric_coroutine_call( coroutine_fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< void, coroutine_fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-# endif
- template< typename Fn >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn, typename StackAllocator >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-#else
- template< typename Fn >
- explicit symmetric_coroutine_call( Fn fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn, typename StackAllocator >
- explicit symmetric_coroutine_call( Fn fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs = attributes(),
- stack_allocator stack_alloc = stack_allocator() ) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-
- template< typename Fn, typename StackAllocator >
- explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
- attributes const& attrs,
- StackAllocator stack_alloc) :
- impl_( 0)
- {
- // create a stack-context
- stack_context stack_ctx;
- // allocate the coroutine-stack
- stack_alloc.allocate( stack_ctx, attrs.size);
- BOOST_ASSERT( 0 != stack_ctx.sp);
- // typedef of internal coroutine-type
- typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
- // reserve space on top of coroutine-stack for internal coroutine-type
- std::size_t size = stack_ctx.size - sizeof( object_t);
- BOOST_ASSERT( 0 != size);
- void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
- BOOST_ASSERT( 0 != sp);
- // placement new for internal coroutine
- impl_ = new ( sp) object_t(
- fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
- BOOST_ASSERT( impl_);
- }
-#endif
-
- ~symmetric_coroutine_call()
- {
- if ( 0 != impl_)
- {
- impl_->destroy();
- impl_ = 0;
- }
- }
-
- inline symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- inline symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
- {
- symmetric_coroutine_call tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- inline bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
-
- inline void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- inline symmetric_coroutine_call & operator()() BOOST_NOEXCEPT
- {
- BOOST_ASSERT( * this);
-
- impl_->resume();
- return * this;
- }
-};
-
-template< typename Arg >
-void swap( symmetric_coroutine_call< Arg > & l,
- symmetric_coroutine_call< Arg > & r)
-{ l.swap( r); }
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_impl.hpp b/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_impl.hpp
deleted file mode 100644
index b4066d8f78..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_impl.hpp
+++ /dev/null
@@ -1,449 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H
-#define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-#include <boost/coroutine/detail/parameters.hpp>
-#include <boost/coroutine/detail/preallocated.hpp>
-#include <boost/coroutine/detail/trampoline.hpp>
-#include <boost/coroutine/exceptions.hpp>
-#include <boost/coroutine/stack_context.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename R >
-class symmetric_coroutine_impl : private noncopyable
-{
-public:
- typedef parameters< R > param_type;
-
- symmetric_coroutine_impl( preallocated const& palloc,
- bool unwind) BOOST_NOEXCEPT :
- flags_( 0),
- caller_(),
- callee_( trampoline< symmetric_coroutine_impl< R > >, palloc)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- virtual ~symmetric_coroutine_impl() {}
-
- bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- bool is_started() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_started); }
-
- bool is_running() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_running); }
-
- bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- void unwind_stack() BOOST_NOEXCEPT
- {
- if ( is_started() && ! is_complete() && force_unwind() )
- {
- flags_ |= flag_unwind_stack;
- flags_ |= flag_running;
- param_type to( unwind_t::force_unwind);
- caller_.jump(
- callee_,
- & to);
- flags_ &= ~flag_running;
- flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( is_complete() );
- }
- }
-
- void resume( R r) BOOST_NOEXCEPT
- {
- param_type to( const_cast< R * >( & r), this);
- resume_( & to);
- }
-
- R * yield()
- {
- BOOST_ASSERT( is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ &= ~flag_running;
- param_type to;
- param_type * from(
- static_cast< param_type * >(
- callee_.jump(
- caller_,
- & to) ) );
- flags_ |= flag_running;
- if ( from->do_unwind) throw forced_unwind();
- BOOST_ASSERT( from->data);
- return from->data;
- }
-
- template< typename X >
- R * yield_to( symmetric_coroutine_impl< X > * other, X x)
- {
- typename symmetric_coroutine_impl< X >::param_type to( & x, other);
- return yield_to_( other, & to);
- }
-
- template< typename X >
- R * yield_to( symmetric_coroutine_impl< X & > * other, X & x)
- {
- typename symmetric_coroutine_impl< X & >::param_type to( & x, other);
- return yield_to_( other, & to);
- }
-
- template< typename X >
- R * yield_to( symmetric_coroutine_impl< X > * other)
- {
- typename symmetric_coroutine_impl< X >::param_type to( other);
- return yield_to_( other, & to);
- }
-
- virtual void run( R *) BOOST_NOEXCEPT = 0;
-
- virtual void destroy() = 0;
-
-protected:
- template< typename X >
- friend class symmetric_coroutine_impl;
-
- int flags_;
- coroutine_context caller_;
- coroutine_context callee_;
-
- void resume_( param_type * to) BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ |= flag_running;
- caller_.jump(
- callee_,
- to);
- flags_ &= ~flag_running;
- }
-
- template< typename Other >
- R * yield_to_( Other * other, typename Other::param_type * to)
- {
- BOOST_ASSERT( is_running() );
- BOOST_ASSERT( ! is_complete() );
- BOOST_ASSERT( ! other->is_running() );
- BOOST_ASSERT( ! other->is_complete() );
-
- other->caller_ = caller_;
- flags_ &= ~flag_running;
- param_type * from(
- static_cast< param_type * >(
- callee_.jump(
- other->callee_,
- to) ) );
- flags_ |= flag_running;
- if ( from->do_unwind) throw forced_unwind();
- BOOST_ASSERT( from->data);
- return from->data;
- }
-};
-
-template< typename R >
-class symmetric_coroutine_impl< R & > : private noncopyable
-{
-public:
- typedef parameters< R & > param_type;
-
- symmetric_coroutine_impl( preallocated const& palloc,
- bool unwind) BOOST_NOEXCEPT :
- flags_( 0),
- caller_(),
- callee_( trampoline< symmetric_coroutine_impl< R > >, palloc)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- virtual ~symmetric_coroutine_impl() {}
-
- bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- bool is_started() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_started); }
-
- bool is_running() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_running); }
-
- bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- void unwind_stack() BOOST_NOEXCEPT
- {
- if ( is_started() && ! is_complete() && force_unwind() )
- {
- flags_ |= flag_unwind_stack;
- flags_ |= flag_running;
- param_type to( unwind_t::force_unwind);
- caller_.jump(
- callee_,
- & to);
- flags_ &= ~flag_running;
- flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( is_complete() );
- }
- }
-
- void resume( R & arg) BOOST_NOEXCEPT
- {
- param_type to( & arg, this);
- resume_( & to);
- }
-
- R * yield()
- {
- BOOST_ASSERT( is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ &= ~flag_running;
- param_type to;
- param_type * from(
- static_cast< param_type * >(
- callee_.jump(
- caller_,
- & to) ) );
- flags_ |= flag_running;
- if ( from->do_unwind) throw forced_unwind();
- BOOST_ASSERT( from->data);
- return from->data;
- }
-
- template< typename X >
- R * yield_to( symmetric_coroutine_impl< X > * other, X x)
- {
- typename symmetric_coroutine_impl< X >::param_type to( & x, other);
- return yield_to_( other, & to);
- }
-
- template< typename X >
- R * yield_to( symmetric_coroutine_impl< X & > * other, X & x)
- {
- typename symmetric_coroutine_impl< X & >::param_type to( & x, other);
- return yield_to_( other, & to);
- }
-
- template< typename X >
- R * yield_to( symmetric_coroutine_impl< X > * other)
- {
- typename symmetric_coroutine_impl< X >::param_type to( other);
- return yield_to_( other, & to);
- }
-
- virtual void run( R *) BOOST_NOEXCEPT = 0;
-
- virtual void destroy() = 0;
-
-protected:
- template< typename X >
- friend class symmetric_coroutine_impl;
-
- int flags_;
- coroutine_context caller_;
- coroutine_context callee_;
-
- void resume_( param_type * to) BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ |= flag_running;
- caller_.jump(
- callee_,
- to);
- flags_ &= ~flag_running;
- }
-
- template< typename Other >
- R * yield_to_( Other * other, typename Other::param_type * to)
- {
- BOOST_ASSERT( is_running() );
- BOOST_ASSERT( ! is_complete() );
- BOOST_ASSERT( ! other->is_running() );
- BOOST_ASSERT( ! other->is_complete() );
-
- other->caller_ = caller_;
- flags_ &= ~flag_running;
- param_type * from(
- static_cast< param_type * >(
- callee_.jump(
- other->callee_,
- to) ) );
- flags_ |= flag_running;
- if ( from->do_unwind) throw forced_unwind();
- BOOST_ASSERT( from->data);
- return from->data;
- }
-};
-
-template<>
-class symmetric_coroutine_impl< void > : private noncopyable
-{
-public:
- typedef parameters< void > param_type;
-
- symmetric_coroutine_impl( preallocated const& palloc,
- bool unwind) BOOST_NOEXCEPT :
- flags_( 0),
- caller_(),
- callee_( trampoline_void< symmetric_coroutine_impl< void > >, palloc)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- }
-
- virtual ~symmetric_coroutine_impl() {}
-
- inline bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- inline bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- inline bool is_started() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_started); }
-
- inline bool is_running() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_running); }
-
- inline bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- inline void unwind_stack() BOOST_NOEXCEPT
- {
- if ( is_started() && ! is_complete() && force_unwind() )
- {
- flags_ |= flag_unwind_stack;
- flags_ |= flag_running;
- param_type to( unwind_t::force_unwind);
- caller_.jump(
- callee_,
- & to);
- flags_ &= ~flag_running;
- flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( is_complete() );
- }
- }
-
- inline void resume() BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- param_type to( this);
- flags_ |= flag_running;
- caller_.jump(
- callee_,
- & to);
- flags_ &= ~flag_running;
- }
-
- inline void yield()
- {
- BOOST_ASSERT( is_running() );
- BOOST_ASSERT( ! is_complete() );
-
- flags_ &= ~flag_running;
- param_type to;
- param_type * from(
- static_cast< param_type * >(
- callee_.jump(
- caller_,
- & to) ) );
- flags_ |= flag_running;
- if ( from->do_unwind) throw forced_unwind();
- }
-
- template< typename X >
- void yield_to( symmetric_coroutine_impl< X > * other, X x)
- {
- typename symmetric_coroutine_impl< X >::param_type to( & x, other);
- yield_to_( other, & to);
- }
-
- template< typename X >
- void yield_to( symmetric_coroutine_impl< X & > * other, X & x)
- {
- typename symmetric_coroutine_impl< X & >::param_type to( & x, other);
- yield_to_( other, & to);
- }
-
- template< typename X >
- void yield_to( symmetric_coroutine_impl< X > * other)
- {
- typename symmetric_coroutine_impl< X >::param_type to( other);
- yield_to_( other, & to);
- }
-
- virtual void run() BOOST_NOEXCEPT = 0;
-
- virtual void destroy() = 0;
-
-protected:
- template< typename X >
- friend class symmetric_coroutine_impl;
-
- int flags_;
- coroutine_context caller_;
- coroutine_context callee_;
-
- template< typename Other >
- void yield_to_( Other * other, typename Other::param_type * to)
- {
- BOOST_ASSERT( is_running() );
- BOOST_ASSERT( ! is_complete() );
- BOOST_ASSERT( ! other->is_running() );
- BOOST_ASSERT( ! other->is_complete() );
-
- other->caller_ = caller_;
- flags_ &= ~flag_running;
- param_type * from(
- static_cast< param_type * >(
- callee_.jump(
- other->callee_,
- to) ) );
- flags_ |= flag_running;
- if ( from->do_unwind) throw forced_unwind();
- }
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_object.hpp b/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_object.hpp
deleted file mode 100644
index a19cd92232..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_object.hpp
+++ /dev/null
@@ -1,267 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_OBJECT_H
-#define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_OBJECT_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-#include <boost/coroutine/detail/preallocated.hpp>
-#include <boost/coroutine/detail/symmetric_coroutine_impl.hpp>
-#include <boost/coroutine/detail/symmetric_coroutine_yield.hpp>
-#include <boost/coroutine/exceptions.hpp>
-#include <boost/coroutine/stack_context.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-struct stack_context;
-
-namespace detail {
-
-template< typename R, typename Fn, typename StackAllocator >
-class symmetric_coroutine_object : public symmetric_coroutine_impl< R >
-{
-private:
- typedef symmetric_coroutine_impl< R > impl_t;
- typedef symmetric_coroutine_object< R, Fn, StackAllocator > obj_t;
-
- Fn fn_;
- stack_context stack_ctx_;
- StackAllocator stack_alloc_;
-
- static void deallocate_( obj_t * obj)
- {
- stack_context stack_ctx( obj->stack_ctx_);
- StackAllocator stack_alloc( obj->stack_alloc_);
- obj->unwind_stack();
- obj->~obj_t();
- stack_alloc.deallocate( stack_ctx);
- }
-
-public:
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- symmetric_coroutine_object( Fn fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- impl_t( palloc,
- stack_unwind == attrs.do_unwind),
- fn_( fn),
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-#endif
-
- symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- impl_t( palloc,
- stack_unwind == attrs.do_unwind),
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn_( fn),
-#else
- fn_( boost::forward< Fn >( fn) ),
-#endif
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-
- void run( R * r) BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! impl_t::unwind_requested() );
-
- impl_t::flags_ |= flag_started;
- impl_t::flags_ |= flag_running;
- try
- {
- symmetric_coroutine_yield< R > yc( this, r);
- fn_( yc);
- }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { std::terminate(); }
-
- impl_t::flags_ |= flag_complete;
- impl_t::flags_ &= ~flag_running;
- typename impl_t::param_type to;
- impl_t::callee_.jump(
- impl_t::caller_,
- & to);
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
-
- void destroy()
- { deallocate_( this); }
-};
-
-template< typename R, typename Fn, typename StackAllocator >
-class symmetric_coroutine_object< R &, Fn, StackAllocator > : public symmetric_coroutine_impl< R & >
-{
-private:
- typedef symmetric_coroutine_impl< R & > impl_t;
- typedef symmetric_coroutine_object< R &, Fn, StackAllocator > obj_t;
-
- Fn fn_;
- stack_context stack_ctx_;
- StackAllocator stack_alloc_;
-
- static void deallocate_( obj_t * obj)
- {
- stack_context stack_ctx( obj->stack_ctx_);
- StackAllocator stack_alloc( obj->stack_alloc_);
- obj->unwind_stack();
- obj->~obj_t();
- stack_alloc.deallocate( stack_ctx);
- }
-
-public:
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- symmetric_coroutine_object( Fn fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- impl_t( palloc,
- stack_unwind == attrs.do_unwind),
- fn_( fn),
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-#endif
-
- symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- impl_t( palloc,
- stack_unwind == attrs.do_unwind),
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn_( fn),
-#else
- fn_( boost::forward< Fn >( fn) ),
-#endif
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-
- void run( R * r) BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! impl_t::unwind_requested() );
-
- impl_t::flags_ |= flag_started;
- impl_t::flags_ |= flag_running;
- try
- {
- symmetric_coroutine_yield< R & > yc( this, r);
- fn_( yc);
- }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { std::terminate(); }
-
- impl_t::flags_ |= flag_complete;
- impl_t::flags_ &= ~flag_running;
- typename impl_t::param_type to;
- impl_t::callee_.jump(
- impl_t::caller_,
- & to);
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
-
- void destroy()
- { deallocate_( this); }
-};
-
-template< typename Fn, typename StackAllocator >
-class symmetric_coroutine_object< void, Fn, StackAllocator > : public symmetric_coroutine_impl< void >
-{
-private:
- typedef symmetric_coroutine_impl< void > impl_t;
- typedef symmetric_coroutine_object< void, Fn, StackAllocator > obj_t;
-
- Fn fn_;
- stack_context stack_ctx_;
- StackAllocator stack_alloc_;
-
- static void deallocate_( obj_t * obj)
- {
- stack_context stack_ctx( obj->stack_ctx_);
- StackAllocator stack_alloc( obj->stack_alloc_);
- obj->unwind_stack();
- obj->~obj_t();
- stack_alloc.deallocate( stack_ctx);
- }
-
-public:
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- symmetric_coroutine_object( Fn fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- impl_t( palloc,
- stack_unwind == attrs.do_unwind),
- fn_( fn),
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-#endif
-
- symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
- preallocated const& palloc,
- StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
- impl_t( palloc,
- stack_unwind == attrs.do_unwind),
-#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
- fn_( fn),
-#else
- fn_( boost::forward< Fn >( fn) ),
-#endif
- stack_ctx_( palloc.sctx),
- stack_alloc_( stack_alloc)
- {}
-
- void run() BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! impl_t::unwind_requested() );
-
- impl_t::flags_ |= flag_started;
- impl_t::flags_ |= flag_running;
- try
- {
- symmetric_coroutine_yield< void > yc( this);
- fn_( yc);
- }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { std::terminate(); }
-
- impl_t::flags_ |= flag_complete;
- impl_t::flags_ &= ~flag_running;
- typename impl_t::param_type to;
- impl_t::callee_.jump(
- impl_t::caller_,
- & to);
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
-
- void destroy()
- { deallocate_( this); }
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_OBJECT_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_yield.hpp b/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_yield.hpp
deleted file mode 100644
index 296676b6f9..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/symmetric_coroutine_yield.hpp
+++ /dev/null
@@ -1,307 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H
-#define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H
-
-#include <algorithm>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/utility/explicit_operator_bool.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/exceptions.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename R >
-class symmetric_coroutine_yield
-{
-private:
- template< typename X, typename Y, typename Z >
- friend class symmetric_coroutine_object;
-
- typedef symmetric_coroutine_impl< R > impl_type;
-
- struct dummy {};
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
-
- impl_type * impl_;
- R * result_;
-
- symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT :
- impl_( impl),
- result_( result)
- {
- BOOST_ASSERT( 0 != impl_);
- BOOST_ASSERT( 0 != result_);
- }
-
-public:
- symmetric_coroutine_yield() BOOST_NOEXCEPT :
- impl_( 0),
- result_( 0)
- {}
-
- symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
- impl_( 0),
- result_( 0)
- { swap( other); }
-
- symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
- {
- symmetric_coroutine_yield tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_; }
-
- void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
- {
- std::swap( impl_, other.impl_);
- std::swap( result_, other.result_);
- }
-
- symmetric_coroutine_yield & operator()()
- {
- result_ = impl_->yield();
- return * this;
- }
-
- template< typename Coro >
- symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type x,
- typename disable_if<
- is_same< typename Coro::value_type, void >,
- dummy*
- >::type = 0)
- {
- BOOST_ASSERT( other);
-
- result_ = impl_->yield_to( other.impl_, x);
- return * this;
- }
-
- template< typename Coro >
- symmetric_coroutine_yield & operator()( Coro & other,
- typename enable_if<
- is_same< typename Coro::value_type, void >,
- dummy*
- >::type = 0)
- {
- BOOST_ASSERT( other);
-
- result_ = impl_->yield_to( other.impl_);
- return * this;
- }
-
- R get() const
- {
- if ( 0 == result_)
- boost::throw_exception(
- invalid_result() );
-
- return * result_;
- }
-};
-
-template< typename R >
-class symmetric_coroutine_yield< R & >
-{
-private:
- template< typename X, typename Y, typename Z >
- friend class symmetric_coroutine_object;
-
- typedef symmetric_coroutine_impl< R & > impl_type;
-
- struct dummy {};
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
-
- impl_type * impl_;
- R * result_;
-
- symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT :
- impl_( impl),
- result_( result)
- {
- BOOST_ASSERT( 0 != impl_);
- BOOST_ASSERT( 0 != result_);
- }
-
-public:
- symmetric_coroutine_yield() BOOST_NOEXCEPT :
- impl_( 0),
- result_( 0)
- {}
-
- symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
- impl_( 0),
- result_( 0)
- { swap( other); }
-
- symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
- {
- symmetric_coroutine_yield tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_; }
-
- void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
- {
- std::swap( impl_, other.impl_);
- std::swap( result_, other.result_);
- }
-
- symmetric_coroutine_yield & operator()()
- {
- result_ = impl_->yield();
- return * this;
- }
-
- template< typename Coro >
- symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x,
- typename disable_if<
- is_same< typename Coro::value_type, void >,
- dummy*
- >::type = 0)
- {
- BOOST_ASSERT( other);
-
- result_ = impl_->yield_to( other.impl_, x);
- return * this;
- }
-
- template< typename Coro >
- symmetric_coroutine_yield & operator()( Coro & other,
- typename enable_if<
- is_same< typename Coro::value_type, void >,
- dummy*
- >::type = 0)
- {
- BOOST_ASSERT( other);
-
- result_ = impl_->yield_to( other.impl_);
- return * this;
- }
-
- R & get() const
- {
- if ( 0 == result_)
- boost::throw_exception(
- invalid_result() );
-
- return * result_;
- }
-};
-
-template<>
-class symmetric_coroutine_yield< void >
-{
-private:
- template< typename X, typename Y, typename Z >
- friend class symmetric_coroutine_object;
-
- typedef symmetric_coroutine_impl< void > impl_type;
-
- struct dummy {};
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
-
- impl_type * impl_;
-
- symmetric_coroutine_yield( impl_type * impl) BOOST_NOEXCEPT :
- impl_( impl)
- { BOOST_ASSERT( 0 != impl_); }
-
-public:
- symmetric_coroutine_yield() BOOST_NOEXCEPT :
- impl_( 0)
- {}
-
- symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
- impl_( 0)
- { swap( other); }
-
- symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
- {
- symmetric_coroutine_yield tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- BOOST_EXPLICIT_OPERATOR_BOOL();
-
- inline bool operator!() const BOOST_NOEXCEPT
- { return 0 == impl_; }
-
- inline void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
- { std::swap( impl_, other.impl_); }
-
- inline symmetric_coroutine_yield & operator()()
- {
- impl_->yield();
- return * this;
- }
-
- template< typename Coro >
- symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x,
- typename disable_if<
- is_same< typename Coro::value_type, void >,
- dummy*
- >::type = 0)
- {
- BOOST_ASSERT( other);
-
- impl_->yield_to( other.impl_, x);
- return * this;
- }
-
- template< typename Coro >
- symmetric_coroutine_yield & operator()( Coro & other,
- typename enable_if<
- is_same< typename Coro::value_type, void >,
- dummy*
- >::type = 0)
- {
- BOOST_ASSERT( other);
-
- impl_->yield_to( other.impl_);
- return * this;
- }
-};
-
-template< typename R >
-void swap( symmetric_coroutine_yield< R > & l, symmetric_coroutine_yield< R > & r)
-{ l.swap( r); }
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/trampoline.hpp b/contrib/restricted/boost/boost/coroutine/detail/trampoline.hpp
deleted file mode 100644
index eb0c6c2378..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/trampoline.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_TRAMPOLINE_H
-#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/context/detail/fcontext.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/data.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename Coro >
-void trampoline( context::detail::transfer_t t)
-{
- typedef typename Coro::param_type param_type;
-
- data_t * data = static_cast< data_t * >( t.data);
- data->from->ctx_ = t.fctx;
- param_type * param(
- static_cast< param_type * >( data->data) );
- BOOST_ASSERT( 0 != param);
- BOOST_ASSERT( 0 != param->data);
-
- Coro * coro(
- static_cast< Coro * >( param->coro) );
- BOOST_ASSERT( 0 != coro);
-
- coro->run( param->data);
-}
-
-template< typename Coro >
-void trampoline_void( context::detail::transfer_t t)
-{
- typedef typename Coro::param_type param_type;
-
- data_t * data = static_cast< data_t * >( t.data);
- data->from->ctx_ = t.fctx;
- param_type * param(
- static_cast< param_type * >( data->data) );
- BOOST_ASSERT( 0 != param);
-
- Coro * coro(
- static_cast< Coro * >( param->coro) );
- BOOST_ASSERT( 0 != coro);
-
- coro->run();
-}
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/trampoline_pull.hpp b/contrib/restricted/boost/boost/coroutine/detail/trampoline_pull.hpp
deleted file mode 100644
index 1daa76db3b..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/trampoline_pull.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_TRAMPOLINE_PULL_H
-#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/context/detail/fcontext.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/data.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename Coro >
-void trampoline_pull( context::detail::transfer_t t)
-{
- typedef typename Coro::param_type param_type;
-
- data_t * data = static_cast< data_t * >( t.data);
- data->from->ctx_ = t.fctx;
- param_type * param(
- static_cast< param_type * >( data->data) );
- BOOST_ASSERT( 0 != param);
-
- Coro * coro(
- static_cast< Coro * >( param->coro) );
- BOOST_ASSERT( 0 != coro);
-
- coro->run();
-}
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H
diff --git a/contrib/restricted/boost/boost/coroutine/detail/trampoline_push.hpp b/contrib/restricted/boost/boost/coroutine/detail/trampoline_push.hpp
deleted file mode 100644
index 80f90d0518..0000000000
--- a/contrib/restricted/boost/boost/coroutine/detail/trampoline_push.hpp
+++ /dev/null
@@ -1,79 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H
-#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H
-
-#include <cstddef>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/context/detail/fcontext.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/exception_ptr.hpp>
-#include <boost/move/move.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/data.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-#include <boost/coroutine/detail/parameters.hpp>
-#include <boost/coroutine/detail/setup.hpp>
-#include <boost/coroutine/detail/setup.hpp>
-#include <boost/coroutine/exceptions.hpp>
-#include <boost/coroutine/flags.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename Coro >
-void trampoline_push( context::detail::transfer_t t)
-{
- typedef typename Coro::param_type param_type;
-
- data_t * data = static_cast< data_t * >( t.data);
- data->from->ctx_ = t.fctx;
- param_type * param(
- static_cast< param_type * >( data->data) );
- BOOST_ASSERT( 0 != param);
- BOOST_ASSERT( 0 != param->data);
-
- Coro * coro(
- static_cast< Coro * >( param->coro) );
- BOOST_ASSERT( 0 != coro);
-
- coro->run( param->data);
-}
-
-template< typename Coro >
-void trampoline_push_void( context::detail::transfer_t t)
-{
- typedef typename Coro::param_type param_type;
-
- data_t * data = static_cast< data_t * >( t.data);
- data->from->ctx_ = t.fctx;
- param_type * param(
- static_cast< param_type * >( data->data) );
- BOOST_ASSERT( 0 != param);
-
- Coro * coro(
- static_cast< Coro * >( param->coro) );
- BOOST_ASSERT( 0 != coro);
-
- coro->run();
-}
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H
diff --git a/contrib/restricted/boost/boost/coroutine/flags.hpp b/contrib/restricted/boost/boost/coroutine/flags.hpp
deleted file mode 100644
index 81940f30e5..0000000000
--- a/contrib/restricted/boost/boost/coroutine/flags.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_FLAGS_H
-#define BOOST_COROUTINES_FLAGS_H
-
-namespace boost {
-namespace coroutines {
-
-enum flag_unwind_t
-{
- stack_unwind = 0,
- no_stack_unwind
-};
-
-}}
-
-#endif // BOOST_COROUTINES_FLAGS_H
diff --git a/contrib/restricted/boost/boost/coroutine/posix/protected_stack_allocator.hpp b/contrib/restricted/boost/boost/coroutine/posix/protected_stack_allocator.hpp
deleted file mode 100644
index 164bb56cd8..0000000000
--- a/contrib/restricted/boost/boost/coroutine/posix/protected_stack_allocator.hpp
+++ /dev/null
@@ -1,106 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
-#define BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
-
-extern "C" {
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <unistd.h>
-}
-
-#if defined(BOOST_USE_VALGRIND)
-#include <valgrind/valgrind.h>
-#endif
-
-#include <cmath>
-#include <cstddef>
-#include <new>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/stack_context.hpp>
-#include <boost/coroutine/stack_traits.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-template< typename traitsT >
-struct basic_protected_stack_allocator
-{
- typedef traitsT traits_type;
-
- void allocate( stack_context & ctx, std::size_t size = traits_type::minimum_size() )
- {
- BOOST_ASSERT( traits_type::minimum_size() <= size);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) );
-
- // page at bottom will be used as guard-page
- const std::size_t pages(
- static_cast< std::size_t >(
- std::floor(
- static_cast< float >( size) / traits_type::page_size() ) ) );
- BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
- const std::size_t size_( pages * traits_type::page_size() );
- BOOST_ASSERT( 0 != size && 0 != size_);
- BOOST_ASSERT( size_ <= size);
-
- // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
-#if defined(MAP_ANON)
- void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
-#else
- void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-#endif
- if ( MAP_FAILED == limit) throw std::bad_alloc();
-
- // conforming to POSIX.1-2001
-#if defined(BOOST_DISABLE_ASSERTS)
- ::mprotect( limit, traits_type::page_size(), PROT_NONE);
-#else
- const int result( ::mprotect( limit, traits_type::page_size(), PROT_NONE) );
- (void)result;
- BOOST_ASSERT( 0 == result);
-#endif
-
- ctx.size = size_;
- ctx.sp = static_cast< char * >( limit) + ctx.size;
-#if defined(BOOST_USE_VALGRIND)
- ctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( ctx.sp, limit);
-#endif
- }
-
- void deallocate( stack_context & ctx)
- {
- BOOST_ASSERT( ctx.sp);
- BOOST_ASSERT( traits_type::minimum_size() <= ctx.size);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) );
-
-#if defined(BOOST_USE_VALGRIND)
- VALGRIND_STACK_DEREGISTER( ctx.valgrind_stack_id);
-#endif
- void * limit = static_cast< char * >( ctx.sp) - ctx.size;
- // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
- ::munmap( limit, ctx.size);
- }
-};
-
-typedef basic_protected_stack_allocator< stack_traits > protected_stack_allocator;
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
diff --git a/contrib/restricted/boost/boost/coroutine/posix/segmented_stack_allocator.hpp b/contrib/restricted/boost/boost/coroutine/posix/segmented_stack_allocator.hpp
deleted file mode 100644
index 49cee28cd2..0000000000
--- a/contrib/restricted/boost/boost/coroutine/posix/segmented_stack_allocator.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_SEGMENTED_STACK_ALLOCATOR_H
-#define BOOST_COROUTINES_SEGMENTED_STACK_ALLOCATOR_H
-
-#include <cstddef>
-#include <new>
-
-#include <boost/config.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/stack_context.hpp>
-#include <boost/coroutine/stack_traits.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-// forward declaration for splitstack-functions defined in libgcc
-extern "C" {
-void *__splitstack_makecontext( std::size_t,
- void * [BOOST_CONTEXT_SEGMENTS],
- std::size_t *);
-
-void __splitstack_releasecontext( void * [BOOST_CONTEXT_SEGMENTS]);
-
-void __splitstack_resetcontext( void * [BOOST_CONTEXT_SEGMENTS]);
-
-void __splitstack_block_signals_context( void * [BOOST_CONTEXT_SEGMENTS],
- int * new_value, int * old_value);
-}
-
-namespace boost {
-namespace coroutines {
-
-template< typename traitsT >
-struct basic_segmented_stack_allocator
-{
- typedef traitsT traits_type;
-
- void allocate( stack_context & ctx, std::size_t size = traits_type::minimum_size() )
- {
- void * limit = __splitstack_makecontext( size, ctx.segments_ctx, & ctx.size);
- if ( ! limit) throw std::bad_alloc();
-
- // ctx.size is already filled by __splitstack_makecontext
- ctx.sp = static_cast< char * >( limit) + ctx.size;
-
- int off = 0;
- __splitstack_block_signals_context( ctx.segments_ctx, & off, 0);
- }
-
- void deallocate( stack_context & ctx)
- { __splitstack_releasecontext( ctx.segments_ctx); }
-};
-
-typedef basic_segmented_stack_allocator< stack_traits > segmented_stack_allocator;
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_SEGMENTED_STACK_ALLOCATOR_H
diff --git a/contrib/restricted/boost/boost/coroutine/protected_stack_allocator.hpp b/contrib/restricted/boost/boost/coroutine/protected_stack_allocator.hpp
deleted file mode 100644
index 268786fec4..0000000000
--- a/contrib/restricted/boost/boost/coroutine/protected_stack_allocator.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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 <boost/config.hpp>
-
-#if defined(BOOST_WINDOWS)
-# include <boost/coroutine/windows/protected_stack_allocator.hpp>
-#else
-# include <boost/coroutine/posix/protected_stack_allocator.hpp>
-#endif
diff --git a/contrib/restricted/boost/boost/coroutine/segmented_stack_allocator.hpp b/contrib/restricted/boost/boost/coroutine/segmented_stack_allocator.hpp
deleted file mode 100644
index f9525a1a5e..0000000000
--- a/contrib/restricted/boost/boost/coroutine/segmented_stack_allocator.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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 <boost/config.hpp>
-
-#if defined(BOOST_USE_SEGMENTED_STACKS)
-# if defined(BOOST_WINDOWS)
-# error "segmented stacks are not supported by Windows"
-# else
-# include <boost/coroutine/posix/segmented_stack_allocator.hpp>
-# endif
-#endif
diff --git a/contrib/restricted/boost/boost/coroutine/stack_allocator.hpp b/contrib/restricted/boost/boost/coroutine/stack_allocator.hpp
deleted file mode 100644
index 662533efe7..0000000000
--- a/contrib/restricted/boost/boost/coroutine/stack_allocator.hpp
+++ /dev/null
@@ -1,37 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_STACK_ALLOCATOR_H
-#define BOOST_COROUTINES_STACK_ALLOCATOR_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-
-#include <boost/context/detail/config.hpp>
-#include <boost/coroutine/segmented_stack_allocator.hpp>
-#include <boost/coroutine/standard_stack_allocator.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-#if defined(BOOST_USE_SEGMENTED_STACKS)
-typedef segmented_stack_allocator stack_allocator;
-#else
-typedef standard_stack_allocator stack_allocator;
-#endif
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_STACK_ALLOCATOR_H
diff --git a/contrib/restricted/boost/boost/coroutine/standard_stack_allocator.hpp b/contrib/restricted/boost/boost/coroutine/standard_stack_allocator.hpp
deleted file mode 100644
index b946fffc4a..0000000000
--- a/contrib/restricted/boost/boost/coroutine/standard_stack_allocator.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_STANDARD_STACK_ALLOCATOR_H
-#define BOOST_COROUTINES_STANDARD_STACK_ALLOCATOR_H
-
-#if defined(BOOST_USE_VALGRIND)
-#include <valgrind/valgrind.h>
-#endif
-
-#include <cstddef>
-#include <cstdlib>
-#include <new>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/stack_context.hpp>
-#include <boost/coroutine/stack_traits.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-template< typename traitsT >
-struct basic_standard_stack_allocator
-{
- typedef traitsT traits_type;
-
- void allocate( stack_context & ctx, std::size_t size = traits_type::minimum_size() )
- {
- BOOST_ASSERT( traits_type::minimum_size() <= size);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) );
-
- void * limit = std::malloc( size);
- if ( ! limit) throw std::bad_alloc();
-
- ctx.size = size;
- ctx.sp = static_cast< char * >( limit) + ctx.size;
-#if defined(BOOST_USE_VALGRIND)
- ctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( ctx.sp, limit);
-#endif
- }
-
- void deallocate( stack_context & ctx)
- {
- BOOST_ASSERT( ctx.sp);
- BOOST_ASSERT( traits_type::minimum_size() <= ctx.size);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) );
-
-#if defined(BOOST_USE_VALGRIND)
- VALGRIND_STACK_DEREGISTER( ctx.valgrind_stack_id);
-#endif
-
- void * limit = static_cast< char * >( ctx.sp) - ctx.size;
- std::free( limit);
- }
-};
-
-typedef basic_standard_stack_allocator< stack_traits > standard_stack_allocator;
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_STANDARD_STACK_ALLOCATOR_H
diff --git a/contrib/restricted/boost/boost/coroutine/symmetric_coroutine.hpp b/contrib/restricted/boost/boost/coroutine/symmetric_coroutine.hpp
deleted file mode 100644
index 646fa32836..0000000000
--- a/contrib/restricted/boost/boost/coroutine/symmetric_coroutine.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_SYMMETRIC_COROUTINE_H
-#define BOOST_COROUTINES_SYMMETRIC_COROUTINE_H
-
-#ifndef BOOST_COROUTINES_NO_DEPRECATION_WARNING
-# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
-//# pragma message ("Warning: Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING.")
-# elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
-//# warning "Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING."
-# endif
-#endif
-
-#include <boost/config.hpp>
-
-#include <boost/coroutine/detail/symmetric_coroutine_call.hpp>
-#include <boost/coroutine/detail/symmetric_coroutine_yield.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-template< typename T >
-struct symmetric_coroutine
-{
- typedef detail::symmetric_coroutine_call< T > call_type;
- typedef detail::symmetric_coroutine_yield< T > yield_type;
-};
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_SYMMETRIC_COROUTINE_H
diff --git a/contrib/restricted/boost/boost/coroutine/windows/protected_stack_allocator.hpp b/contrib/restricted/boost/boost/coroutine/windows/protected_stack_allocator.hpp
deleted file mode 100644
index 29e19babb7..0000000000
--- a/contrib/restricted/boost/boost/coroutine/windows/protected_stack_allocator.hpp
+++ /dev/null
@@ -1,87 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
-#define BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
-
-extern "C" {
-#include <windows.h>
-}
-
-#include <cmath>
-#include <cstddef>
-#include <new>
-
-#include <boost/config.hpp>
-
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/stack_traits.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-
-struct stack_context;
-
-template< typename traitsT >
-struct basic_protected_stack_allocator
-{
- typedef traitsT traits_type;
-
- void allocate( stack_context & ctx, std::size_t size)
- {
- BOOST_ASSERT( traits_type::minimum_size() <= size);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) );
-
- // page at bottom will be used as guard-page
- const std::size_t pages(
- static_cast< std::size_t >(
- std::floor(
- static_cast< float >( size) / traits_type::page_size() ) ) );
- BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
- const std::size_t size_ = pages * traits_type::page_size();
- BOOST_ASSERT( 0 != size && 0 != size_);
-
- void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
- if ( ! limit) throw std::bad_alloc();
-
- DWORD old_options;
-#if defined(BOOST_DISABLE_ASSERTS)
- ::VirtualProtect(
- limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
-#else
- const BOOL result = ::VirtualProtect(
- limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
- BOOST_ASSERT( FALSE != result);
-#endif
-
- ctx.size = size_;
- ctx.sp = static_cast< char * >( limit) + ctx.size;
- }
-
- void deallocate( stack_context & ctx)
- {
- BOOST_ASSERT( ctx.sp);
- BOOST_ASSERT( traits_type::minimum_size() <= ctx.size);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) );
-
- void * limit = static_cast< char * >( ctx.sp) - ctx.size;
- ::VirtualFree( limit, 0, MEM_RELEASE);
- }
-};
-
-typedef basic_protected_stack_allocator< stack_traits > protected_stack_allocator;
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
diff --git a/contrib/restricted/boost/config/include/boost/config/no_tr1/complex.hpp b/contrib/restricted/boost/config/include/boost/config/no_tr1/complex.hpp
deleted file mode 100644
index ca200922b3..0000000000
--- a/contrib/restricted/boost/config/include/boost/config/no_tr1/complex.hpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// (C) Copyright John Maddock 2005.
-// Use, modification and distribution are subject to 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)
-//
-// The aim of this header is just to include <complex> but to do
-// so in a way that does not result in recursive inclusion of
-// the Boost TR1 components if boost/tr1/tr1/complex is in the
-// include search path. We have to do this to avoid circular
-// dependencies:
-//
-
-#ifndef BOOST_CONFIG_COMPLEX
-# define BOOST_CONFIG_COMPLEX
-
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_CONFIG_NO_COMPLEX_RECURSION
-# endif
-
-# include <complex>
-
-# ifdef BOOST_CONFIG_NO_COMPLEX_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# undef BOOST_CONFIG_NO_COMPLEX_RECURSION
-# endif
-
-#endif
diff --git a/contrib/restricted/boost/core/include/boost/non_type.hpp b/contrib/restricted/boost/core/include/boost/non_type.hpp
deleted file mode 100644
index 896aed4d34..0000000000
--- a/contrib/restricted/boost/core/include/boost/non_type.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// -------------------------------------
-//
-// (C) Copyright Gennaro Prota 2003.
-//
-// 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_NON_TYPE_HPP_GP_20030417
-#define BOOST_NON_TYPE_HPP_GP_20030417
-
-
-namespace boost {
-
- // Just a simple "envelope" for non-type template parameters. Useful
- // to work around some MSVC deficiencies.
-
- template <typename T, T n>
- struct non_type { };
-
-
-}
-
-
-#endif // include guard
diff --git a/contrib/restricted/boost/coroutine/README.md b/contrib/restricted/boost/coroutine/README.md
new file mode 100644
index 0000000000..2e14589153
--- /dev/null
+++ b/contrib/restricted/boost/coroutine/README.md
@@ -0,0 +1,14 @@
+boost.coroutine
+===============
+
+boost.coroutine provides templates for generalized subroutines which allow multiple entry points for
+suspending and resuming execution at certain locations. It preserves the local state of execution and
+allows re-entering subroutines more than once (useful if state must be kept across function calls).
+
+Coroutines can be viewed as a language-level construct providing a special kind of control flow.
+
+In contrast to threads, which are pre-emptive, coroutines switches are cooperative (programmer controls
+when a switch will happen). The kernel is not involved in the coroutine switches.
+
+Note that boost.coroutine is deprecated - boost.coroutine2 is its successor.
+If you are forced to use a pre-C++11 compiler you should still use boost.coroutine.
diff --git a/contrib/restricted/boost/boost/coroutine/detail/config.hpp b/contrib/restricted/boost/coroutine/include/boost/coroutine/detail/config.hpp
index dab0a83d8b..12632bbf7b 100644
--- a/contrib/restricted/boost/boost/coroutine/detail/config.hpp
+++ b/contrib/restricted/boost/coroutine/include/boost/coroutine/detail/config.hpp
@@ -12,9 +12,9 @@
#ifndef BOOST_COROUTINES_NO_DEPRECATION_WARNING
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
-//# pragma message ("Warning: Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING.")
+# pragma message ("Warning: Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING.")
# elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
-//# warning "Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING."
+# warning "Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING."
# endif
#endif
diff --git a/contrib/restricted/boost/boost/coroutine/detail/coroutine_context.hpp b/contrib/restricted/boost/coroutine/include/boost/coroutine/detail/coroutine_context.hpp
index 2d2b60ace2..2d2b60ace2 100644
--- a/contrib/restricted/boost/boost/coroutine/detail/coroutine_context.hpp
+++ b/contrib/restricted/boost/coroutine/include/boost/coroutine/detail/coroutine_context.hpp
diff --git a/contrib/restricted/boost/boost/coroutine/detail/data.hpp b/contrib/restricted/boost/coroutine/include/boost/coroutine/detail/data.hpp
index 7c008fe831..7c008fe831 100644
--- a/contrib/restricted/boost/boost/coroutine/detail/data.hpp
+++ b/contrib/restricted/boost/coroutine/include/boost/coroutine/detail/data.hpp
diff --git a/contrib/restricted/boost/boost/coroutine/detail/preallocated.hpp b/contrib/restricted/boost/coroutine/include/boost/coroutine/detail/preallocated.hpp
index 1658561ac8..1658561ac8 100644
--- a/contrib/restricted/boost/boost/coroutine/detail/preallocated.hpp
+++ b/contrib/restricted/boost/coroutine/include/boost/coroutine/detail/preallocated.hpp
diff --git a/contrib/restricted/boost/boost/coroutine/exceptions.hpp b/contrib/restricted/boost/coroutine/include/boost/coroutine/exceptions.hpp
index 5dbd55f106..5dbd55f106 100644
--- a/contrib/restricted/boost/boost/coroutine/exceptions.hpp
+++ b/contrib/restricted/boost/coroutine/include/boost/coroutine/exceptions.hpp
diff --git a/contrib/restricted/boost/boost/coroutine/stack_context.hpp b/contrib/restricted/boost/coroutine/include/boost/coroutine/stack_context.hpp
index 433056f7a1..433056f7a1 100644
--- a/contrib/restricted/boost/boost/coroutine/stack_context.hpp
+++ b/contrib/restricted/boost/coroutine/include/boost/coroutine/stack_context.hpp
diff --git a/contrib/restricted/boost/boost/coroutine/stack_traits.hpp b/contrib/restricted/boost/coroutine/include/boost/coroutine/stack_traits.hpp
index 0e8f25182d..0e8f25182d 100644
--- a/contrib/restricted/boost/boost/coroutine/stack_traits.hpp
+++ b/contrib/restricted/boost/coroutine/include/boost/coroutine/stack_traits.hpp
diff --git a/contrib/restricted/boost/libs/coroutine/src/detail/coroutine_context.cpp b/contrib/restricted/boost/coroutine/src/detail/coroutine_context.cpp
index 6a6d524833..6a6d524833 100644
--- a/contrib/restricted/boost/libs/coroutine/src/detail/coroutine_context.cpp
+++ b/contrib/restricted/boost/coroutine/src/detail/coroutine_context.cpp
diff --git a/contrib/restricted/boost/libs/coroutine/src/exceptions.cpp b/contrib/restricted/boost/coroutine/src/exceptions.cpp
index d32eb54683..d32eb54683 100644
--- a/contrib/restricted/boost/libs/coroutine/src/exceptions.cpp
+++ b/contrib/restricted/boost/coroutine/src/exceptions.cpp
diff --git a/contrib/restricted/boost/libs/coroutine/src/posix/stack_traits.cpp b/contrib/restricted/boost/coroutine/src/posix/stack_traits.cpp
index b629943221..b629943221 100644
--- a/contrib/restricted/boost/libs/coroutine/src/posix/stack_traits.cpp
+++ b/contrib/restricted/boost/coroutine/src/posix/stack_traits.cpp
diff --git a/contrib/restricted/boost/integer/include/boost/integer/static_min_max.hpp b/contrib/restricted/boost/integer/include/boost/integer/static_min_max.hpp
deleted file mode 100644
index bfe1e260c5..0000000000
--- a/contrib/restricted/boost/integer/include/boost/integer/static_min_max.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-// Boost integer/static_min_max.hpp header file ----------------------------//
-
-// (C) Copyright Daryle Walker 2001.
-// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
-// https://www.boost.org/LICENSE_1_0.txt)
-
-// See https://www.boost.org for updates, documentation, and revision history.
-
-#ifndef BOOST_INTEGER_STATIC_MIN_MAX_HPP
-#define BOOST_INTEGER_STATIC_MIN_MAX_HPP
-
-#include <boost/config.hpp>
-#include <boost/integer_fwd.hpp> // self include
-
-namespace boost
-{
-
-// Compile-time extrema class declarations ---------------------------------//
-// Get the minimum or maximum of two values, signed or unsigned.
-
-template <static_min_max_signed_type Value1, static_min_max_signed_type Value2>
-struct static_signed_min
-{
- BOOST_STATIC_CONSTANT(static_min_max_signed_type, value = (Value1 > Value2) ? Value2 : Value1 );
-};
-
-template <static_min_max_signed_type Value1, static_min_max_signed_type Value2>
-struct static_signed_max
-{
- BOOST_STATIC_CONSTANT(static_min_max_signed_type, value = (Value1 < Value2) ? Value2 : Value1 );
-};
-
-template <static_min_max_unsigned_type Value1, static_min_max_unsigned_type Value2>
-struct static_unsigned_min
-{
- BOOST_STATIC_CONSTANT(static_min_max_unsigned_type, value
- = (Value1 > Value2) ? Value2 : Value1 );
-};
-
-template <static_min_max_unsigned_type Value1, static_min_max_unsigned_type Value2>
-struct static_unsigned_max
-{
- BOOST_STATIC_CONSTANT(static_min_max_unsigned_type, value
- = (Value1 < Value2) ? Value2 : Value1 );
-};
-
-
-} // namespace boost
-
-
-#endif // BOOST_INTEGER_STATIC_MIN_MAX_HPP
diff --git a/contrib/restricted/boost/math/LICENSE b/contrib/restricted/boost/math/LICENSE
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/contrib/restricted/boost/math/LICENSE
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/contrib/restricted/boost/math/README.md b/contrib/restricted/boost/math/README.md
new file mode 100644
index 0000000000..b9dba9a9a9
--- /dev/null
+++ b/contrib/restricted/boost/math/README.md
@@ -0,0 +1,148 @@
+Boost Math Library
+[![Build Status](https://drone.cpp.al/api/badges/boostorg/math/status.svg)](https://drone.cpp.al/boostorg/math)[![Build Status](https://github.com/boostorg/math/workflows/CI/badge.svg?branch=develop)](https://github.com/boostorg/math/actions)
+==================
+
+>ANNOUNCEMENT: Support for C++11 will be deprecated in this library starting in July 2023 (Boost 1.82).
+>New features will require *at least* C++14, as will existing features starting with the deprecation release.
+
+This library is divided into several interconnected parts:
+
+### Floating Point Utilities
+
+Utility functions for dealing with floating point arithmetic, includes functions for floating point classification (fpclassify, isnan, isinf etc), sign manipulation, rounding, comparison, and computing the distance between floating point numbers.
+
+### Specific Width Floating Point Types
+
+A set of typedefs similar to those provided by `<cstdint>` but for floating point types.
+
+### Mathematical Constants
+
+A wide range of constants ranging from various multiples of π, fractions, Euler's constant, etc.
+
+These are of course usable from template code, or as non-templates with a simplified interface if that is more appropriate.
+
+### Statistical Distributions
+
+Provides a reasonably comprehensive set of statistical distributions, upon which higher level statistical tests can be built.
+
+The initial focus is on the central univariate distributions. Both continuous (like normal & Fisher) and discrete (like binomial & Poisson) distributions are provided.
+
+A comprehensive tutorial is provided, along with a series of worked examples illustrating how the library is used to conduct statistical tests.
+
+### Special Functions
+
+Provides a small number of high quality special functions; initially these were concentrated on functions used in statistical applications along with those in the Technical Report on C++ Library Extensions.
+
+The function families currently implemented are the gamma, beta & error functions along with the incomplete gamma and beta functions (four variants of each) and all the possible inverses of these, plus the digamma, various factorial functions, Bessel functions, elliptic integrals, hypergeometrics, sinus cardinals (along with their hyperbolic variants), inverse hyperbolic functions, Legrendre/Laguerre/Hermite/Chebyshev polynomials and various special power and logarithmic functions.
+
+All the implementations are fully generic and support the use of arbitrary "real-number" types, including Boost.Multiprecision, although they are optimised for use with types with known significand (or mantissa) sizes: typically float, double or long double.
+
+These functions also provide the basis of support for the TR1 special functions.
+
+### Root Finding and Function Minimisation
+
+A comprehensive set of root-finding algorithms over the real line, both with derivatives and derivative free.
+
+Also function minimisation via Brent's Method.
+
+### Polynomials and Rational Functions
+
+Tools for manipulating polynomials and for efficient evaluation of rationals or polynomials.
+
+### Interpolation
+
+Function interpolation via barycentric rational interpolation, compactly supported quadratic, cubic, and quintic B-splines, the Chebyshev transform, trigonometric polynomials, Makima, pchip, cubic Hermite splines, and bilinear interpolation.
+
+### Numerical Integration and Differentiation
+
+A reasonably comprehensive set of routines for integration (trapezoidal, Gauss-Legendre, Gauss-Kronrod, Gauss-Chebyshev, double-exponential, and Monte-Carlo) and differentiation (Chebyshev transform, finite difference, the complex step derivative, and forward-mode automatic differentiation).
+
+The integration routines are usable for functions returning complex results - and hence can be used for computation of contour integrals.
+
+### Quaternions and Octonions
+
+Quaternion and Octonians are class templates similar to std::complex.
+
+The full documentation is available on [boost.org](http://www.boost.org/doc/libs/release/libs/math).
+
+### Standalone Mode (Beta)
+
+Defining BOOST_MATH_STANDALONE allows Boost.Math to be used without any Boost dependencies. Some functionality is reduced in this mode. A static_assert message will alert you if a particular feature has been disabled by standalone mode.
+
+## Supported Compilers ##
+
+The following compilers are tested with the CI system, and are known to work. Starting with Boost 1.76 (April 2021 Release) a compiler that is fully compliant with C++11 is required to use Boost.Math.
+
+* g++ 5 or later
+* clang++ 5 or later
+* Visual Studio 2015 (14.0) or later
+
+## Build Status ##
+
+| | Master | Develop |
+|------------------|----------|-------------|
+| Github Actions | [![Build Status](https://github.com/boostorg/math/workflows/CI/badge.svg?branch=master)](https://github.com/boostorg/math/actions) | [![Build Status](https://github.com/boostorg/math/workflows/CI/badge.svg?branch=develop)](https://github.com/boostorg/math/actions) |
+|Drone | [![Build Status](https://drone.cpp.al/api/badges/boostorg/math/status.svg?ref=refs/heads/master)](https://drone.cpp.al/boostorg/math) | [![Build Status](https://drone.cpp.al/api/badges/boostorg/math/status.svg)](https://drone.cpp.al/boostorg/math) |
+
+
+
+## Support, bugs and feature requests ##
+
+Bugs and feature requests can be reported through the [GitHub issue tracker](https://github.com/boostorg/math/issues)
+(see [open issues](https://github.com/boostorg/math/issues) and
+[closed issues](https://github.com/boostorg/math/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aclosed)).
+
+You can submit your changes through a [pull request](https://github.com/boostorg/math/pulls).
+
+There is no mailing-list specific to Boost Math, although you can use the general-purpose Boost [mailing-list](http://lists.boost.org/mailman/listinfo.cgi/boost-users) using the tag [math].
+
+
+## Development ##
+
+Clone the whole boost project, which includes the individual Boost projects as submodules ([see boost+git doc](https://github.com/boostorg/boost/wiki/Getting-Started)):
+
+ $ git clone https://github.com/boostorg/boost
+ $ cd boost
+ $ git submodule update --init
+
+The Boost Math Library is located in `libs/math/`.
+
+### Running tests ###
+First, make sure you are in `libs/math/test`.
+You can either run all the tests listed in `Jamfile.v2` or run a single test:
+
+ test$ ../../../b2 <- run all tests
+ test$ ../../../b2 static_assert_test <- single test
+ test$ # A more advanced syntax, demoing various options for building the tests:
+ test$ ../../../b2 -a -j2 -q --reconfigure toolset=clang cxxflags="--std=c++14 -fsanitize=address -fsanitize=undefined" linkflags="-fsanitize=undefined -fsanitize=address"
+
+### Continuous Integration ###
+The default action for a PR or commit to a PR is for CI to run the full complement of tests. The following can be appended to the end of a commit message to modify behavior:
+
+ * [ci skip] to skip all tests
+ * [linux] to test using GCC Versions 5-10 and Clang Versions 5-10 on Ubuntu LTS versions 16.04-20.04.
+ * [apple] to test Apple Clang on the latest version of MacOS.
+ * [windows] to test MSVC-14.0, MSVC-14.2 and mingw on the latest version of Windows.
+ * [standalone] to run standalone mode compile tests
+
+### Building documentation ###
+
+Full instructions can be found [here](https://svn.boost.org/trac10/wiki/BoostDocs/GettingStarted), but to reiterate slightly:
+
+```bash
+libs/math/doc$ brew install docbook-xsl # on mac
+libs/math/doc$ touch ~/user-config.jam
+libs/math/doc$ # now edit so that:
+libs/math/doc$ cat ~/user-config.jam
+using darwin ;
+
+using xsltproc ;
+
+using boostbook
+ : /usr/local/opt/docbook-xsl/docbook-xsl
+ ;
+
+using doxygen ;
+using quickbook ;
+libs/math/doc$ ../../../b2
+```
diff --git a/contrib/restricted/boost/math/include/boost/cstdfloat.hpp b/contrib/restricted/boost/math/include/boost/cstdfloat.hpp
new file mode 100644
index 0000000000..2814bb08bb
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/cstdfloat.hpp
@@ -0,0 +1,58 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2014.
+// Copyright John Maddock 2014.
+// Copyright Paul Bristow 2014.
+// 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)
+//
+
+// <boost/cstdfloat.hpp> implements floating-point typedefs having
+// specified widths, as described in N3626 (proposed for C++14).
+// See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3626.pdf
+
+#ifndef BOOST_MATH_CSTDFLOAT_2014_01_09_HPP_
+ #define BOOST_MATH_CSTDFLOAT_2014_01_09_HPP_
+
+ // Include the floating-point type definitions.
+ #include <boost/math/cstdfloat/cstdfloat_types.hpp>
+
+ // Support a specialization of std::numeric_limits<> for the wrapped quadmath library (if available).
+ #if !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS)
+ #include <boost/math/cstdfloat/cstdfloat_limits.hpp>
+ #endif
+
+ // Support <cmath> functions for the wrapped quadmath library (if available).
+ #if !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
+ #include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
+ #endif
+
+ // Support I/O stream operations for the wrapped quadmath library (if available).
+ #if !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM)
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_iostream.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
+ #endif
+ #include <boost/math/cstdfloat/cstdfloat_iostream.hpp>
+ #endif
+
+ // Support a specialization of std::complex<> for the wrapped quadmath library (if available).
+ #if !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_COMPLEX)
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS defined.
+ #endif
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
+ #endif
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM defined.
+ #endif
+ #include <boost/math/cstdfloat/cstdfloat_complex.hpp>
+ #endif
+
+
+ // Undefine BOOST_NO_FLOAT128_T because this constant is not meant for public use.
+ #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T)
+ #undef BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T
+ #endif
+
+#endif // BOOST_MATH_CSTDFLOAT_2014_01_09_HPP_
diff --git a/contrib/restricted/boost/math/include/boost/math/constants/calculate_constants.hpp b/contrib/restricted/boost/math/include/boost/math/constants/calculate_constants.hpp
new file mode 100644
index 0000000000..0f383bf684
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/constants/calculate_constants.hpp
@@ -0,0 +1,1110 @@
+// Copyright John Maddock 2010, 2012.
+// Copyright Paul A. Bristow 2011, 2012.
+
+// Use, modification and distribution are subject to 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_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED
+#define BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED
+#include <type_traits>
+
+namespace boost{ namespace math{ namespace constants{ namespace detail{
+
+template <class T>
+template<int N>
+inline T constant_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+
+ return ldexp(acos(T(0)), 1);
+
+ /*
+ // Although this code works well, it's usually more accurate to just call acos
+ // and access the number types own representation of PI which is usually calculated
+ // at slightly higher precision...
+
+ T result;
+ T a = 1;
+ T b;
+ T A(a);
+ T B = 0.5f;
+ T D = 0.25f;
+
+ T lim;
+ lim = boost::math::tools::epsilon<T>();
+
+ unsigned k = 1;
+
+ do
+ {
+ result = A + B;
+ result = ldexp(result, -2);
+ b = sqrt(B);
+ a += b;
+ a = ldexp(a, -1);
+ A = a * a;
+ B = A - result;
+ B = ldexp(B, 1);
+ result = A - B;
+ bool neg = boost::math::sign(result) < 0;
+ if(neg)
+ result = -result;
+ if(result <= lim)
+ break;
+ if(neg)
+ result = -result;
+ result = ldexp(result, k - 1);
+ D -= result;
+ ++k;
+ lim = ldexp(lim, 1);
+ }
+ while(true);
+
+ result = B / D;
+ return result;
+ */
+}
+
+template <class T>
+template<int N>
+inline T constant_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return 2 * pi<T, policies::policy<policies::digits2<N> > >();
+}
+
+template <class T> // 2 / pi
+template<int N>
+inline T constant_two_div_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return 2 / pi<T, policies::policy<policies::digits2<N> > >();
+}
+
+template <class T> // sqrt(2/pi)
+template <int N>
+inline T constant_root_two_div_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt((2 / pi<T, policies::policy<policies::digits2<N> > >()));
+}
+
+template <class T>
+template<int N>
+inline T constant_one_div_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return 1 / two_pi<T, policies::policy<policies::digits2<N> > >();
+}
+
+template <class T>
+template<int N>
+inline T constant_root_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt(pi<T, policies::policy<policies::digits2<N> > >());
+}
+
+template <class T>
+template<int N>
+inline T constant_root_half_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt(pi<T, policies::policy<policies::digits2<N> > >() / 2);
+}
+
+template <class T>
+template<int N>
+inline T constant_root_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt(two_pi<T, policies::policy<policies::digits2<N> > >());
+}
+
+template <class T>
+template<int N>
+inline T constant_log_root_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return log(root_two_pi<T, policies::policy<policies::digits2<N> > >());
+}
+
+template <class T>
+template<int N>
+inline T constant_root_ln_four<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt(log(static_cast<T>(4)));
+}
+
+template <class T>
+template<int N>
+inline T constant_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ //
+ // Although we can clearly calculate this from first principles, this hooks into
+ // T's own notion of e, which hopefully will more accurate than one calculated to
+ // a few epsilon:
+ //
+ BOOST_MATH_STD_USING
+ return exp(static_cast<T>(1));
+}
+
+template <class T>
+template<int N>
+inline T constant_half<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return static_cast<T>(1) / static_cast<T>(2);
+}
+
+template <class T>
+template<int M>
+inline T constant_euler<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, M>)))
+{
+ BOOST_MATH_STD_USING
+ //
+ // This is the method described in:
+ // "Some New Algorithms for High-Precision Computation of Euler's Constant"
+ // Richard P Brent and Edwin M McMillan.
+ // Mathematics of Computation, Volume 34, Number 149, Jan 1980, pages 305-312.
+ // See equation 17 with p = 2.
+ //
+ T n = 3 + (M ? (std::min)(M, tools::digits<T>()) : tools::digits<T>()) / 4;
+ T lim = M ? ldexp(T(1), 1 - (std::min)(M, tools::digits<T>())) : tools::epsilon<T>();
+ T lnn = log(n);
+ T term = 1;
+ T N = -lnn;
+ T D = 1;
+ T Hk = 0;
+ T one = 1;
+
+ for(unsigned k = 1;; ++k)
+ {
+ term *= n * n;
+ term /= k * k;
+ Hk += one / k;
+ N += term * (Hk - lnn);
+ D += term;
+
+ if(term < D * lim)
+ break;
+ }
+ return N / D;
+}
+
+template <class T>
+template<int N>
+inline T constant_euler_sqr<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return euler<T, policies::policy<policies::digits2<N> > >()
+ * euler<T, policies::policy<policies::digits2<N> > >();
+}
+
+template <class T>
+template<int N>
+inline T constant_one_div_euler<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(1)
+ / euler<T, policies::policy<policies::digits2<N> > >();
+}
+
+
+template <class T>
+template<int N>
+inline T constant_root_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt(static_cast<T>(2));
+}
+
+
+template <class T>
+template<int N>
+inline T constant_root_three<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt(static_cast<T>(3));
+}
+
+template <class T>
+template<int N>
+inline T constant_half_root_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt(static_cast<T>(2)) / 2;
+}
+
+template <class T>
+template<int N>
+inline T constant_ln_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ //
+ // Although there are good ways to calculate this from scratch, this hooks into
+ // T's own notion of log(2) which will hopefully be accurate to the full precision
+ // of T:
+ //
+ BOOST_MATH_STD_USING
+ return log(static_cast<T>(2));
+}
+
+template <class T>
+template<int N>
+inline T constant_ln_ten<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return log(static_cast<T>(10));
+}
+
+template <class T>
+template<int N>
+inline T constant_ln_ln_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return log(log(static_cast<T>(2)));
+}
+
+template <class T>
+template<int N>
+inline T constant_third<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(1) / static_cast<T>(3);
+}
+
+template <class T>
+template<int N>
+inline T constant_twothirds<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(2) / static_cast<T>(3);
+}
+
+template <class T>
+template<int N>
+inline T constant_two_thirds<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(2) / static_cast<T>(3);
+}
+
+template <class T>
+template<int N>
+inline T constant_three_quarters<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(3) / static_cast<T>(4);
+}
+
+template <class T>
+template<int N>
+inline T constant_sixth<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(1) / static_cast<T>(6);
+}
+
+// Pi and related constants.
+template <class T>
+template<int N>
+inline T constant_pi_minus_three<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(3);
+}
+
+template <class T>
+template<int N>
+inline T constant_four_minus_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return static_cast<T>(4) - pi<T, policies::policy<policies::digits2<N> > >();
+}
+
+template <class T>
+template<int N>
+inline T constant_exp_minus_half<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return exp(static_cast<T>(-0.5));
+}
+
+template <class T>
+template<int N>
+inline T constant_exp_minus_one<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return exp(static_cast<T>(-1.));
+}
+
+template <class T>
+template<int N>
+inline T constant_one_div_root_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return static_cast<T>(1) / root_two<T, policies::policy<policies::digits2<N> > >();
+}
+
+template <class T>
+template<int N>
+inline T constant_one_div_root_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return static_cast<T>(1) / root_pi<T, policies::policy<policies::digits2<N> > >();
+}
+
+template <class T>
+template<int N>
+inline T constant_one_div_root_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return static_cast<T>(1) / root_two_pi<T, policies::policy<policies::digits2<N> > >();
+}
+
+template <class T>
+template<int N>
+inline T constant_root_one_div_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt(static_cast<T>(1) / pi<T, policies::policy<policies::digits2<N> > >());
+}
+
+template <class T>
+template<int N>
+inline T constant_four_thirds_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >() * static_cast<T>(4) / static_cast<T>(3);
+}
+
+template <class T>
+template<int N>
+inline T constant_half_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >() / static_cast<T>(2);
+}
+
+template <class T>
+template<int N>
+inline T constant_third_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >() / static_cast<T>(3);
+}
+
+template <class T>
+template<int N>
+inline T constant_sixth_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >() / static_cast<T>(6);
+}
+
+template <class T>
+template<int N>
+inline T constant_two_thirds_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >() * static_cast<T>(2) / static_cast<T>(3);
+}
+
+template <class T>
+template<int N>
+inline T constant_three_quarters_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >() * static_cast<T>(3) / static_cast<T>(4);
+}
+
+template <class T>
+template<int N>
+inline T constant_pi_pow_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pow(pi<T, policies::policy<policies::digits2<N> > >(), e<T, policies::policy<policies::digits2<N> > >()); //
+}
+
+template <class T>
+template<int N>
+inline T constant_pi_sqr<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >()
+ * pi<T, policies::policy<policies::digits2<N> > >() ; //
+}
+
+template <class T>
+template<int N>
+inline T constant_pi_sqr_div_six<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >()
+ * pi<T, policies::policy<policies::digits2<N> > >()
+ / static_cast<T>(6); //
+}
+
+template <class T>
+template<int N>
+inline T constant_pi_cubed<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >()
+ * pi<T, policies::policy<policies::digits2<N> > >()
+ * pi<T, policies::policy<policies::digits2<N> > >()
+ ; //
+}
+
+template <class T>
+template<int N>
+inline T constant_cbrt_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pow(pi<T, policies::policy<policies::digits2<N> > >(), static_cast<T>(1)/ static_cast<T>(3));
+}
+
+template <class T>
+template<int N>
+inline T constant_one_div_cbrt_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(1)
+ / pow(pi<T, policies::policy<policies::digits2<N> > >(), static_cast<T>(1)/ static_cast<T>(3));
+}
+
+// Euler's e
+
+template <class T>
+template<int N>
+inline T constant_e_pow_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pow(e<T, policies::policy<policies::digits2<N> > >(), pi<T, policies::policy<policies::digits2<N> > >()); //
+}
+
+template <class T>
+template<int N>
+inline T constant_root_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sqrt(e<T, policies::policy<policies::digits2<N> > >());
+}
+
+template <class T>
+template<int N>
+inline T constant_log10_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return log10(e<T, policies::policy<policies::digits2<N> > >());
+}
+
+template <class T>
+template<int N>
+inline T constant_one_div_log10_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(1) /
+ log10(e<T, policies::policy<policies::digits2<N> > >());
+}
+
+// Trigonometric
+
+template <class T>
+template<int N>
+inline T constant_degree<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return pi<T, policies::policy<policies::digits2<N> > >()
+ / static_cast<T>(180)
+ ; //
+}
+
+template <class T>
+template<int N>
+inline T constant_radian<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(180)
+ / pi<T, policies::policy<policies::digits2<N> > >()
+ ; //
+}
+
+template <class T>
+template<int N>
+inline T constant_sin_one<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sin(static_cast<T>(1)) ; //
+}
+
+template <class T>
+template<int N>
+inline T constant_cos_one<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return cos(static_cast<T>(1)) ; //
+}
+
+template <class T>
+template<int N>
+inline T constant_sinh_one<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return sinh(static_cast<T>(1)) ; //
+}
+
+template <class T>
+template<int N>
+inline T constant_cosh_one<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return cosh(static_cast<T>(1)) ; //
+}
+
+template <class T>
+template<int N>
+inline T constant_phi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return (static_cast<T>(1) + sqrt(static_cast<T>(5)) )/static_cast<T>(2) ; //
+}
+
+template <class T>
+template<int N>
+inline T constant_ln_phi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return log((static_cast<T>(1) + sqrt(static_cast<T>(5)) )/static_cast<T>(2) );
+}
+
+template <class T>
+template<int N>
+inline T constant_one_div_ln_phi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+ return static_cast<T>(1) /
+ log((static_cast<T>(1) + sqrt(static_cast<T>(5)) )/static_cast<T>(2) );
+}
+
+// Zeta
+
+template <class T>
+template<int N>
+inline T constant_zeta_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ BOOST_MATH_STD_USING
+
+ return pi<T, policies::policy<policies::digits2<N> > >()
+ * pi<T, policies::policy<policies::digits2<N> > >()
+ /static_cast<T>(6);
+}
+
+template <class T>
+template<int N>
+inline T constant_zeta_three<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ // http://mathworld.wolfram.com/AperysConstant.html
+ // http://en.wikipedia.org/wiki/Mathematical_constant
+
+ // http://oeis.org/A002117/constant
+ //T zeta3("1.20205690315959428539973816151144999076"
+ // "4986292340498881792271555341838205786313"
+ // "09018645587360933525814619915");
+
+ //"1.202056903159594285399738161511449990, 76498629234049888179227155534183820578631309018645587360933525814619915" A002117
+ // 1.202056903159594285399738161511449990, 76498629234049888179227155534183820578631309018645587360933525814619915780, +00);
+ //"1.2020569031595942 double
+ // http://www.spaennare.se/SSPROG/ssnum.pdf // section 11, Algorithm for Apery's constant zeta(3).
+ // Programs to Calculate some Mathematical Constants to Large Precision, Document Version 1.50
+
+ // by Stefan Spannare September 19, 2007
+ // zeta(3) = 1/64 * sum
+ BOOST_MATH_STD_USING
+ T n_fact=static_cast<T>(1); // build n! for n = 0.
+ T sum = static_cast<double>(77); // Start with n = 0 case.
+ // for n = 0, (77/1) /64 = 1.203125
+ //double lim = std::numeric_limits<double>::epsilon();
+ T lim = N ? ldexp(T(1), 1 - (std::min)(N, tools::digits<T>())) : tools::epsilon<T>();
+ for(unsigned int n = 1; n < 40; ++n)
+ { // three to five decimal digits per term, so 40 should be plenty for 100 decimal digits.
+ //cout << "n = " << n << endl;
+ n_fact *= n; // n!
+ T n_fact_p10 = n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact; // (n!)^10
+ T num = ((205 * n * n) + (250 * n) + 77) * n_fact_p10; // 205n^2 + 250n + 77
+ // int nn = (2 * n + 1);
+ // T d = factorial(nn); // inline factorial.
+ T d = 1;
+ for(unsigned int i = 1; i <= (n+n + 1); ++i) // (2n + 1)
+ {
+ d *= i;
+ }
+ T den = d * d * d * d * d; // [(2n+1)!]^5
+ //cout << "den = " << den << endl;
+ T term = num/den;
+ if (n % 2 != 0)
+ { //term *= -1;
+ sum -= term;
+ }
+ else
+ {
+ sum += term;
+ }
+ //cout << "term = " << term << endl;
+ //cout << "sum/64 = " << sum/64 << endl;
+ if(abs(term) < lim)
+ {
+ break;
+ }
+ }
+ return sum / 64;
+}
+
+template <class T>
+template<int N>
+inline T constant_catalan<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{ // http://oeis.org/A006752/constant
+ //T c("0.915965594177219015054603514932384110774"
+ //"149374281672134266498119621763019776254769479356512926115106248574");
+
+ // 9.159655941772190150546035149323841107, 74149374281672134266498119621763019776254769479356512926115106248574422619, -01);
+
+ // This is equation (entry) 31 from
+ // http://www-2.cs.cmu.edu/~adamchik/articles/catalan/catalan.htm
+ // See also http://www.mpfr.org/algorithms.pdf
+ BOOST_MATH_STD_USING
+ T k_fact = 1;
+ T tk_fact = 1;
+ T sum = 1;
+ T term;
+ T lim = N ? ldexp(T(1), 1 - (std::min)(N, tools::digits<T>())) : tools::epsilon<T>();
+
+ for(unsigned k = 1;; ++k)
+ {
+ k_fact *= k;
+ tk_fact *= (2 * k) * (2 * k - 1);
+ term = k_fact * k_fact / (tk_fact * (2 * k + 1) * (2 * k + 1));
+ sum += term;
+ if(term < lim)
+ {
+ break;
+ }
+ }
+ return boost::math::constants::pi<T, boost::math::policies::policy<> >()
+ * log(2 + boost::math::constants::root_three<T, boost::math::policies::policy<> >())
+ / 8
+ + 3 * sum / 8;
+}
+
+namespace khinchin_detail{
+
+template <class T>
+T zeta_polynomial_series(T s, T sc, int digits)
+{
+ BOOST_MATH_STD_USING
+ //
+ // This is algorithm 3 from:
+ //
+ // "An Efficient Algorithm for the Riemann Zeta Function", P. Borwein,
+ // Canadian Mathematical Society, Conference Proceedings, 2000.
+ // See: http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P155.pdf
+ //
+ BOOST_MATH_STD_USING
+ int n = (digits * 19) / 53;
+ T sum = 0;
+ T two_n = ldexp(T(1), n);
+ int ej_sign = 1;
+ for(int j = 0; j < n; ++j)
+ {
+ sum += ej_sign * -two_n / pow(T(j + 1), s);
+ ej_sign = -ej_sign;
+ }
+ T ej_sum = 1;
+ T ej_term = 1;
+ for(int j = n; j <= 2 * n - 1; ++j)
+ {
+ sum += ej_sign * (ej_sum - two_n) / pow(T(j + 1), s);
+ ej_sign = -ej_sign;
+ ej_term *= 2 * n - j;
+ ej_term /= j - n + 1;
+ ej_sum += ej_term;
+ }
+ return -sum / (two_n * (1 - pow(T(2), sc)));
+}
+
+template <class T>
+T khinchin(int digits)
+{
+ BOOST_MATH_STD_USING
+ T sum = 0;
+ T term;
+ T lim = ldexp(T(1), 1-digits);
+ T factor = 0;
+ unsigned last_k = 1;
+ T num = 1;
+ for(unsigned n = 1;; ++n)
+ {
+ for(unsigned k = last_k; k <= 2 * n - 1; ++k)
+ {
+ factor += num / k;
+ num = -num;
+ }
+ last_k = 2 * n;
+ term = (zeta_polynomial_series(T(2 * n), T(1 - T(2 * n)), digits) - 1) * factor / n;
+ sum += term;
+ if(term < lim)
+ break;
+ }
+ return exp(sum / boost::math::constants::ln_two<T, boost::math::policies::policy<> >());
+}
+
+}
+
+template <class T>
+template<int N>
+inline T constant_khinchin<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ int n = N ? (std::min)(N, tools::digits<T>()) : tools::digits<T>();
+ return khinchin_detail::khinchin<T>(n);
+}
+
+template <class T>
+template<int N>
+inline T constant_extreme_value_skewness<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{ // N[12 Sqrt[6] Zeta[3]/Pi^3, 1101]
+ BOOST_MATH_STD_USING
+ T ev(12 * sqrt(static_cast<T>(6)) * zeta_three<T, policies::policy<policies::digits2<N> > >()
+ / pi_cubed<T, policies::policy<policies::digits2<N> > >() );
+
+//T ev(
+//"1.1395470994046486574927930193898461120875997958365518247216557100852480077060706857071875468869385150"
+//"1894272048688553376986765366075828644841024041679714157616857834895702411080704529137366329462558680"
+//"2015498788776135705587959418756809080074611906006528647805347822929577145038743873949415294942796280"
+//"0895597703063466053535550338267721294164578901640163603544404938283861127819804918174973533694090594"
+//"3094963822672055237678432023017824416203652657301470473548274848068762500300316769691474974950757965"
+//"8640779777748741897542093874605477776538884083378029488863880220988107155275203245233994097178778984"
+//"3488995668362387892097897322246698071290011857605809901090220903955815127463328974447572119951192970"
+//"3684453635456559086126406960279692862247058250100678008419431185138019869693206366891639436908462809"
+//"9756051372711251054914491837034685476095423926553367264355374652153595857163724698198860485357368964"
+//"3807049634423621246870868566707915720704996296083373077647528285782964567312903914752617978405994377"
+//"9064157147206717895272199736902453130842229559980076472936976287378945035706933650987259357729800315");
+
+ return ev;
+}
+
+namespace detail{
+//
+// Calculation of the Glaisher constant depends upon calculating the
+// derivative of the zeta function at 2, we can then use the relation:
+// zeta'(2) = 1/6 pi^2 [euler + ln(2pi)-12ln(A)]
+// To get the constant A.
+// See equation 45 at http://mathworld.wolfram.com/RiemannZetaFunction.html.
+//
+// The derivative of the zeta function is computed by direct differentiation
+// of the relation:
+// (1-2^(1-s))zeta(s) = SUM(n=0, INF){ (-n)^n / (n+1)^s }
+// Which gives us 2 slowly converging but alternating sums to compute,
+// for this we use Algorithm 1 from "Convergent Acceleration of Alternating Series",
+// Henri Cohen, Fernando Rodriguez Villegas and Don Zagier, Experimental Mathematics 9:1 (1999).
+// See http://www.math.utexas.edu/users/villegas/publications/conv-accel.pdf
+//
+template <class T>
+T zeta_series_derivative_2(unsigned digits)
+{
+ // Derivative of the series part, evaluated at 2:
+ BOOST_MATH_STD_USING
+ int n = digits * 301 * 13 / 10000;
+ T d = pow(3 + sqrt(T(8)), n);
+ d = (d + 1 / d) / 2;
+ T b = -1;
+ T c = -d;
+ T s = 0;
+ for(int k = 0; k < n; ++k)
+ {
+ T a = -log(T(k+1)) / ((k+1) * (k+1));
+ c = b - c;
+ s = s + c * a;
+ b = (k + n) * (k - n) * b / ((k + T(0.5f)) * (k + 1));
+ }
+ return s / d;
+}
+
+template <class T>
+T zeta_series_2(unsigned digits)
+{
+ // Series part of zeta at 2:
+ BOOST_MATH_STD_USING
+ int n = digits * 301 * 13 / 10000;
+ T d = pow(3 + sqrt(T(8)), n);
+ d = (d + 1 / d) / 2;
+ T b = -1;
+ T c = -d;
+ T s = 0;
+ for(int k = 0; k < n; ++k)
+ {
+ T a = T(1) / ((k + 1) * (k + 1));
+ c = b - c;
+ s = s + c * a;
+ b = (k + n) * (k - n) * b / ((k + T(0.5f)) * (k + 1));
+ }
+ return s / d;
+}
+
+template <class T>
+inline T zeta_series_lead_2()
+{
+ // lead part at 2:
+ return 2;
+}
+
+template <class T>
+inline T zeta_series_derivative_lead_2()
+{
+ // derivative of lead part at 2:
+ return -2 * boost::math::constants::ln_two<T>();
+}
+
+template <class T>
+inline T zeta_derivative_2(unsigned n)
+{
+ // zeta derivative at 2:
+ return zeta_series_derivative_2<T>(n) * zeta_series_lead_2<T>()
+ + zeta_series_derivative_lead_2<T>() * zeta_series_2<T>(n);
+}
+
+} // namespace detail
+
+template <class T>
+template<int N>
+inline T constant_glaisher<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+
+ BOOST_MATH_STD_USING
+ typedef policies::policy<policies::digits2<N> > forwarding_policy;
+ int n = N ? (std::min)(N, tools::digits<T>()) : tools::digits<T>();
+ T v = detail::zeta_derivative_2<T>(n);
+ v *= 6;
+ v /= boost::math::constants::pi<T, forwarding_policy>() * boost::math::constants::pi<T, forwarding_policy>();
+ v -= boost::math::constants::euler<T, forwarding_policy>();
+ v -= log(2 * boost::math::constants::pi<T, forwarding_policy>());
+ v /= -12;
+ return exp(v);
+
+ /*
+ // from http://mpmath.googlecode.com/svn/data/glaisher.txt
+ // 20,000 digits of the Glaisher-Kinkelin constant A = exp(1/2 - zeta'(-1))
+ // Computed using A = exp((6 (-zeta'(2))/pi^2 + log 2 pi + gamma)/12)
+ // with Euler-Maclaurin summation for zeta'(2).
+ T g(
+ "1.282427129100622636875342568869791727767688927325001192063740021740406308858826"
+ "46112973649195820237439420646120399000748933157791362775280404159072573861727522"
+ "14334327143439787335067915257366856907876561146686449997784962754518174312394652"
+ "76128213808180219264516851546143919901083573730703504903888123418813674978133050"
+ "93770833682222494115874837348064399978830070125567001286994157705432053927585405"
+ "81731588155481762970384743250467775147374600031616023046613296342991558095879293"
+ "36343887288701988953460725233184702489001091776941712153569193674967261270398013"
+ "52652668868978218897401729375840750167472114895288815996668743164513890306962645"
+ "59870469543740253099606800842447417554061490189444139386196089129682173528798629"
+ "88434220366989900606980888785849587494085307347117090132667567503310523405221054"
+ "14176776156308191919997185237047761312315374135304725819814797451761027540834943"
+ "14384965234139453373065832325673954957601692256427736926358821692159870775858274"
+ "69575162841550648585890834128227556209547002918593263079373376942077522290940187");
+
+ return g;
+ */
+}
+
+template <class T>
+template<int N>
+inline T constant_rayleigh_skewness<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{ // 1100 digits of the Rayleigh distribution skewness
+ // N[2 Sqrt[Pi] (Pi - 3)/((4 - Pi)^(3/2)), 1100]
+
+ BOOST_MATH_STD_USING
+ T rs(2 * root_pi<T, policies::policy<policies::digits2<N> > >()
+ * pi_minus_three<T, policies::policy<policies::digits2<N> > >()
+ / pow(four_minus_pi<T, policies::policy<policies::digits2<N> > >(), static_cast<T>(3./2))
+ );
+ // 6.31110657818937138191899351544227779844042203134719497658094585692926819617473725459905027032537306794400047264,
+
+ //"0.6311106578189371381918993515442277798440422031347194976580945856929268196174737254599050270325373067"
+ //"9440004726436754739597525250317640394102954301685809920213808351450851396781817932734836994829371322"
+ //"5797376021347531983451654130317032832308462278373358624120822253764532674177325950686466133508511968"
+ //"2389168716630349407238090652663422922072397393006683401992961569208109477307776249225072042971818671"
+ //"4058887072693437217879039875871765635655476241624825389439481561152126886932506682176611183750503553"
+ //"1218982627032068396407180216351425758181396562859085306247387212297187006230007438534686340210168288"
+ //"8956816965453815849613622117088096547521391672977226658826566757207615552041767516828171274858145957"
+ //"6137539156656005855905288420585194082284972984285863898582313048515484073396332610565441264220790791"
+ //"0194897267890422924599776483890102027823328602965235306539844007677157873140562950510028206251529523"
+ //"7428049693650605954398446899724157486062545281504433364675815915402937209673727753199567661561209251"
+ //"4695589950526053470201635372590001578503476490223746511106018091907936826431407434894024396366284848"); ;
+ return rs;
+}
+
+template <class T>
+template<int N>
+inline T constant_rayleigh_kurtosis_excess<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{ // - (6 Pi^2 - 24 Pi + 16)/((Pi - 4)^2)
+ // Might provide and calculate this using pi_minus_four.
+ BOOST_MATH_STD_USING
+ return - (((static_cast<T>(6) * pi<T, policies::policy<policies::digits2<N> > >()
+ * pi<T, policies::policy<policies::digits2<N> > >())
+ - (static_cast<T>(24) * pi<T, policies::policy<policies::digits2<N> > >()) + static_cast<T>(16) )
+ /
+ ((pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(4))
+ * (pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(4)))
+ );
+}
+
+template <class T>
+template<int N>
+inline T constant_rayleigh_kurtosis<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{ // 3 - (6 Pi^2 - 24 Pi + 16)/((Pi - 4)^2)
+ // Might provide and calculate this using pi_minus_four.
+ BOOST_MATH_STD_USING
+ return static_cast<T>(3) - (((static_cast<T>(6) * pi<T, policies::policy<policies::digits2<N> > >()
+ * pi<T, policies::policy<policies::digits2<N> > >())
+ - (static_cast<T>(24) * pi<T, policies::policy<policies::digits2<N> > >()) + static_cast<T>(16) )
+ /
+ ((pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(4))
+ * (pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(4)))
+ );
+}
+
+template <class T>
+template<int N>
+inline T constant_log2_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return 1 / boost::math::constants::ln_two<T>();
+}
+
+template <class T>
+template<int N>
+inline T constant_quarter_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return boost::math::constants::pi<T>() / 4;
+}
+
+template <class T>
+template<int N>
+inline T constant_one_div_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return 1 / boost::math::constants::pi<T>();
+}
+
+template <class T>
+template<int N>
+inline T constant_two_div_root_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ return 2 * boost::math::constants::one_div_root_pi<T>();
+}
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
+template <class T>
+template<int N>
+inline T constant_first_feigenbaum<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ // We know the constant to 1018 decimal digits.
+ // See: http://www.plouffe.fr/simon/constants/feigenbaum.txt
+ // Also: https://oeis.org/A006890
+ // N is in binary digits; so we multiply by log_2(10)
+
+ static_assert(N < 3.321*1018, "\nThe first Feigenbaum constant cannot be computed at runtime; it is too expensive. It is known to 1018 decimal digits; you must request less than that.");
+ T alpha{"4.6692016091029906718532038204662016172581855774757686327456513430041343302113147371386897440239480138171659848551898151344086271420279325223124429888908908599449354632367134115324817142199474556443658237932020095610583305754586176522220703854106467494942849814533917262005687556659523398756038256372256480040951071283890611844702775854285419801113440175002428585382498335715522052236087250291678860362674527213399057131606875345083433934446103706309452019115876972432273589838903794946257251289097948986768334611626889116563123474460575179539122045562472807095202198199094558581946136877445617396074115614074243754435499204869180982648652368438702799649017397793425134723808737136211601860128186102056381818354097598477964173900328936171432159878240789776614391395764037760537119096932066998361984288981837003229412030210655743295550388845849737034727532121925706958414074661841981961006129640161487712944415901405467941800198133253378592493365883070459999938375411726563553016862529032210862320550634510679399023341675"};
+ return alpha;
+}
+
+template <class T>
+template<int N>
+inline T constant_plastic<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ using std::cbrt;
+ using std::sqrt;
+ return (cbrt(9-sqrt(T(69))) + cbrt(9+sqrt(T(69))))/cbrt(T(18));
+}
+
+
+template <class T>
+template<int N>
+inline T constant_gauss<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ using std::sqrt;
+ T a = sqrt(T(2));
+ T g = 1;
+ const T scale = sqrt(std::numeric_limits<T>::epsilon())/512;
+ while (a-g > scale*g)
+ {
+ T anp1 = (a + g)/2;
+ g = sqrt(a*g);
+ a = anp1;
+ }
+
+ return 2/(a + g);
+}
+
+template <class T>
+template<int N>
+inline T constant_dottie<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ // Error analysis: cos(x(1+d)) - x(1+d) = -(sin(x)+1)xd; plug in x = 0.739 gives -1.236d; take d as half an ulp gives the termination criteria we want.
+ using std::cos;
+ using std::abs;
+ using std::sin;
+ T x{".739085133215160641655312087673873404013411758900757464965680635773284654883547594599376106931766531849801246"};
+ T residual = cos(x) - x;
+ do {
+ x += residual/(sin(x)+1);
+ residual = cos(x) - x;
+ } while(abs(residual) > std::numeric_limits<T>::epsilon());
+ return x;
+}
+
+
+template <class T>
+template<int N>
+inline T constant_reciprocal_fibonacci<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ // Wikipedia says Gosper has deviced a faster algorithm for this, but I read the linked paper and couldn't see it!
+ // In any case, k bits per iteration is fine, though it would be better to sum from smallest to largest.
+ // That said, the condition number is unity, so it should be fine.
+ T x0 = 1;
+ T x1 = 1;
+ T sum = 2;
+ T diff = 1;
+ while (diff > std::numeric_limits<T>::epsilon()) {
+ T tmp = x1 + x0;
+ diff = 1/tmp;
+ sum += diff;
+ x0 = x1;
+ x1 = tmp;
+ }
+ return sum;
+}
+
+template <class T>
+template<int N>
+inline T constant_laplace_limit<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))
+{
+ // If x is the exact root, then the approximate root is given by x(1+delta).
+ // Plugging this into the equation for the Laplace limit gives the residual of approximately
+ // 2.6389delta. Take delta as half an epsilon and give some leeway so we don't get caught in an infinite loop,
+ // gives a termination condition as 2eps.
+ using std::abs;
+ using std::exp;
+ using std::sqrt;
+ T x{"0.66274341934918158097474209710925290705623354911502241752039253499097185308651127724965480259895818168"};
+ T tmp = sqrt(1+x*x);
+ T etmp = exp(tmp);
+ T residual = x*exp(tmp) - 1 - tmp;
+ T df = etmp -x/tmp + etmp*x*x/tmp;
+ do {
+ x -= residual/df;
+ tmp = sqrt(1+x*x);
+ etmp = exp(tmp);
+ residual = x*exp(tmp) - 1 - tmp;
+ df = etmp -x/tmp + etmp*x*x/tmp;
+ } while(abs(residual) > 2*std::numeric_limits<T>::epsilon());
+ return x;
+}
+
+#endif
+
+}
+}
+}
+} // namespaces
+
+#endif // BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED
diff --git a/contrib/restricted/boost/math/include/boost/math/constants/constants.hpp b/contrib/restricted/boost/math/include/boost/math/constants/constants.hpp
new file mode 100644
index 0000000000..730256c666
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/constants/constants.hpp
@@ -0,0 +1,345 @@
+// Copyright John Maddock 2005-2006, 2011.
+// Copyright Paul A. Bristow 2006-2011.
+// Use, modification and distribution are subject to 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_MATH_CONSTANTS_CONSTANTS_INCLUDED
+#define BOOST_MATH_CONSTANTS_CONSTANTS_INCLUDED
+
+#include <boost/math/tools/config.hpp>
+#include <boost/math/tools/cxx03_warn.hpp>
+#include <boost/math/policies/policy.hpp>
+#include <boost/math/tools/precision.hpp>
+#include <boost/math/tools/convert_from_string.hpp>
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127 4701)
+#endif
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#include <utility>
+#include <type_traits>
+
+#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
+//
+// This is the only way we can avoid
+// warning: non-standard suffix on floating constant [-Wpedantic]
+// when building with -Wall -pedantic. Neither __extension__
+// nor #pragma diagnostic ignored work :(
+//
+#pragma GCC system_header
+#endif
+
+namespace boost{ namespace math
+{
+ namespace constants
+ {
+ // To permit other calculations at about 100 decimal digits with some UDT,
+ // it is obviously necessary to define constants to this accuracy.
+
+ // However, some compilers do not accept decimal digits strings as long as this.
+ // So the constant is split into two parts, with the 1st containing at least
+ // long double precision, and the 2nd zero if not needed or known.
+ // The 3rd part permits an exponent to be provided if necessary (use zero if none) -
+ // the other two parameters may only contain decimal digits (and sign and decimal point),
+ // and may NOT include an exponent like 1.234E99.
+ // The second digit string is only used if T is a User-Defined Type,
+ // when the constant is converted to a long string literal and lexical_casted to type T.
+ // (This is necessary because you can't use a numeric constant
+ // since even a long double might not have enough digits).
+
+ enum construction_method
+ {
+ construct_from_float = 1,
+ construct_from_double = 2,
+ construct_from_long_double = 3,
+ construct_from_string = 4,
+ construct_from_float128 = 5,
+ // Must be the largest value above:
+ construct_max = construct_from_float128
+ };
+
+ //
+ // Traits class determines how to convert from string based on whether T has a constructor
+ // from const char* or not:
+ //
+ template <int N>
+ struct dummy_size{};
+
+ //
+ // Max number of binary digits in the string representations of our constants:
+ //
+ static constexpr int max_string_digits = (101 * 1000L) / 301L;
+
+ template <typename Real, typename Policy>
+ struct construction_traits
+ {
+ private:
+ using real_precision = typename policies::precision<Real, Policy>::type;
+ using float_precision = typename policies::precision<float, Policy>::type;
+ using double_precision = typename policies::precision<double, Policy>::type;
+ using long_double_precision = typename policies::precision<long double, Policy>::type;
+ public:
+ using type = std::integral_constant<int,
+ (0 == real_precision::value) ? 0 :
+ std::is_convertible<float, Real>::value && (real_precision::value <= float_precision::value)? construct_from_float :
+ std::is_convertible<double, Real>::value && (real_precision::value <= double_precision::value)? construct_from_double :
+ std::is_convertible<long double, Real>::value && (real_precision::value <= long_double_precision::value)? construct_from_long_double :
+#ifdef BOOST_MATH_USE_FLOAT128
+ std::is_convertible<BOOST_MATH_FLOAT128_TYPE, Real>::value && (real_precision::value <= 113) ? construct_from_float128 :
+#endif
+ (real_precision::value <= max_string_digits) ? construct_from_string : real_precision::value
+ >;
+ };
+
+#ifdef BOOST_HAS_THREADS
+#define BOOST_MATH_CONSTANT_THREAD_HELPER(name, prefix) \
+ boost::once_flag f = BOOST_ONCE_INIT;\
+ boost::call_once(f, &BOOST_JOIN(BOOST_JOIN(string_, get_), name)<T>);
+#else
+#define BOOST_MATH_CONSTANT_THREAD_HELPER(name, prefix)
+#endif
+
+ namespace detail{
+
+ template <class Real, class Policy = boost::math::policies::policy<> >
+ struct constant_return
+ {
+ using construct_type = typename construction_traits<Real, Policy>::type;
+ using type = typename std::conditional<
+ (construct_type::value == construct_from_string) || (construct_type::value > construct_max),
+ const Real&, Real>::type;
+ };
+
+ template <typename T, const T& (*F)()>
+ struct constant_initializer
+ {
+ static void force_instantiate()
+ {
+ init.force_instantiate();
+ }
+ private:
+ struct initializer
+ {
+ initializer()
+ {
+ F();
+ }
+ void force_instantiate()const{}
+ };
+ static const initializer init;
+ };
+
+ template <typename T, const T& (*F)()>
+ typename constant_initializer<T, F>::initializer const constant_initializer<T, F>::init;
+
+ template <typename T, int N, const T& (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ struct constant_initializer2
+ {
+ static void force_instantiate()
+ {
+ init.force_instantiate();
+ }
+ private:
+ struct initializer
+ {
+ initializer()
+ {
+ F();
+ }
+ void force_instantiate()const{}
+ };
+ static const initializer init;
+ };
+
+ template <typename T, int N, const T& (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ typename constant_initializer2<T, N, F>::initializer const constant_initializer2<T, N, F>::init;
+
+ }
+
+#ifdef BOOST_MATH_USE_FLOAT128
+# define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \
+ static inline constexpr T get(const std::integral_constant<int, construct_from_float128>&) noexcept\
+ { return BOOST_JOIN(x, Q); }
+#else
+# define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x)
+#endif
+
+#ifdef BOOST_NO_CXX11_THREAD_LOCAL
+# define BOOST_MATH_PRECOMPUTE_IF_NOT_LOCAL(constant_, name) constant_initializer<T, & BOOST_JOIN(constant_, name)<T>::get_from_variable_precision>::force_instantiate();
+#else
+# define BOOST_MATH_PRECOMPUTE_IF_NOT_LOCAL(constant_, name)
+#endif
+
+#define BOOST_DEFINE_MATH_CONSTANT(name, x, y)\
+ namespace detail{\
+ template <typename T> struct BOOST_JOIN(constant_, name){\
+ private:\
+ /* The default implementations come next: */ \
+ static inline const T& get_from_string()\
+ {\
+ static const T result(boost::math::tools::convert_from_string<T>(y));\
+ return result;\
+ }\
+ /* This one is for very high precision that is none the less known at compile time: */ \
+ template <int N> static T compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)));\
+ template <int N> static inline const T& get_from_compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant<int, N>)))\
+ {\
+ static const T result = compute<N>();\
+ return result;\
+ }\
+ static inline const T& get_from_variable_precision()\
+ {\
+ static BOOST_MATH_THREAD_LOCAL int digits = 0;\
+ static BOOST_MATH_THREAD_LOCAL T value;\
+ int current_digits = boost::math::tools::digits<T>();\
+ if(digits != current_digits)\
+ {\
+ value = current_digits > max_string_digits ? compute<0>() : T(boost::math::tools::convert_from_string<T>(y));\
+ digits = current_digits; \
+ }\
+ return value;\
+ }\
+ /* public getters come next */\
+ public:\
+ static inline const T& get(const std::integral_constant<int, construct_from_string>&)\
+ {\
+ constant_initializer<T, & BOOST_JOIN(constant_, name)<T>::get_from_string >::force_instantiate();\
+ return get_from_string();\
+ }\
+ static inline constexpr T get(const std::integral_constant<int, construct_from_float>) noexcept\
+ { return BOOST_JOIN(x, F); }\
+ static inline constexpr T get(const std::integral_constant<int, construct_from_double>&) noexcept\
+ { return x; }\
+ static inline constexpr T get(const std::integral_constant<int, construct_from_long_double>&) noexcept\
+ { return BOOST_JOIN(x, L); }\
+ BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \
+ template <int N> static inline const T& get(const std::integral_constant<int, N>&)\
+ {\
+ constant_initializer2<T, N, & BOOST_JOIN(constant_, name)<T>::template get_from_compute<N> >::force_instantiate();\
+ return get_from_compute<N>(); \
+ }\
+ /* This one is for true arbitrary precision, which may well vary at runtime: */ \
+ static inline T get(const std::integral_constant<int, 0>&)\
+ {\
+ BOOST_MATH_PRECOMPUTE_IF_NOT_LOCAL(constant_, name)\
+ return get_from_variable_precision(); }\
+ }; /* end of struct */\
+ } /* namespace detail */ \
+ \
+ \
+ /* The actual forwarding function: */ \
+ template <typename T, typename Policy> inline constexpr typename detail::constant_return<T, Policy>::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy)) BOOST_MATH_NOEXCEPT(T)\
+ { return detail:: BOOST_JOIN(constant_, name)<T>::get(typename construction_traits<T, Policy>::type()); }\
+ template <typename T> inline constexpr typename detail::constant_return<T>::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) BOOST_MATH_NOEXCEPT(T)\
+ { return name<T, boost::math::policies::policy<> >(); }\
+ \
+ \
+ /* Now the namespace specific versions: */ \
+ } namespace float_constants{ static constexpr float name = BOOST_JOIN(x, F); }\
+ namespace double_constants{ static constexpr double name = x; } \
+ namespace long_double_constants{ static constexpr long double name = BOOST_JOIN(x, L); }\
+ namespace constants{
+
+ BOOST_DEFINE_MATH_CONSTANT(half, 5.000000000000000000000000000000000000e-01, "5.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-01")
+ BOOST_DEFINE_MATH_CONSTANT(third, 3.333333333333333333333333333333333333e-01, "3.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333e-01")
+ BOOST_DEFINE_MATH_CONSTANT(twothirds, 6.666666666666666666666666666666666666e-01, "6.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01")
+ BOOST_DEFINE_MATH_CONSTANT(two_thirds, 6.666666666666666666666666666666666666e-01, "6.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01")
+ BOOST_DEFINE_MATH_CONSTANT(sixth, 1.666666666666666666666666666666666666e-01, "1.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01")
+ BOOST_DEFINE_MATH_CONSTANT(three_quarters, 7.500000000000000000000000000000000000e-01, "7.50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-01")
+ BOOST_DEFINE_MATH_CONSTANT(root_two, 1.414213562373095048801688724209698078e+00, "1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157273501384623e+00")
+ BOOST_DEFINE_MATH_CONSTANT(root_three, 1.732050807568877293527446341505872366e+00, "1.73205080756887729352744634150587236694280525381038062805580697945193301690880003708114618675724857567562614142e+00")
+ BOOST_DEFINE_MATH_CONSTANT(half_root_two, 7.071067811865475244008443621048490392e-01, "7.07106781186547524400844362104849039284835937688474036588339868995366239231053519425193767163820786367506923115e-01")
+ BOOST_DEFINE_MATH_CONSTANT(ln_two, 6.931471805599453094172321214581765680e-01, "6.93147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687542001481021e-01")
+ BOOST_DEFINE_MATH_CONSTANT(ln_ln_two, -3.665129205816643270124391582326694694e-01, "-3.66512920581664327012439158232669469454263447837105263053677713670561615319352738549455822856698908358302523045e-01")
+ BOOST_DEFINE_MATH_CONSTANT(root_ln_four, 1.177410022515474691011569326459699637e+00, "1.17741002251547469101156932645969963774738568938582053852252575650002658854698492680841813836877081106747157858e+00")
+ BOOST_DEFINE_MATH_CONSTANT(one_div_root_two, 7.071067811865475244008443621048490392e-01, "7.07106781186547524400844362104849039284835937688474036588339868995366239231053519425193767163820786367506923115e-01")
+ BOOST_DEFINE_MATH_CONSTANT(pi, 3.141592653589793238462643383279502884e+00, "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651e+00")
+ BOOST_DEFINE_MATH_CONSTANT(half_pi, 1.570796326794896619231321691639751442e+00, "1.57079632679489661923132169163975144209858469968755291048747229615390820314310449931401741267105853399107404326e+00")
+ BOOST_DEFINE_MATH_CONSTANT(third_pi, 1.047197551196597746154214461093167628e+00, "1.04719755119659774615421446109316762806572313312503527365831486410260546876206966620934494178070568932738269550e+00")
+ BOOST_DEFINE_MATH_CONSTANT(sixth_pi, 5.235987755982988730771072305465838140e-01, "5.23598775598298873077107230546583814032861566562517636829157432051302734381034833104672470890352844663691347752e-01")
+ BOOST_DEFINE_MATH_CONSTANT(two_pi, 6.283185307179586476925286766559005768e+00, "6.28318530717958647692528676655900576839433879875021164194988918461563281257241799725606965068423413596429617303e+00")
+ BOOST_DEFINE_MATH_CONSTANT(two_thirds_pi, 2.094395102393195492308428922186335256e+00, "2.09439510239319549230842892218633525613144626625007054731662972820521093752413933241868988356141137865476539101e+00")
+ BOOST_DEFINE_MATH_CONSTANT(three_quarters_pi, 2.356194490192344928846982537459627163e+00, "2.35619449019234492884698253745962716314787704953132936573120844423086230471465674897102611900658780098661106488e+00")
+ BOOST_DEFINE_MATH_CONSTANT(four_thirds_pi, 4.188790204786390984616857844372670512e+00, "4.18879020478639098461685784437267051226289253250014109463325945641042187504827866483737976712282275730953078202e+00")
+ BOOST_DEFINE_MATH_CONSTANT(one_div_two_pi, 1.591549430918953357688837633725143620e-01, "1.59154943091895335768883763372514362034459645740456448747667344058896797634226535090113802766253085956072842727e-01")
+ BOOST_DEFINE_MATH_CONSTANT(one_div_root_two_pi, 3.989422804014326779399460599343818684e-01, "3.98942280401432677939946059934381868475858631164934657665925829670657925899301838501252333907306936430302558863e-01")
+ BOOST_DEFINE_MATH_CONSTANT(root_pi, 1.772453850905516027298167483341145182e+00, "1.77245385090551602729816748334114518279754945612238712821380778985291128459103218137495065673854466541622682362e+00")
+ BOOST_DEFINE_MATH_CONSTANT(root_half_pi, 1.253314137315500251207882642405522626e+00, "1.25331413731550025120788264240552262650349337030496915831496178817114682730392098747329791918902863305800498633e+00")
+ BOOST_DEFINE_MATH_CONSTANT(root_two_pi, 2.506628274631000502415765284811045253e+00, "2.50662827463100050241576528481104525300698674060993831662992357634229365460784197494659583837805726611600997267e+00")
+ BOOST_DEFINE_MATH_CONSTANT(log_root_two_pi, 9.189385332046727417803297364056176398e-01, "9.18938533204672741780329736405617639861397473637783412817151540482765695927260397694743298635954197622005646625e-01")
+ BOOST_DEFINE_MATH_CONSTANT(one_div_root_pi, 5.641895835477562869480794515607725858e-01, "5.64189583547756286948079451560772585844050629328998856844085721710642468441493414486743660202107363443028347906e-01")
+ BOOST_DEFINE_MATH_CONSTANT(root_one_div_pi, 5.641895835477562869480794515607725858e-01, "5.64189583547756286948079451560772585844050629328998856844085721710642468441493414486743660202107363443028347906e-01")
+ BOOST_DEFINE_MATH_CONSTANT(pi_minus_three, 1.415926535897932384626433832795028841e-01, "1.41592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513e-01")
+ BOOST_DEFINE_MATH_CONSTANT(four_minus_pi, 8.584073464102067615373566167204971158e-01, "8.58407346410206761537356616720497115802830600624894179025055407692183593713791001371965174657882932017851913487e-01")
+ //BOOST_DEFINE_MATH_CONSTANT(pow23_four_minus_pi, 7.953167673715975443483953350568065807e-01, "7.95316767371597544348395335056806580727639173327713205445302234388856268267518187590758006888600828436839800178e-01")
+ BOOST_DEFINE_MATH_CONSTANT(pi_pow_e, 2.245915771836104547342715220454373502e+01, "2.24591577183610454734271522045437350275893151339966922492030025540669260403991179123185197527271430315314500731e+01")
+ BOOST_DEFINE_MATH_CONSTANT(pi_sqr, 9.869604401089358618834490999876151135e+00, "9.86960440108935861883449099987615113531369940724079062641334937622004482241920524300177340371855223182402591377e+00")
+ BOOST_DEFINE_MATH_CONSTANT(pi_sqr_div_six, 1.644934066848226436472415166646025189e+00, "1.64493406684822643647241516664602518921894990120679843773555822937000747040320087383362890061975870530400431896e+00")
+ BOOST_DEFINE_MATH_CONSTANT(pi_cubed, 3.100627668029982017547631506710139520e+01, "3.10062766802998201754763150671013952022252885658851076941445381038063949174657060375667010326028861930301219616e+01")
+ BOOST_DEFINE_MATH_CONSTANT(cbrt_pi, 1.464591887561523263020142527263790391e+00, "1.46459188756152326302014252726379039173859685562793717435725593713839364979828626614568206782035382089750397002e+00")
+ BOOST_DEFINE_MATH_CONSTANT(one_div_cbrt_pi, 6.827840632552956814670208331581645981e-01, "6.82784063255295681467020833158164598108367515632448804042681583118899226433403918237673501922595519865685577274e-01")
+ BOOST_DEFINE_MATH_CONSTANT(log2_e, 1.44269504088896340735992468100189213742664595415298, "1.44269504088896340735992468100189213742664595415298593413544940693110921918118507988552662289350634449699751830965e+00")
+ BOOST_DEFINE_MATH_CONSTANT(e, 2.718281828459045235360287471352662497e+00, "2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193e+00")
+ BOOST_DEFINE_MATH_CONSTANT(exp_minus_half, 6.065306597126334236037995349911804534e-01, "6.06530659712633423603799534991180453441918135487186955682892158735056519413748423998647611507989456026423789794e-01")
+ BOOST_DEFINE_MATH_CONSTANT(exp_minus_one, 3.678794411714423215955237701614608674e-01, "3.67879441171442321595523770161460867445811131031767834507836801697461495744899803357147274345919643746627325277e-01")
+ BOOST_DEFINE_MATH_CONSTANT(e_pow_pi, 2.314069263277926900572908636794854738e+01, "2.31406926327792690057290863679485473802661062426002119934450464095243423506904527835169719970675492196759527048e+01")
+ BOOST_DEFINE_MATH_CONSTANT(root_e, 1.648721270700128146848650787814163571e+00, "1.64872127070012814684865078781416357165377610071014801157507931164066102119421560863277652005636664300286663776e+00")
+ BOOST_DEFINE_MATH_CONSTANT(log10_e, 4.342944819032518276511289189166050822e-01, "4.34294481903251827651128918916605082294397005803666566114453783165864649208870774729224949338431748318706106745e-01")
+ BOOST_DEFINE_MATH_CONSTANT(one_div_log10_e, 2.302585092994045684017991454684364207e+00, "2.30258509299404568401799145468436420760110148862877297603332790096757260967735248023599720508959829834196778404e+00")
+ BOOST_DEFINE_MATH_CONSTANT(ln_ten, 2.302585092994045684017991454684364207e+00, "2.30258509299404568401799145468436420760110148862877297603332790096757260967735248023599720508959829834196778404e+00")
+ BOOST_DEFINE_MATH_CONSTANT(degree, 1.745329251994329576923690768488612713e-02, "1.74532925199432957692369076848861271344287188854172545609719144017100911460344944368224156963450948221230449251e-02")
+ BOOST_DEFINE_MATH_CONSTANT(radian, 5.729577951308232087679815481410517033e+01, "5.72957795130823208767981548141051703324054724665643215491602438612028471483215526324409689958511109441862233816e+01")
+ BOOST_DEFINE_MATH_CONSTANT(sin_one, 8.414709848078965066525023216302989996e-01, "8.41470984807896506652502321630298999622563060798371065672751709991910404391239668948639743543052695854349037908e-01")
+ BOOST_DEFINE_MATH_CONSTANT(cos_one, 5.403023058681397174009366074429766037e-01, "5.40302305868139717400936607442976603732310420617922227670097255381100394774471764517951856087183089343571731160e-01")
+ BOOST_DEFINE_MATH_CONSTANT(sinh_one, 1.175201193643801456882381850595600815e+00, "1.17520119364380145688238185059560081515571798133409587022956541301330756730432389560711745208962339184041953333e+00")
+ BOOST_DEFINE_MATH_CONSTANT(cosh_one, 1.543080634815243778477905620757061682e+00, "1.54308063481524377847790562075706168260152911236586370473740221471076906304922369896426472643554303558704685860e+00")
+ BOOST_DEFINE_MATH_CONSTANT(phi, 1.618033988749894848204586834365638117e+00, "1.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748475408808e+00")
+ BOOST_DEFINE_MATH_CONSTANT(ln_phi, 4.812118250596034474977589134243684231e-01, "4.81211825059603447497758913424368423135184334385660519661018168840163867608221774412009429122723474997231839958e-01")
+ BOOST_DEFINE_MATH_CONSTANT(one_div_ln_phi, 2.078086921235027537601322606117795767e+00, "2.07808692123502753760132260611779576774219226778328348027813992191974386928553540901445615414453604821933918634e+00")
+ BOOST_DEFINE_MATH_CONSTANT(euler, 5.772156649015328606065120900824024310e-01, "5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447250e-01")
+ BOOST_DEFINE_MATH_CONSTANT(one_div_euler, 1.732454714600633473583025315860829681e+00, "1.73245471460063347358302531586082968115577655226680502204843613287065531408655243008832840219409928068072365714e+00")
+ BOOST_DEFINE_MATH_CONSTANT(euler_sqr, 3.331779238077186743183761363552442266e-01, "3.33177923807718674318376136355244226659417140249629743150833338002265793695756669661263268631715977303039565603e-01")
+ BOOST_DEFINE_MATH_CONSTANT(zeta_two, 1.644934066848226436472415166646025189e+00, "1.64493406684822643647241516664602518921894990120679843773555822937000747040320087383362890061975870530400431896e+00")
+ BOOST_DEFINE_MATH_CONSTANT(zeta_three, 1.202056903159594285399738161511449990e+00, "1.20205690315959428539973816151144999076498629234049888179227155534183820578631309018645587360933525814619915780e+00")
+ BOOST_DEFINE_MATH_CONSTANT(catalan, 9.159655941772190150546035149323841107e-01, "9.15965594177219015054603514932384110774149374281672134266498119621763019776254769479356512926115106248574422619e-01")
+ BOOST_DEFINE_MATH_CONSTANT(glaisher, 1.282427129100622636875342568869791727e+00, "1.28242712910062263687534256886979172776768892732500119206374002174040630885882646112973649195820237439420646120e+00")
+ BOOST_DEFINE_MATH_CONSTANT(khinchin, 2.685452001065306445309714835481795693e+00, "2.68545200106530644530971483548179569382038229399446295305115234555721885953715200280114117493184769799515346591e+00")
+ BOOST_DEFINE_MATH_CONSTANT(extreme_value_skewness, 1.139547099404648657492793019389846112e+00, "1.13954709940464865749279301938984611208759979583655182472165571008524800770607068570718754688693851501894272049e+00")
+ BOOST_DEFINE_MATH_CONSTANT(rayleigh_skewness, 6.311106578189371381918993515442277798e-01, "6.31110657818937138191899351544227779844042203134719497658094585692926819617473725459905027032537306794400047264e-01")
+ BOOST_DEFINE_MATH_CONSTANT(rayleigh_kurtosis, 3.245089300687638062848660410619754415e+00, "3.24508930068763806284866041061975441541706673178920936177133764493367904540874159051490619368679348977426462633e+00")
+ BOOST_DEFINE_MATH_CONSTANT(rayleigh_kurtosis_excess, 2.450893006876380628486604106197544154e-01, "2.45089300687638062848660410619754415417066731789209361771337644933679045408741590514906193686793489774264626328e-01")
+
+ BOOST_DEFINE_MATH_CONSTANT(two_div_pi, 6.366197723675813430755350534900574481e-01, "6.36619772367581343075535053490057448137838582961825794990669376235587190536906140360455211065012343824291370907e-01")
+ BOOST_DEFINE_MATH_CONSTANT(root_two_div_pi, 7.978845608028653558798921198687637369e-01, "7.97884560802865355879892119868763736951717262329869315331851659341315851798603677002504667814613872860605117725e-01")
+ BOOST_DEFINE_MATH_CONSTANT(quarter_pi, 0.785398163397448309615660845819875721049292, "0.785398163397448309615660845819875721049292349843776455243736148076954101571552249657008706335529266995537021628320576661773")
+ BOOST_DEFINE_MATH_CONSTANT(one_div_pi, 0.3183098861837906715377675267450287240689192, "0.31830988618379067153776752674502872406891929148091289749533468811779359526845307018022760553250617191214568545351")
+ BOOST_DEFINE_MATH_CONSTANT(two_div_root_pi, 1.12837916709551257389615890312154517168810125, "1.12837916709551257389615890312154517168810125865799771368817144342128493688298682897348732040421472688605669581272")
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
+ BOOST_DEFINE_MATH_CONSTANT(first_feigenbaum, 4.66920160910299067185320382046620161725818557747576863274, "4.6692016091029906718532038204662016172581855774757686327456513430041343302113147371386897440239480138171")
+ BOOST_DEFINE_MATH_CONSTANT(plastic, 1.324717957244746025960908854478097340734404056901733364534, "1.32471795724474602596090885447809734073440405690173336453401505030282785124554759405469934798178728032991")
+ BOOST_DEFINE_MATH_CONSTANT(gauss, 0.834626841674073186281429732799046808993993013490347002449, "0.83462684167407318628142973279904680899399301349034700244982737010368199270952641186969116035127532412906785")
+ BOOST_DEFINE_MATH_CONSTANT(dottie, 0.739085133215160641655312087673873404013411758900757464965, "0.739085133215160641655312087673873404013411758900757464965680635773284654883547594599376106931766531849801246")
+ BOOST_DEFINE_MATH_CONSTANT(reciprocal_fibonacci, 3.35988566624317755317201130291892717968890513, "3.35988566624317755317201130291892717968890513373196848649555381532513031899668338361541621645679008729704")
+ BOOST_DEFINE_MATH_CONSTANT(laplace_limit, 0.662743419349181580974742097109252907056233549115022417, "0.66274341934918158097474209710925290705623354911502241752039253499097185308651127724965480259895818168")
+#endif
+
+template <typename T>
+inline constexpr T tau() { return two_pi<T>(); }
+
+} // namespace constants
+} // namespace math
+} // namespace boost
+
+//
+// We deliberately include this *after* all the declarations above,
+// that way the calculation routines can call on other constants above:
+//
+#include <boost/math/constants/calculate_constants.hpp>
+
+#endif // BOOST_MATH_CONSTANTS_CONSTANTS_INCLUDED
+
+
diff --git a/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_cmath.hpp b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_cmath.hpp
new file mode 100644
index 0000000000..a066c57169
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_cmath.hpp
@@ -0,0 +1,1057 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2014.
+// Copyright John Maddock 2014.
+// Copyright Paul Bristow 2014.
+// 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)
+//
+
+// Implement quadruple-precision <cmath> support.
+
+#ifndef BOOST_MATH_CSTDFLOAT_CMATH_2014_02_15_HPP_
+#define BOOST_MATH_CSTDFLOAT_CMATH_2014_02_15_HPP_
+
+#include <boost/math/cstdfloat/cstdfloat_types.hpp>
+#include <boost/math/cstdfloat/cstdfloat_limits.hpp>
+
+#if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+
+#include <cstdint>
+#include <cmath>
+#include <stdexcept>
+#include <iostream>
+#include <type_traits>
+#include <memory>
+#include <boost/math/tools/assert.hpp>
+#include <boost/math/tools/throw_exception.hpp>
+
+#if defined(_WIN32) && defined(__GNUC__)
+ // Several versions of Mingw and probably cygwin too have broken
+ // libquadmath implementations that segfault as soon as you call
+ // expq or any function that depends on it.
+#define BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+#endif
+
+// Here is a helper function used for raising the value of a given
+// floating-point type to the power of n, where n has integral type.
+namespace boost {
+ namespace math {
+ namespace cstdfloat {
+ namespace detail {
+
+ template<class float_type, class integer_type>
+ inline float_type pown(const float_type& x, const integer_type p)
+ {
+ const bool isneg = (x < 0);
+ const bool isnan = (x != x);
+ const bool isinf = ((!isneg) ? bool(+x > (std::numeric_limits<float_type>::max)())
+ : bool(-x > (std::numeric_limits<float_type>::max)()));
+
+ if (isnan) { return x; }
+
+ if (isinf) { return std::numeric_limits<float_type>::quiet_NaN(); }
+
+ const bool x_is_neg = (x < 0);
+ const float_type abs_x = (x_is_neg ? -x : x);
+
+ if (p < static_cast<integer_type>(0))
+ {
+ if (abs_x < (std::numeric_limits<float_type>::min)())
+ {
+ return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
+ }
+ else
+ {
+ return float_type(1) / pown(x, static_cast<integer_type>(-p));
+ }
+ }
+
+ if (p == static_cast<integer_type>(0))
+ {
+ return float_type(1);
+ }
+ else
+ {
+ if (p == static_cast<integer_type>(1)) { return x; }
+
+ if (abs_x > (std::numeric_limits<float_type>::max)())
+ {
+ return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
+ }
+
+ if (p == static_cast<integer_type>(2)) { return (x * x); }
+ else if (p == static_cast<integer_type>(3)) { return ((x * x) * x); }
+ else if (p == static_cast<integer_type>(4)) { const float_type x2 = (x * x); return (x2 * x2); }
+ else
+ {
+ // The variable xn stores the binary powers of x.
+ float_type result(((p % integer_type(2)) != integer_type(0)) ? x : float_type(1));
+ float_type xn(x);
+
+ integer_type p2 = p;
+
+ while (integer_type(p2 /= 2) != integer_type(0))
+ {
+ // Square xn for each binary power.
+ xn *= xn;
+
+ const bool has_binary_power = (integer_type(p2 % integer_type(2)) != integer_type(0));
+
+ if (has_binary_power)
+ {
+ // Multiply the result with each binary power contained in the exponent.
+ result *= xn;
+ }
+ }
+
+ return result;
+ }
+ }
+ }
+
+ }
+ }
+ }
+} // boost::math::cstdfloat::detail
+
+// We will now define preprocessor symbols representing quadruple-precision <cmath> functions.
+#if defined(__INTEL_COMPILER)
+#define BOOST_CSTDFLOAT_FLOAT128_LDEXP __ldexpq
+#define BOOST_CSTDFLOAT_FLOAT128_FREXP __frexpq
+#define BOOST_CSTDFLOAT_FLOAT128_FABS __fabsq
+#define BOOST_CSTDFLOAT_FLOAT128_FLOOR __floorq
+#define BOOST_CSTDFLOAT_FLOAT128_CEIL __ceilq
+#if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT)
+#define BOOST_CSTDFLOAT_FLOAT128_SQRT __sqrtq
+#endif
+#define BOOST_CSTDFLOAT_FLOAT128_TRUNC __truncq
+#define BOOST_CSTDFLOAT_FLOAT128_EXP __expq
+#define BOOST_CSTDFLOAT_FLOAT128_EXPM1 __expm1q
+#define BOOST_CSTDFLOAT_FLOAT128_POW __powq
+#define BOOST_CSTDFLOAT_FLOAT128_LOG __logq
+#define BOOST_CSTDFLOAT_FLOAT128_LOG10 __log10q
+#define BOOST_CSTDFLOAT_FLOAT128_SIN __sinq
+#define BOOST_CSTDFLOAT_FLOAT128_COS __cosq
+#define BOOST_CSTDFLOAT_FLOAT128_TAN __tanq
+#define BOOST_CSTDFLOAT_FLOAT128_ASIN __asinq
+#define BOOST_CSTDFLOAT_FLOAT128_ACOS __acosq
+#define BOOST_CSTDFLOAT_FLOAT128_ATAN __atanq
+#define BOOST_CSTDFLOAT_FLOAT128_SINH __sinhq
+#define BOOST_CSTDFLOAT_FLOAT128_COSH __coshq
+#define BOOST_CSTDFLOAT_FLOAT128_TANH __tanhq
+#define BOOST_CSTDFLOAT_FLOAT128_ASINH __asinhq
+#define BOOST_CSTDFLOAT_FLOAT128_ACOSH __acoshq
+#define BOOST_CSTDFLOAT_FLOAT128_ATANH __atanhq
+#define BOOST_CSTDFLOAT_FLOAT128_FMOD __fmodq
+#define BOOST_CSTDFLOAT_FLOAT128_ATAN2 __atan2q
+#define BOOST_CSTDFLOAT_FLOAT128_LGAMMA __lgammaq
+#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA __tgammaq
+// begin more functions
+#define BOOST_CSTDFLOAT_FLOAT128_REMAINDER __remainderq
+#define BOOST_CSTDFLOAT_FLOAT128_REMQUO __remquoq
+#define BOOST_CSTDFLOAT_FLOAT128_FMA __fmaq
+#define BOOST_CSTDFLOAT_FLOAT128_FMAX __fmaxq
+#define BOOST_CSTDFLOAT_FLOAT128_FMIN __fminq
+#define BOOST_CSTDFLOAT_FLOAT128_FDIM __fdimq
+#define BOOST_CSTDFLOAT_FLOAT128_NAN __nanq
+//#define BOOST_CSTDFLOAT_FLOAT128_EXP2 __exp2q
+#define BOOST_CSTDFLOAT_FLOAT128_LOG2 __log2q
+#define BOOST_CSTDFLOAT_FLOAT128_LOG1P __log1pq
+#define BOOST_CSTDFLOAT_FLOAT128_CBRT __cbrtq
+#define BOOST_CSTDFLOAT_FLOAT128_HYPOT __hypotq
+#define BOOST_CSTDFLOAT_FLOAT128_ERF __erfq
+#define BOOST_CSTDFLOAT_FLOAT128_ERFC __erfcq
+#define BOOST_CSTDFLOAT_FLOAT128_LLROUND __llroundq
+#define BOOST_CSTDFLOAT_FLOAT128_LROUND __lroundq
+#define BOOST_CSTDFLOAT_FLOAT128_ROUND __roundq
+#define BOOST_CSTDFLOAT_FLOAT128_NEARBYINT __nearbyintq
+#define BOOST_CSTDFLOAT_FLOAT128_LLRINT __llrintq
+#define BOOST_CSTDFLOAT_FLOAT128_LRINT __lrintq
+#define BOOST_CSTDFLOAT_FLOAT128_RINT __rintq
+#define BOOST_CSTDFLOAT_FLOAT128_MODF __modfq
+#define BOOST_CSTDFLOAT_FLOAT128_SCALBLN __scalblnq
+#define BOOST_CSTDFLOAT_FLOAT128_SCALBN __scalbnq
+#define BOOST_CSTDFLOAT_FLOAT128_ILOGB __ilogbq
+#define BOOST_CSTDFLOAT_FLOAT128_LOGB __logbq
+#define BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER __nextafterq
+//#define BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD __nexttowardq
+#define BOOST_CSTDFLOAT_FLOAT128_COPYSIGN __copysignq
+#define BOOST_CSTDFLOAT_FLOAT128_SIGNBIT __signbitq
+//#define BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY __fpclassifyq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISFINITE __isfiniteq
+#define BOOST_CSTDFLOAT_FLOAT128_ISINF __isinfq
+#define BOOST_CSTDFLOAT_FLOAT128_ISNAN __isnanq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISNORMAL __isnormalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATER __isgreaterq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL __isgreaterequalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESS __islessq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL __islessequalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER __islessgreaterq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED __isunorderedq
+// end more functions
+#elif defined(__GNUC__)
+#define BOOST_CSTDFLOAT_FLOAT128_LDEXP ldexpq
+#define BOOST_CSTDFLOAT_FLOAT128_FREXP frexpq
+#define BOOST_CSTDFLOAT_FLOAT128_FABS fabsq
+#define BOOST_CSTDFLOAT_FLOAT128_FLOOR floorq
+#define BOOST_CSTDFLOAT_FLOAT128_CEIL ceilq
+#if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT)
+#define BOOST_CSTDFLOAT_FLOAT128_SQRT sqrtq
+#endif
+#define BOOST_CSTDFLOAT_FLOAT128_TRUNC truncq
+#define BOOST_CSTDFLOAT_FLOAT128_POW powq
+#define BOOST_CSTDFLOAT_FLOAT128_LOG logq
+#define BOOST_CSTDFLOAT_FLOAT128_LOG10 log10q
+#define BOOST_CSTDFLOAT_FLOAT128_SIN sinq
+#define BOOST_CSTDFLOAT_FLOAT128_COS cosq
+#define BOOST_CSTDFLOAT_FLOAT128_TAN tanq
+#define BOOST_CSTDFLOAT_FLOAT128_ASIN asinq
+#define BOOST_CSTDFLOAT_FLOAT128_ACOS acosq
+#define BOOST_CSTDFLOAT_FLOAT128_ATAN atanq
+#define BOOST_CSTDFLOAT_FLOAT128_FMOD fmodq
+#define BOOST_CSTDFLOAT_FLOAT128_ATAN2 atan2q
+#define BOOST_CSTDFLOAT_FLOAT128_LGAMMA lgammaq
+#if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS)
+#define BOOST_CSTDFLOAT_FLOAT128_EXP expq
+#define BOOST_CSTDFLOAT_FLOAT128_EXPM1 expm1q
+#define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq
+#define BOOST_CSTDFLOAT_FLOAT128_COSH coshq
+#define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq
+#define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq
+#define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq
+#define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq
+#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq
+#else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+#define BOOST_CSTDFLOAT_FLOAT128_EXP expq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_COSH coshq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq_patch
+#endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+// begin more functions
+#define BOOST_CSTDFLOAT_FLOAT128_REMAINDER remainderq
+#define BOOST_CSTDFLOAT_FLOAT128_REMQUO remquoq
+#define BOOST_CSTDFLOAT_FLOAT128_FMA fmaq
+#define BOOST_CSTDFLOAT_FLOAT128_FMAX fmaxq
+#define BOOST_CSTDFLOAT_FLOAT128_FMIN fminq
+#define BOOST_CSTDFLOAT_FLOAT128_FDIM fdimq
+#define BOOST_CSTDFLOAT_FLOAT128_NAN nanq
+//#define BOOST_CSTDFLOAT_FLOAT128_EXP2 exp2q
+#define BOOST_CSTDFLOAT_FLOAT128_LOG2 log2q
+#define BOOST_CSTDFLOAT_FLOAT128_LOG1P log1pq
+#define BOOST_CSTDFLOAT_FLOAT128_CBRT cbrtq
+#define BOOST_CSTDFLOAT_FLOAT128_HYPOT hypotq
+#define BOOST_CSTDFLOAT_FLOAT128_ERF erfq
+#define BOOST_CSTDFLOAT_FLOAT128_ERFC erfcq
+#define BOOST_CSTDFLOAT_FLOAT128_LLROUND llroundq
+#define BOOST_CSTDFLOAT_FLOAT128_LROUND lroundq
+#define BOOST_CSTDFLOAT_FLOAT128_ROUND roundq
+#define BOOST_CSTDFLOAT_FLOAT128_NEARBYINT nearbyintq
+#define BOOST_CSTDFLOAT_FLOAT128_LLRINT llrintq
+#define BOOST_CSTDFLOAT_FLOAT128_LRINT lrintq
+#define BOOST_CSTDFLOAT_FLOAT128_RINT rintq
+#define BOOST_CSTDFLOAT_FLOAT128_MODF modfq
+#define BOOST_CSTDFLOAT_FLOAT128_SCALBLN scalblnq
+#define BOOST_CSTDFLOAT_FLOAT128_SCALBN scalbnq
+#define BOOST_CSTDFLOAT_FLOAT128_ILOGB ilogbq
+#define BOOST_CSTDFLOAT_FLOAT128_LOGB logbq
+#define BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER nextafterq
+//#define BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD nexttowardq
+#define BOOST_CSTDFLOAT_FLOAT128_COPYSIGN copysignq
+#define BOOST_CSTDFLOAT_FLOAT128_SIGNBIT signbitq
+//#define BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY fpclassifyq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISFINITE isfiniteq
+#define BOOST_CSTDFLOAT_FLOAT128_ISINF isinfq
+#define BOOST_CSTDFLOAT_FLOAT128_ISNAN isnanq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISNORMAL isnormalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATER isgreaterq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL isgreaterequalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESS islessq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL islessequalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER islessgreaterq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED isunorderedq
+// end more functions
+#endif
+
+// Implement quadruple-precision <cmath> functions in the namespace
+// boost::math::cstdfloat::detail. Subsequently inject these into the
+// std namespace via *using* directive.
+
+// Begin with some forward function declarations. Also implement patches
+// for compilers that have broken float128 exponential functions.
+
+extern "C" int quadmath_snprintf(char*, std::size_t, const char*, ...) throw();
+
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LDEXP(boost::math::cstdfloat::detail::float_internal128_t, int) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FREXP(boost::math::cstdfloat::detail::float_internal128_t, int*) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FABS(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FLOOR(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CEIL(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TRUNC(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_POW(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG10(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SIN(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COS(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TAN(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASIN(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOS(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMOD(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN2(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LGAMMA(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+
+// begin more functions
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMAINDER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMQUO(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t, int*) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMA(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMAX(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMIN(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FDIM(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NAN(const char*) throw();
+//extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP2 (boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG2(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG1P(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CBRT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_HYPOT(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERF(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERFC(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLROUND(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LROUND(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ROUND(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLRINT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LRINT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_RINT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_MODF(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t*) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBLN(boost::math::cstdfloat::detail::float_internal128_t, long int) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBN(boost::math::cstdfloat::detail::float_internal128_t, int) throw();
+extern "C" int BOOST_CSTDFLOAT_FLOAT128_ILOGB(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOGB(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" int BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY (boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISFINITE (boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISINF(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISNAN(boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ISNORMAL (boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISGREATER (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISLESS (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+ // end more functions
+
+#if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS)
+
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(boost::math::cstdfloat::detail::float_internal128_t x) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(boost::math::cstdfloat::detail::float_internal128_t x) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(boost::math::cstdfloat::detail::float_internal128_t x) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(boost::math::cstdfloat::detail::float_internal128_t x) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) noexcept;
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) noexcept;
+
+#else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+
+// Forward declaration of the patched exponent function, exp(x).
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x);
+
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Compute exp(x) - 1 for x small.
+
+ // Use an order-12 Pade approximation of the exponential function.
+ // PadeApproximant[Exp[x] - 1, {x, 0, 12, 12}].
+
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+
+ float_type sum;
+
+ if (x > BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255))
+ {
+ sum = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x) - float_type(1);
+ }
+ else
+ {
+ const float_type x2 = (x * x);
+
+ const float_type top = ((((( float_type(BOOST_FLOAT128_C(2.4087176110456818621091195109360728010934088788572E-13)) * x2
+ + float_type(BOOST_FLOAT128_C(9.2735628025258751691201101171038802842096241836000E-10))) * x2
+ + float_type(BOOST_FLOAT128_C(9.0806726962333369656024118266681195742980640005812E-07))) * x2
+ + float_type(BOOST_FLOAT128_C(3.1055900621118012422360248447204968944099378881988E-04))) * x2
+ + float_type(BOOST_FLOAT128_C(3.6231884057971014492753623188405797101449275362319E-02))) * x2
+ + float_type(BOOST_FLOAT128_C(1.00000000000000000000000000000000000000000000000000000)))
+ ;
+
+ const float_type bot = (((((((((((( float_type(BOOST_FLOAT128_C(+7.7202487533515444298369215094104897470942592271063E-16)) * x
+ + float_type(BOOST_FLOAT128_C(-1.2043588055228409310545597554680364005467044394286E-13))) * x
+ + float_type(BOOST_FLOAT128_C(+9.2735628025258751691201101171038802842096241836000E-12))) * x
+ + float_type(BOOST_FLOAT128_C(-4.6367814012629375845600550585519401421048120918000E-10))) * x
+ + float_type(BOOST_FLOAT128_C(+1.6692413044546575304416198210786984511577323530480E-08))) * x
+ + float_type(BOOST_FLOAT128_C(-4.5403363481166684828012059133340597871490320002906E-07))) * x
+ + float_type(BOOST_FLOAT128_C(+9.5347063310450038138825324180015255530129672006102E-06))) * x
+ + float_type(BOOST_FLOAT128_C(-1.5527950310559006211180124223602484472049689440994E-04))) * x
+ + float_type(BOOST_FLOAT128_C(+1.9409937888198757763975155279503105590062111801242E-03))) * x
+ + float_type(BOOST_FLOAT128_C(-1.8115942028985507246376811594202898550724637681159E-02))) * x
+ + float_type(BOOST_FLOAT128_C(+1.1956521739130434782608695652173913043478260869565E-01))) * x
+ + float_type(BOOST_FLOAT128_C(-0.50000000000000000000000000000000000000000000000000000))) * x
+ + float_type(BOOST_FLOAT128_C(+1.00000000000000000000000000000000000000000000000000000)))
+ ;
+
+ sum = (x * top) / bot;
+ }
+
+ return sum;
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Patch the expq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+
+ // Scale the argument x to the range (-ln2 < x < ln2).
+ constexpr float_type one_over_ln2 = float_type(BOOST_FLOAT128_C(1.44269504088896340735992468100189213742664595415299));
+ const float_type x_over_ln2 = x * one_over_ln2;
+
+ int n;
+
+ if (x != x)
+ {
+ // The argument is NaN.
+ return std::numeric_limits<float_type>::quiet_NaN();
+ }
+ else if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) > BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255))
+ {
+ // The absolute value of the argument exceeds ln2.
+ n = static_cast<int>(::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x_over_ln2));
+ }
+ else if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255))
+ {
+ // The absolute value of the argument is less than ln2.
+ n = 0;
+ }
+ else
+ {
+ // The absolute value of the argument is exactly equal to ln2 (in the sense of floating-point equality).
+ return float_type(2);
+ }
+
+ // Check if the argument is very near an integer.
+ const float_type floor_of_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x);
+
+ if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x - floor_of_x) < float_type(BOOST_CSTDFLOAT_FLOAT128_EPS))
+ {
+ // Return e^n for arguments very near an integer.
+ return boost::math::cstdfloat::detail::pown(BOOST_FLOAT128_C(2.71828182845904523536028747135266249775724709369996), static_cast<std::int_fast32_t>(floor_of_x));
+ }
+
+ // Compute the scaled argument alpha.
+ const float_type alpha = x - (n * BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255));
+
+ // Compute the polynomial approximation of expm1(alpha) and add to it
+ // in order to obtain the scaled result.
+ const float_type scaled_result = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(alpha) + float_type(1);
+
+ // Rescale the result and return it.
+ return scaled_result * boost::math::cstdfloat::detail::pown(float_type(2), n);
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Patch the sinhq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+
+ // Here, we use the following:
+ // Set: ex = exp(x)
+ // Set: em1 = expm1(x)
+ // Then
+ // sinh(x) = (ex - 1/ex) / 2 ; for |x| >= 1
+ // sinh(x) = (2em1 + em1^2) / (2ex) ; for |x| < 1
+
+ const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
+
+ if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < float_type(+1))
+ {
+ const float_type em1 = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x);
+
+ return ((em1 * 2) + (em1 * em1)) / (ex * 2);
+ }
+ else
+ {
+ return (ex - (float_type(1) / ex)) / 2;
+ }
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Patch the coshq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
+ return (ex + (float_type(1) / ex)) / 2;
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Patch the tanhq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ const float_type ex_plus = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
+ const float_type ex_minus = (float_type(1) / ex_plus);
+ return (ex_plus - ex_minus) / (ex_plus + ex_minus);
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) noexcept
+{
+ // Patch the asinh() function since quadmath does not have it.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + ::BOOST_CSTDFLOAT_FLOAT128_SQRT((x * x) + float_type(1)));
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) noexcept
+{
+ // Patch the acosh() function since quadmath does not have it.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ const float_type zp(x + float_type(1));
+ const float_type zm(x - float_type(1));
+
+ return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + (zp * ::BOOST_CSTDFLOAT_FLOAT128_SQRT(zm / zp)));
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) noexcept
+{
+ // Patch the atanh() function since quadmath does not have it.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ return (::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) + x)
+ - ::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) - x)) / 2;
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) noexcept
+{
+ // Patch the tgammaq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+
+ if (x > float_type(0))
+ {
+ return ::BOOST_CSTDFLOAT_FLOAT128_EXP(::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x));
+ }
+ else if (x < float_type(0))
+ {
+ // For x < 0, compute tgamma(-x) and use the reflection formula.
+ const float_type positive_x = -x;
+ float_type gamma_value = ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(positive_x);
+ const float_type floor_of_positive_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(positive_x);
+
+ // Take the reflection checks (slightly adapted) from <boost/math/gamma.hpp>.
+ const bool floor_of_z_is_equal_to_z = (positive_x == ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(positive_x));
+
+ constexpr float_type my_pi = BOOST_FLOAT128_C(3.14159265358979323846264338327950288419716939937511);
+
+ if (floor_of_z_is_equal_to_z)
+ {
+ const bool is_odd = ((std::int32_t(floor_of_positive_x) % std::int32_t(2)) != std::int32_t(0));
+
+ return (is_odd ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
+ }
+
+ const float_type sinpx_value = x * ::BOOST_CSTDFLOAT_FLOAT128_SIN(my_pi * x);
+
+ gamma_value *= sinpx_value;
+
+ const bool result_is_too_large_to_represent = ((::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value) < float_type(1))
+ && (((std::numeric_limits<float_type>::max)() * ::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value)) < my_pi));
+
+ if (result_is_too_large_to_represent)
+ {
+ const bool is_odd = ((std::int32_t(floor_of_positive_x) % std::int32_t(2)) != std::int32_t(0));
+
+ return (is_odd ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
+ }
+
+ gamma_value = -my_pi / gamma_value;
+
+ if ((gamma_value > float_type(0)) || (gamma_value < float_type(0)))
+ {
+ return gamma_value;
+ }
+ else
+ {
+ // The value of gamma is too small to represent. Return 0.0 here.
+ return float_type(0);
+ }
+ }
+ else
+ {
+ // Gamma of zero is complex infinity. Return NaN here.
+ return std::numeric_limits<float_type>::quiet_NaN();
+ }
+}
+#endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+
+// Define the quadruple-precision <cmath> functions in the namespace boost::math::cstdfloat::detail.
+
+namespace boost {
+ namespace math {
+ namespace cstdfloat {
+ namespace detail {
+ inline boost::math::cstdfloat::detail::float_internal128_t ldexp(boost::math::cstdfloat::detail::float_internal128_t x, int n) { return ::BOOST_CSTDFLOAT_FLOAT128_LDEXP(x, n); }
+ inline boost::math::cstdfloat::detail::float_internal128_t frexp(boost::math::cstdfloat::detail::float_internal128_t x, int* pn) { return ::BOOST_CSTDFLOAT_FLOAT128_FREXP(x, pn); }
+ inline boost::math::cstdfloat::detail::float_internal128_t fabs(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t abs(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t floor(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t ceil(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CEIL(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t sqrt(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t trunc(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TRUNC(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t exp(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t expm1(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t pow(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, a); }
+ inline boost::math::cstdfloat::detail::float_internal128_t pow(boost::math::cstdfloat::detail::float_internal128_t x, int a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, boost::math::cstdfloat::detail::float_internal128_t(a)); }
+ inline boost::math::cstdfloat::detail::float_internal128_t log(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t log10(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG10(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t sin(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t cos(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COS(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t tan(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TAN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t asin(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASIN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t acos(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOS(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t atan(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t sinh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SINH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t cosh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COSH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t tanh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TANH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t asinh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASINH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t acosh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOSH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t atanh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATANH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t fmod(boost::math::cstdfloat::detail::float_internal128_t a, boost::math::cstdfloat::detail::float_internal128_t b) { return ::BOOST_CSTDFLOAT_FLOAT128_FMOD(a, b); }
+ inline boost::math::cstdfloat::detail::float_internal128_t atan2(boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN2(y, x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t lgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t tgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(x); }
+ // begin more functions
+ inline boost::math::cstdfloat::detail::float_internal128_t remainder(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_REMAINDER(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t remquo(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, int* z) { return ::BOOST_CSTDFLOAT_FLOAT128_REMQUO(x, y, z); }
+ inline boost::math::cstdfloat::detail::float_internal128_t fma(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t z) { return BOOST_CSTDFLOAT_FLOAT128_FMA(x, y, z); }
+
+ inline boost::math::cstdfloat::detail::float_internal128_t fmax(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ fmax(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ fmax(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t fmin(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ fmin(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ fmin(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); }
+
+ inline boost::math::cstdfloat::detail::float_internal128_t fdim(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FDIM(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t nanq(const char* x) { return ::BOOST_CSTDFLOAT_FLOAT128_NAN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t exp2(boost::math::cstdfloat::detail::float_internal128_t x)
+ {
+ return ::BOOST_CSTDFLOAT_FLOAT128_POW(boost::math::cstdfloat::detail::float_internal128_t(2), x);
+ }
+ inline boost::math::cstdfloat::detail::float_internal128_t log2(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG2(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t log1p(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG1P(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t cbrt(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CBRT(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t hypot(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t z) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x*x + y * y + z * z); }
+ inline boost::math::cstdfloat::detail::float_internal128_t hypot(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ hypot(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ hypot(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); }
+
+
+ inline boost::math::cstdfloat::detail::float_internal128_t erf(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERF(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t erfc(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERFC(x); }
+ inline long long int llround(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLROUND(x); }
+ inline long int lround(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LROUND(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t round(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ROUND(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t nearbyint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(x); }
+ inline long long int llrint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLRINT(x); }
+ inline long int lrint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LRINT(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t rint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_RINT(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t modf(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t* y) { return ::BOOST_CSTDFLOAT_FLOAT128_MODF(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t scalbln(boost::math::cstdfloat::detail::float_internal128_t x, long int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBLN(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t scalbn(boost::math::cstdfloat::detail::float_internal128_t x, int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBN(x, y); }
+ inline int ilogb(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ILOGB(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t logb(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOGB(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t nextafter(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t nexttoward(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return -(::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(-x, -y)); }
+ inline boost::math::cstdfloat::detail::float_internal128_t copysign BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(x, y); }
+ inline bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(x); }
+ inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x)
+ {
+ if (::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x))
+ return FP_NAN;
+ else if (::BOOST_CSTDFLOAT_FLOAT128_ISINF(x))
+ return FP_INFINITE;
+ else if (x == BOOST_FLOAT128_C(0.0))
+ return FP_ZERO;
+
+ if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < BOOST_CSTDFLOAT_FLOAT128_MIN)
+ return FP_SUBNORMAL;
+ else
+ return FP_NORMAL;
+ }
+ inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x)
+ {
+ return !::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x) && !::BOOST_CSTDFLOAT_FLOAT128_ISINF(x);
+ }
+ inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISINF(x); }
+ inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x); }
+ inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return boost::math::cstdfloat::detail::fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(x) == FP_NORMAL; }
+ inline bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return x > y;
+ }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isgreater BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+ inline bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return x >= y;
+ }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+ inline bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return x < y;
+ }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isless BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isless BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isless BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isless BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+
+ inline bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return x <= y;
+ }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return islessequal BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+
+ inline bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return (x < y) || (x > y);
+ }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+
+ inline bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x) || ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename std::enable_if<
+ std::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !std::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isunordered BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+
+ // end more functions
+ }
+ }
+ }
+} // boost::math::cstdfloat::detail
+
+// We will now inject the quadruple-precision <cmath> functions
+// into the std namespace. This is done via *using* directive.
+namespace std
+{
+ using boost::math::cstdfloat::detail::ldexp;
+ using boost::math::cstdfloat::detail::frexp;
+ using boost::math::cstdfloat::detail::fabs;
+
+#if !(defined(_GLIBCXX_USE_FLOAT128) && defined(__GNUC__) && (__GNUC__ >= 7))
+#if (defined(__clang__) && !(!defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128))) || (__GNUC__ <= 6 && !defined(__clang__))
+ // workaround for clang using libstdc++ and old GCC
+ using boost::math::cstdfloat::detail::abs;
+#endif
+#endif
+
+ using boost::math::cstdfloat::detail::floor;
+ using boost::math::cstdfloat::detail::ceil;
+ using boost::math::cstdfloat::detail::sqrt;
+ using boost::math::cstdfloat::detail::trunc;
+ using boost::math::cstdfloat::detail::exp;
+ using boost::math::cstdfloat::detail::expm1;
+ using boost::math::cstdfloat::detail::pow;
+ using boost::math::cstdfloat::detail::log;
+ using boost::math::cstdfloat::detail::log10;
+ using boost::math::cstdfloat::detail::sin;
+ using boost::math::cstdfloat::detail::cos;
+ using boost::math::cstdfloat::detail::tan;
+ using boost::math::cstdfloat::detail::asin;
+ using boost::math::cstdfloat::detail::acos;
+ using boost::math::cstdfloat::detail::atan;
+ using boost::math::cstdfloat::detail::sinh;
+ using boost::math::cstdfloat::detail::cosh;
+ using boost::math::cstdfloat::detail::tanh;
+ using boost::math::cstdfloat::detail::asinh;
+ using boost::math::cstdfloat::detail::acosh;
+ using boost::math::cstdfloat::detail::atanh;
+ using boost::math::cstdfloat::detail::fmod;
+ using boost::math::cstdfloat::detail::atan2;
+ using boost::math::cstdfloat::detail::lgamma;
+ using boost::math::cstdfloat::detail::tgamma;
+
+ // begin more functions
+ using boost::math::cstdfloat::detail::remainder;
+ using boost::math::cstdfloat::detail::remquo;
+ using boost::math::cstdfloat::detail::fma;
+ using boost::math::cstdfloat::detail::fmax;
+ using boost::math::cstdfloat::detail::fmin;
+ using boost::math::cstdfloat::detail::fdim;
+ using boost::math::cstdfloat::detail::nanq;
+ using boost::math::cstdfloat::detail::exp2;
+ using boost::math::cstdfloat::detail::log2;
+ using boost::math::cstdfloat::detail::log1p;
+ using boost::math::cstdfloat::detail::cbrt;
+ using boost::math::cstdfloat::detail::hypot;
+ using boost::math::cstdfloat::detail::erf;
+ using boost::math::cstdfloat::detail::erfc;
+ using boost::math::cstdfloat::detail::llround;
+ using boost::math::cstdfloat::detail::lround;
+ using boost::math::cstdfloat::detail::round;
+ using boost::math::cstdfloat::detail::nearbyint;
+ using boost::math::cstdfloat::detail::llrint;
+ using boost::math::cstdfloat::detail::lrint;
+ using boost::math::cstdfloat::detail::rint;
+ using boost::math::cstdfloat::detail::modf;
+ using boost::math::cstdfloat::detail::scalbln;
+ using boost::math::cstdfloat::detail::scalbn;
+ using boost::math::cstdfloat::detail::ilogb;
+ using boost::math::cstdfloat::detail::logb;
+ using boost::math::cstdfloat::detail::nextafter;
+ using boost::math::cstdfloat::detail::nexttoward;
+ using boost::math::cstdfloat::detail::copysign;
+ using boost::math::cstdfloat::detail::signbit;
+ using boost::math::cstdfloat::detail::fpclassify;
+ using boost::math::cstdfloat::detail::isfinite;
+ using boost::math::cstdfloat::detail::isinf;
+ using boost::math::cstdfloat::detail::isnan;
+ using boost::math::cstdfloat::detail::isnormal;
+ using boost::math::cstdfloat::detail::isgreater;
+ using boost::math::cstdfloat::detail::isgreaterequal;
+ using boost::math::cstdfloat::detail::isless;
+ using boost::math::cstdfloat::detail::islessequal;
+ using boost::math::cstdfloat::detail::islessgreater;
+ using boost::math::cstdfloat::detail::isunordered;
+ // end more functions
+
+ //
+ // Very basic iostream operator:
+ //
+ inline std::ostream& operator << (std::ostream& os, __float128 m_value)
+ {
+ std::streamsize digits = os.precision();
+ std::ios_base::fmtflags f = os.flags();
+ std::string s;
+
+ char buf[100];
+ std::unique_ptr<char[]> buf2;
+ std::string format = "%";
+ if (f & std::ios_base::showpos)
+ format += "+";
+ if (f & std::ios_base::showpoint)
+ format += "#";
+ format += ".*";
+ if (digits == 0)
+ digits = 36;
+ format += "Q";
+ if (f & std::ios_base::scientific)
+ format += "e";
+ else if (f & std::ios_base::fixed)
+ format += "f";
+ else
+ format += "g";
+
+ int v = quadmath_snprintf(buf, 100, format.c_str(), digits, m_value);
+
+ if ((v < 0) || (v >= 99))
+ {
+ int v_max = v;
+ buf2.reset(new char[v + 3]);
+ v = quadmath_snprintf(&buf2[0], v_max + 3, format.c_str(), digits, m_value);
+ if (v >= v_max + 3)
+ {
+ BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of float128_type failed."));
+ }
+ s = &buf2[0];
+ }
+ else
+ s = buf;
+ std::streamsize ss = os.width();
+ if (ss > static_cast<std::streamsize>(s.size()))
+ {
+ char fill = os.fill();
+ if ((os.flags() & std::ios_base::left) == std::ios_base::left)
+ s.append(static_cast<std::string::size_type>(ss - s.size()), fill);
+ else
+ s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - s.size()), fill);
+ }
+
+ return os << s;
+ }
+
+
+} // namespace std
+
+// We will now remove the preprocessor symbols representing quadruple-precision <cmath>
+// functions from the preprocessor.
+
+#undef BOOST_CSTDFLOAT_FLOAT128_LDEXP
+#undef BOOST_CSTDFLOAT_FLOAT128_FREXP
+#undef BOOST_CSTDFLOAT_FLOAT128_FABS
+#undef BOOST_CSTDFLOAT_FLOAT128_FLOOR
+#undef BOOST_CSTDFLOAT_FLOAT128_CEIL
+#undef BOOST_CSTDFLOAT_FLOAT128_SQRT
+#undef BOOST_CSTDFLOAT_FLOAT128_TRUNC
+#undef BOOST_CSTDFLOAT_FLOAT128_EXP
+#undef BOOST_CSTDFLOAT_FLOAT128_EXPM1
+#undef BOOST_CSTDFLOAT_FLOAT128_POW
+#undef BOOST_CSTDFLOAT_FLOAT128_LOG
+#undef BOOST_CSTDFLOAT_FLOAT128_LOG10
+#undef BOOST_CSTDFLOAT_FLOAT128_SIN
+#undef BOOST_CSTDFLOAT_FLOAT128_COS
+#undef BOOST_CSTDFLOAT_FLOAT128_TAN
+#undef BOOST_CSTDFLOAT_FLOAT128_ASIN
+#undef BOOST_CSTDFLOAT_FLOAT128_ACOS
+#undef BOOST_CSTDFLOAT_FLOAT128_ATAN
+#undef BOOST_CSTDFLOAT_FLOAT128_SINH
+#undef BOOST_CSTDFLOAT_FLOAT128_COSH
+#undef BOOST_CSTDFLOAT_FLOAT128_TANH
+#undef BOOST_CSTDFLOAT_FLOAT128_ASINH
+#undef BOOST_CSTDFLOAT_FLOAT128_ACOSH
+#undef BOOST_CSTDFLOAT_FLOAT128_ATANH
+#undef BOOST_CSTDFLOAT_FLOAT128_FMOD
+#undef BOOST_CSTDFLOAT_FLOAT128_ATAN2
+#undef BOOST_CSTDFLOAT_FLOAT128_LGAMMA
+#undef BOOST_CSTDFLOAT_FLOAT128_TGAMMA
+
+// begin more functions
+#undef BOOST_CSTDFLOAT_FLOAT128_REMAINDER
+#undef BOOST_CSTDFLOAT_FLOAT128_REMQUO
+#undef BOOST_CSTDFLOAT_FLOAT128_FMA
+#undef BOOST_CSTDFLOAT_FLOAT128_FMAX
+#undef BOOST_CSTDFLOAT_FLOAT128_FMIN
+#undef BOOST_CSTDFLOAT_FLOAT128_FDIM
+#undef BOOST_CSTDFLOAT_FLOAT128_NAN
+#undef BOOST_CSTDFLOAT_FLOAT128_EXP2
+#undef BOOST_CSTDFLOAT_FLOAT128_LOG2
+#undef BOOST_CSTDFLOAT_FLOAT128_LOG1P
+#undef BOOST_CSTDFLOAT_FLOAT128_CBRT
+#undef BOOST_CSTDFLOAT_FLOAT128_HYPOT
+#undef BOOST_CSTDFLOAT_FLOAT128_ERF
+#undef BOOST_CSTDFLOAT_FLOAT128_ERFC
+#undef BOOST_CSTDFLOAT_FLOAT128_LLROUND
+#undef BOOST_CSTDFLOAT_FLOAT128_LROUND
+#undef BOOST_CSTDFLOAT_FLOAT128_ROUND
+#undef BOOST_CSTDFLOAT_FLOAT128_NEARBYINT
+#undef BOOST_CSTDFLOAT_FLOAT128_LLRINT
+#undef BOOST_CSTDFLOAT_FLOAT128_LRINT
+#undef BOOST_CSTDFLOAT_FLOAT128_RINT
+#undef BOOST_CSTDFLOAT_FLOAT128_MODF
+#undef BOOST_CSTDFLOAT_FLOAT128_SCALBLN
+#undef BOOST_CSTDFLOAT_FLOAT128_SCALBN
+#undef BOOST_CSTDFLOAT_FLOAT128_ILOGB
+#undef BOOST_CSTDFLOAT_FLOAT128_LOGB
+#undef BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER
+#undef BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD
+#undef BOOST_CSTDFLOAT_FLOAT128_COPYSIGN
+#undef BOOST_CSTDFLOAT_FLOAT128_SIGNBIT
+#undef BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY
+#undef BOOST_CSTDFLOAT_FLOAT128_ISFINITE
+#undef BOOST_CSTDFLOAT_FLOAT128_ISINF
+#undef BOOST_CSTDFLOAT_FLOAT128_ISNAN
+#undef BOOST_CSTDFLOAT_FLOAT128_ISNORMAL
+#undef BOOST_CSTDFLOAT_FLOAT128_ISGREATER
+#undef BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL
+#undef BOOST_CSTDFLOAT_FLOAT128_ISLESS
+#undef BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL
+#undef BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER
+#undef BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED
+// end more functions
+
+#endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
+
+#endif // BOOST_MATH_CSTDFLOAT_CMATH_2014_02_15_HPP_
+
diff --git a/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_complex.hpp b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_complex.hpp
new file mode 100644
index 0000000000..f79ff6d423
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_complex.hpp
@@ -0,0 +1,38 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2014.
+// Copyright John Maddock 2014.
+// Copyright Paul Bristow 2014.
+// 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)
+//
+
+// Implement quadruple-precision (and extended) support for <complex>.
+
+#ifndef BOOST_MATH_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
+ #define BOOST_MATH_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
+
+ #include <boost/math/cstdfloat/cstdfloat_types.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_limits.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_iostream.hpp>
+
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS defined.
+ #endif
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
+ #endif
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM defined.
+ #endif
+
+ #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+
+ #define BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE boost::math::cstdfloat::detail::float_internal128_t
+ #include <boost/math/cstdfloat/cstdfloat_complex_std.hpp>
+ #undef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE
+
+ #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
+
+#endif // BOOST_MATH_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
diff --git a/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp
new file mode 100644
index 0000000000..a4007ee186
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp
@@ -0,0 +1,813 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2014.
+// Copyright John Maddock 2014.
+// Copyright Paul Bristow 2014.
+// 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)
+//
+
+// Implement a specialization of std::complex<> for *anything* that
+// is defined as BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE.
+
+#ifndef BOOST_MATH_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_
+ #define BOOST_MATH_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_
+
+ #if defined(__GNUC__)
+ #pragma GCC system_header
+ #endif
+
+ #include <complex>
+ #include <boost/math/constants/constants.hpp>
+ #include <boost/math/tools/cxx03_warn.hpp>
+
+ namespace std
+ {
+ // Forward declarations.
+ template<class float_type>
+ class complex;
+
+ template<>
+ class complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>;
+
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> conj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> proj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&,
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& = 0);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sqrt (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sin (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cos (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tan (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asin (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acos (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atan (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> exp (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log10(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&,
+ int);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&,
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&,
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&,
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sinh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cosh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tanh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ template<class char_type, class traits_type>
+ inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>&, const std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ template<class char_type, class traits_type>
+ inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>&, std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ // Template specialization of the complex class.
+ template<>
+ class complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ {
+ public:
+ typedef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE value_type;
+
+ complex(const complex<float>&);
+ complex(const complex<double>&);
+ complex(const complex<long double>&);
+
+ #if defined(BOOST_NO_CXX11_CONSTEXPR)
+ complex(const value_type& r = value_type(),
+ const value_type& i = value_type()) : re(r),
+ im(i) { }
+
+ template<typename X>
+ explicit complex(const complex<X>& x) : re(x.real()),
+ im(x.imag()) { }
+
+ const value_type& real() const { return re; }
+ const value_type& imag() const { return im; }
+
+ value_type& real() { return re; }
+ value_type& imag() { return im; }
+ #else
+ constexpr complex(const value_type& r = value_type(),
+ const value_type& i = value_type()) : re(r),
+ im(i) { }
+
+ template<typename X>
+ explicit constexpr complex(const complex<X>& x) : re(x.real()),
+ im(x.imag()) { }
+
+ value_type real() const { return re; }
+ value_type imag() const { return im; }
+ #endif
+
+ void real(value_type r) { re = r; }
+ void imag(value_type i) { im = i; }
+
+ complex<value_type>& operator=(const value_type& v)
+ {
+ re = v;
+ im = value_type(0);
+ return *this;
+ }
+
+ complex<value_type>& operator+=(const value_type& v)
+ {
+ re += v;
+ return *this;
+ }
+
+ complex<value_type>& operator-=(const value_type& v)
+ {
+ re -= v;
+ return *this;
+ }
+
+ complex<value_type>& operator*=(const value_type& v)
+ {
+ re *= v;
+ im *= v;
+ return *this;
+ }
+
+ complex<value_type>& operator/=(const value_type& v)
+ {
+ re /= v;
+ im /= v;
+ return *this;
+ }
+
+ template<typename X>
+ complex<value_type>& operator=(const complex<X>& x)
+ {
+ re = x.real();
+ im = x.imag();
+ return *this;
+ }
+
+ template<typename X>
+ complex<value_type>& operator+=(const complex<X>& x)
+ {
+ re += x.real();
+ im += x.imag();
+ return *this;
+ }
+
+ template<typename X>
+ complex<value_type>& operator-=(const complex<X>& x)
+ {
+ re -= x.real();
+ im -= x.imag();
+ return *this;
+ }
+
+ template<typename X>
+ complex<value_type>& operator*=(const complex<X>& x)
+ {
+ const value_type tmp_real = (re * x.real()) - (im * x.imag());
+ im = (re * x.imag()) + (im * x.real());
+ re = tmp_real;
+ return *this;
+ }
+
+ template<typename X>
+ complex<value_type>& operator/=(const complex<X>& x)
+ {
+ const value_type tmp_real = (re * x.real()) + (im * x.imag());
+ const value_type the_norm = std::norm(x);
+ im = ((im * x.real()) - (re * x.imag())) / the_norm;
+ re = tmp_real / the_norm;
+ return *this;
+ }
+
+ private:
+ value_type re;
+ value_type im;
+ };
+
+ // Constructors from built-in complex representation of floating-point types.
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<float>& f) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.imag())) { }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<double>& d) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.imag())) { }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<long double>& ld) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.imag())) { }
+ } // namespace std
+
+ namespace boost { namespace math { namespace cstdfloat { namespace detail {
+ template<class float_type> inline std::complex<float_type> multiply_by_i(const std::complex<float_type>& x)
+ {
+ // Multiply x (in C) by I (the imaginary component), and return the result.
+ return std::complex<float_type>(-x.imag(), x.real());
+ }
+ } } } } // boost::math::cstdfloat::detail
+
+ namespace std
+ {
+ // ISO/IEC 14882:2011, Section 26.4.7, specific values.
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return x.real(); }
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return x.imag(); }
+
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { using std::sqrt; return sqrt ((real(x) * real(x)) + (imag(x) * imag(x))); }
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { using std::atan2; return atan2(x.imag(), x.real()); }
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return (real(x) * real(x)) + (imag(x) * imag(x)); }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> conj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(x.real(), -x.imag()); }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> proj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE m = (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)();
+ if ( (x.real() > m)
+ || (x.real() < -m)
+ || (x.imag() > m)
+ || (x.imag() < -m))
+ {
+ // We have an infinity, return a normalized infinity, respecting the sign of the imaginary part:
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(), x.imag() < 0 ? -0 : 0);
+ }
+ return x;
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& rho,
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& theta)
+ {
+ using std::sin;
+ using std::cos;
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(rho * cos(theta), rho * sin(theta));
+ }
+
+ // Global add, sub, mul, div.
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() + v.real(), u.imag() + v.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() - v.real(), u.imag() - v.imag()); }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v)
+ {
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>((u.real() * v.real()) - (u.imag() * v.imag()),
+ (u.real() * v.imag()) + (u.imag() * v.real()));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v)
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE the_norm = std::norm(v);
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(((u.real() * v.real()) + (u.imag() * v.imag())) / the_norm,
+ ((u.imag() * v.real()) - (u.real() * v.imag())) / the_norm);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() + v, u.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() - v, u.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() * v, u.imag() * v); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() / v, u.imag() / v); }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u + v.real(), v.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u - v.real(), -v.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u * v.real(), u * v.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE v_norm = norm(v); return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>((u * v.real()) / v_norm, (-u * v.imag()) / v_norm); }
+
+ // Unary plus / minus.
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u) { return u; }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(-u.real(), -u.imag()); }
+
+ // Equality and inequality.
+ inline bool operator==(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x.real() == y.real()) && (x.imag() == y.imag())); }
+ inline bool operator==(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() == y) && (x.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); }
+ inline bool operator==(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x == y.real()) && (y.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); }
+ inline bool operator!=(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x.real() != y.real()) || (x.imag() != y.imag())); }
+ inline bool operator!=(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() != y) || (x.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); }
+ inline bool operator!=(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x != y.real()) || (y.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); }
+
+ // ISO/IEC 14882:2011, Section 26.4.8, transcendentals.
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sqrt(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::fabs;
+ using std::sqrt;
+
+ // Compute sqrt(x) for x in C:
+ // sqrt(x) = (s , xi / 2s) : for xr > 0,
+ // (|xi| / 2s, +-s) : for xr < 0,
+ // (sqrt(xi), sqrt(xi) : for xr = 0,
+ // where s = sqrt{ [ |xr| + sqrt(xr^2 + xi^2) ] / 2 },
+ // and the +- sign is the same as the sign of xi.
+
+ if(x.real() > 0)
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2);
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(s, x.imag() / (s * 2));
+ }
+ else if(x.real() < 0)
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2);
+
+ const bool imag_is_neg = (x.imag() < 0);
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(fabs(x.imag()) / (s * 2), (imag_is_neg ? -s : s));
+ }
+ else
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sqrt_xi_half = sqrt(x.imag() / 2);
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sqrt_xi_half, sqrt_xi_half);
+ }
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sin(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::sin;
+ using std::cos;
+ using std::exp;
+
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2;
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sin_x * cosh_y, cos_x * sinh_y);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cos(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::sin;
+ using std::cos;
+ using std::exp;
+
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2;
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_x * cosh_y, -(sin_x * sinh_y));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tan(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::sin;
+ using std::cos;
+ using std::exp;
+
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2;
+
+ return ( complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sin_x * cosh_y, cos_x * sinh_y)
+ / complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_x * cosh_y, -sin_x * sinh_y));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asin(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ return -boost::math::cstdfloat::detail::multiply_by_i(std::log(boost::math::cstdfloat::detail::multiply_by_i(x) + std::sqrt(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - (x * x))));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acos(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ return boost::math::constants::half_pi<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>() - std::asin(x);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atan(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> izz = boost::math::cstdfloat::detail::multiply_by_i(x);
+
+ return boost::math::cstdfloat::detail::multiply_by_i(std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - izz) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + izz)) / 2;
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> exp(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::exp;
+
+ return std::polar(exp(x.real()), x.imag());
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::atan2;
+ using std::log;
+
+ const bool re_isneg = (x.real() < 0);
+ const bool re_isnan = (x.real() != x.real());
+ const bool re_isinf = ((!re_isneg) ? bool(+x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ : bool(-x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
+
+ const bool im_isneg = (x.imag() < 0);
+ const bool im_isnan = (x.imag() != x.imag());
+ const bool im_isinf = ((!im_isneg) ? bool(+x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ : bool(-x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
+
+ if(re_isnan || im_isnan) { return x; }
+
+ if(re_isinf || im_isinf)
+ {
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(),
+ BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0.0));
+ }
+
+ const bool re_iszero = ((re_isneg || (x.real() > 0)) == false);
+
+ if(re_iszero)
+ {
+ const bool im_iszero = ((im_isneg || (x.imag() > 0)) == false);
+
+ if(im_iszero)
+ {
+ return std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ (
+ -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(),
+ BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0.0)
+ );
+ }
+ else
+ {
+ if(im_isneg == false)
+ {
+ return std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ (
+ log(x.imag()),
+ boost::math::constants::half_pi<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>()
+ );
+ }
+ else
+ {
+ return std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ (
+ log(-x.imag()),
+ -boost::math::constants::half_pi<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>()
+ );
+ }
+ }
+ }
+ else
+ {
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(log(std::norm(x)) / 2, atan2(x.imag(), x.real()));
+ }
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log10(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ return std::log(x) / boost::math::constants::ln_ten<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>();
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x,
+ int p)
+ {
+ const bool re_isneg = (x.real() < 0);
+ const bool re_isnan = (x.real() != x.real());
+ const bool re_isinf = ((!re_isneg) ? bool(+x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ : bool(-x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
+
+ const bool im_isneg = (x.imag() < 0);
+ const bool im_isnan = (x.imag() != x.imag());
+ const bool im_isinf = ((!im_isneg) ? bool(+x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ : bool(-x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
+
+ if(re_isnan || im_isnan) { return x; }
+
+ if(re_isinf || im_isinf)
+ {
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(),
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN());
+ }
+
+ if(p < 0)
+ {
+ if(std::abs(x) < (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::min)())
+ {
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(),
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity());
+ }
+ else
+ {
+ return BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / std::pow(x, -p);
+ }
+ }
+
+ if(p == 0)
+ {
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1));
+ }
+ else
+ {
+ if(p == 1) { return x; }
+
+ if(std::abs(x) > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE re = (re_isneg ? -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()
+ : +std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity());
+
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE im = (im_isneg ? -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()
+ : +std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity());
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(re, im);
+ }
+
+ if (p == 2) { return (x * x); }
+ else if(p == 3) { return ((x * x) * x); }
+ else if(p == 4) { const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> x2 = (x * x); return (x2 * x2); }
+ else
+ {
+ // The variable xn stores the binary powers of x.
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> result(((p % 2) != 0) ? x : complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)));
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> xn (x);
+
+ int p2 = p;
+
+ while((p2 /= 2) != 0)
+ {
+ // Square xn for each binary power.
+ xn *= xn;
+
+ const bool has_binary_power = ((p2 % 2) != 0);
+
+ if(has_binary_power)
+ {
+ // Multiply the result with each binary power contained in the exponent.
+ result *= xn;
+ }
+ }
+
+ return result;
+ }
+ }
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x,
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& a)
+ {
+ const bool x_im_isneg = (x.imag() < 0);
+ const bool x_im_iszero = ((x_im_isneg || (x.imag() > 0)) == false);
+
+ if(x_im_iszero)
+ {
+ using std::pow;
+
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE pxa = pow(x.real(), a);
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(pxa, BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0));
+ }
+ else
+ {
+ return std::exp(a * std::log(x));
+ }
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x,
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& a)
+ {
+ const bool x_im_isneg = (x.imag() < 0);
+ const bool x_im_iszero = ((x_im_isneg || (x.imag() > 0)) == false);
+
+ if(x_im_iszero)
+ {
+ using std::pow;
+
+ return pow(x.real(), a);
+ }
+ else
+ {
+ return std::exp(a * std::log(x));
+ }
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x,
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& a)
+ {
+ const bool x_isneg = (x < 0);
+ const bool x_isnan = (x != x);
+ const bool x_isinf = ((!x_isneg) ? bool(+x > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ : bool(-x > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
+
+ const bool a_re_isneg = (a.real() < 0);
+ const bool a_re_isnan = (a.real() != a.real());
+ const bool a_re_isinf = ((!a_re_isneg) ? bool(+a.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ : bool(-a.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
+
+ const bool a_im_isneg = (a.imag() < 0);
+ const bool a_im_isnan = (a.imag() != a.imag());
+ const bool a_im_isinf = ((!a_im_isneg) ? bool(+a.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ : bool(-a.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
+
+ const bool args_is_nan = (x_isnan || a_re_isnan || a_im_isnan);
+ const bool a_is_finite = (!(a_re_isnan || a_re_isinf || a_im_isnan || a_im_isinf));
+
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> result;
+
+ if(args_is_nan)
+ {
+ result =
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ (
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(),
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN()
+ );
+ }
+ else if(x_isinf)
+ {
+ if(a_is_finite)
+ {
+ result =
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ (
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(),
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()
+ );
+ }
+ else
+ {
+ result =
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ (
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(),
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN()
+ );
+ }
+ }
+ else if(x > 0)
+ {
+ result = std::exp(a * std::log(x));
+ }
+ else if(x < 0)
+ {
+ using std::acos;
+ using std::log;
+
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ cpx_lg_x
+ (
+ log(-x),
+ acos(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(-1))
+ );
+
+ result = std::exp(a * cpx_lg_x);
+ }
+ else
+ {
+ if(a_is_finite)
+ {
+ result =
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ (
+ BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0),
+ BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0)
+ );
+ }
+ else
+ {
+ result =
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ (
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(),
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN()
+ );
+ }
+ }
+
+ return result;
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::sin;
+ using std::cos;
+ using std::exp;
+
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2;
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_y * sinh_x, cosh_x * sin_y);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::sin;
+ using std::cos;
+ using std::exp;
+
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real());
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2;
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2;
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_y * cosh_x, sin_y * sinh_x);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> ex_plus = std::exp(x);
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> ex_minus = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / ex_plus;
+
+ return (ex_plus - ex_minus) / (ex_plus + ex_minus);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ return std::log(x + std::sqrt((x * x) + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE my_one(1);
+
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> zp(x.real() + my_one, x.imag());
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> zm(x.real() - my_one, x.imag());
+
+ return std::log(x + (zp * std::sqrt(zm / zp)));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ return (std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + x) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - x)) / 2.0;
+ }
+
+ template<class char_type, class traits_type>
+ inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ std::basic_ostringstream<char_type, traits_type> ostr;
+
+ ostr.flags(os.flags());
+ ostr.imbue(os.getloc());
+ ostr.precision(os.precision());
+
+ ostr << char_type('(')
+ << x.real()
+ << char_type(',')
+ << x.imag()
+ << char_type(')');
+
+ return (os << ostr.str());
+ }
+
+ template<class char_type, class traits_type>
+ inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE rx;
+ BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE ix;
+
+ char_type the_char;
+
+ static_cast<void>(is >> the_char);
+
+ if(the_char == static_cast<char_type>('('))
+ {
+ static_cast<void>(is >> rx >> the_char);
+
+ if(the_char == static_cast<char_type>(','))
+ {
+ static_cast<void>(is >> ix >> the_char);
+
+ if(the_char == static_cast<char_type>(')'))
+ {
+ x = complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(rx, ix);
+ }
+ else
+ {
+ is.setstate(ios_base::failbit);
+ }
+ }
+ else if(the_char == static_cast<char_type>(')'))
+ {
+ x = rx;
+ }
+ else
+ {
+ is.setstate(ios_base::failbit);
+ }
+ }
+ else
+ {
+ static_cast<void>(is.putback(the_char));
+
+ static_cast<void>(is >> rx);
+
+ x = rx;
+ }
+
+ return is;
+ }
+ } // namespace std
+
+#endif // BOOST_MATH_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_
diff --git a/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_iostream.hpp b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_iostream.hpp
new file mode 100644
index 0000000000..4d46c38829
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_iostream.hpp
@@ -0,0 +1,774 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2014.
+// Copyright John Maddock 2014.
+// Copyright Paul Bristow 2014.
+// 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)
+//
+
+// Implement quadruple-precision I/O stream operations.
+
+#ifndef BOOST_MATH_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
+ #define BOOST_MATH_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
+
+ #include <boost/math/cstdfloat/cstdfloat_types.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_limits.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
+
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_iostream.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
+ #endif
+
+ #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+
+ #include <cstddef>
+ #include <istream>
+ #include <ostream>
+ #include <sstream>
+ #include <stdexcept>
+ #include <string>
+ #include <boost/math/tools/assert.hpp>
+ #include <boost/math/tools/throw_exception.hpp>
+
+// #if (0)
+ #if defined(__GNUC__)
+
+ // Forward declarations of quadruple-precision string functions.
+ extern "C" int quadmath_snprintf(char *str, size_t size, const char *format, ...) noexcept;
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t strtoflt128(const char*, char **) noexcept;
+
+ namespace std
+ {
+ template<typename char_type, class traits_type>
+ inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const boost::math::cstdfloat::detail::float_internal128_t& x)
+ {
+ std::basic_ostringstream<char_type, traits_type> ostr;
+ ostr.flags(os.flags());
+ ostr.imbue(os.getloc());
+ ostr.precision(os.precision());
+
+ char my_buffer[64U];
+
+ const int my_prec = static_cast<int>(os.precision());
+ const int my_digits = ((my_prec == 0) ? 36 : my_prec);
+
+ const std::ios_base::fmtflags my_flags = os.flags();
+
+ char my_format_string[8U];
+
+ std::size_t my_format_string_index = 0U;
+
+ my_format_string[my_format_string_index] = '%';
+ ++my_format_string_index;
+
+ if(my_flags & std::ios_base::showpos) { my_format_string[my_format_string_index] = '+'; ++my_format_string_index; }
+ if(my_flags & std::ios_base::showpoint) { my_format_string[my_format_string_index] = '#'; ++my_format_string_index; }
+
+ my_format_string[my_format_string_index + 0U] = '.';
+ my_format_string[my_format_string_index + 1U] = '*';
+ my_format_string[my_format_string_index + 2U] = 'Q';
+
+ my_format_string_index += 3U;
+
+ char the_notation_char;
+
+ if (my_flags & std::ios_base::scientific) { the_notation_char = 'e'; }
+ else if(my_flags & std::ios_base::fixed) { the_notation_char = 'f'; }
+ else { the_notation_char = 'g'; }
+
+ my_format_string[my_format_string_index + 0U] = the_notation_char;
+ my_format_string[my_format_string_index + 1U] = 0;
+
+ const int v = ::quadmath_snprintf(my_buffer,
+ static_cast<int>(sizeof(my_buffer)),
+ my_format_string,
+ my_digits,
+ x);
+
+ if(v < 0) { BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed internally in quadmath_snprintf().")); }
+
+ if(v >= static_cast<int>(sizeof(my_buffer) - 1U))
+ {
+ // Evidently there is a really long floating-point string here,
+ // such as a small decimal representation in non-scientific notation.
+ // So we have to use dynamic memory allocation for the output
+ // string buffer.
+
+ char* my_buffer2 = static_cast<char*>(0U);
+
+#ifndef BOOST_NO_EXCEPTIONS
+ try
+ {
+#endif
+ my_buffer2 = new char[v + 3];
+#ifndef BOOST_NO_EXCEPTIONS
+ }
+ catch(const std::bad_alloc&)
+ {
+ BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed while allocating memory."));
+ }
+#endif
+ const int v2 = ::quadmath_snprintf(my_buffer2,
+ v + 3,
+ my_format_string,
+ my_digits,
+ x);
+
+ if(v2 >= v + 3)
+ {
+ BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed."));
+ }
+
+ static_cast<void>(ostr << my_buffer2);
+
+ delete [] my_buffer2;
+ }
+ else
+ {
+ static_cast<void>(ostr << my_buffer);
+ }
+
+ return (os << ostr.str());
+ }
+
+ template<typename char_type, class traits_type>
+ inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, boost::math::cstdfloat::detail::float_internal128_t& x)
+ {
+ std::string str;
+
+ static_cast<void>(is >> str);
+
+ char* p_end;
+
+ x = strtoflt128(str.c_str(), &p_end);
+
+ if(static_cast<std::ptrdiff_t>(p_end - str.c_str()) != static_cast<std::ptrdiff_t>(str.length()))
+ {
+ for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it)
+ {
+ static_cast<void>(is.putback(*it));
+ }
+
+ is.setstate(ios_base::failbit);
+
+ BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
+ }
+
+ return is;
+ }
+ }
+
+// #elif defined(__GNUC__)
+ #elif defined(__INTEL_COMPILER)
+
+ // The section for I/O stream support for the ICC compiler is particularly
+ // long, because these functions must be painstakingly synthesized from
+ // manually-written routines (ICC does not support I/O stream operations
+ // for its _Quad type).
+
+ // The following string-extraction routines are based on the methodology
+ // used in Boost.Multiprecision by John Maddock and Christopher Kormanyos.
+ // This methodology has been slightly modified here for boost::float128_t.
+
+ #include <cstring>
+ #include <cctype>
+
+ namespace boost { namespace math { namespace cstdfloat { namespace detail {
+
+ template<class string_type>
+ void format_float_string(string_type& str,
+ int my_exp,
+ int digits,
+ const std::ios_base::fmtflags f,
+ const bool iszero)
+ {
+ typedef typename string_type::size_type size_type;
+
+ const bool scientific = ((f & std::ios_base::scientific) == std::ios_base::scientific);
+ const bool fixed = ((f & std::ios_base::fixed) == std::ios_base::fixed);
+ const bool showpoint = ((f & std::ios_base::showpoint) == std::ios_base::showpoint);
+ const bool showpos = ((f & std::ios_base::showpos) == std::ios_base::showpos);
+
+ const bool b_neg = ((str.size() != 0U) && (str[0] == '-'));
+
+ if(b_neg)
+ {
+ str.erase(0, 1);
+ }
+
+ if(digits == 0)
+ {
+ digits = static_cast<int>((std::max)(str.size(), size_type(16)));
+ }
+
+ if(iszero || str.empty() || (str.find_first_not_of('0') == string_type::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(b_neg)
+ {
+ str.insert(0U, 1U, '-');
+ }
+ else if(showpos)
+ {
+ str.insert(0U, 1U, '+');
+ }
+
+ return;
+ }
+
+ if(!fixed && !scientific && !showpoint)
+ {
+ // Suppress trailing zeros.
+ typename string_type::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.
+
+ int chars = static_cast<int>(str.size());
+ chars = digits - chars;
+
+ if(scientific)
+ {
+ ++chars;
+ }
+
+ if(chars > 0)
+ {
+ str.append(static_cast<size_type>(chars), '0');
+ }
+ }
+
+ if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
+ {
+ if((1 + my_exp) > static_cast<int>(str.size()))
+ {
+ // Just pad out the end with zeros.
+ str.append(static_cast<size_type>((1 + my_exp) - static_cast<int>(str.size())), '0');
+
+ if(showpoint || fixed)
+ {
+ str.append(".");
+ }
+ }
+ else if(my_exp + 1 < static_cast<int>(str.size()))
+ {
+ if(my_exp < 0)
+ {
+ str.insert(0U, static_cast<size_type>(-1 - my_exp), '0');
+ str.insert(0U, "0.");
+ }
+ else
+ {
+ // Insert the decimal point:
+ str.insert(static_cast<size_type>(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.
+ int l = static_cast<int>(str.find('.') + 1U);
+ l = digits - (static_cast<int>(str.size()) - l);
+
+ if(l > 0)
+ {
+ str.append(size_type(l), '0');
+ }
+ }
+ }
+ else
+ {
+ // Scientific format:
+ if(showpoint || (str.size() > 1))
+ {
+ str.insert(1U, 1U, '.');
+ }
+
+ str.append(1U, 'e');
+
+ string_type e = std::to_string(std::abs(my_exp));
+
+ if(e.size() < 2U)
+ {
+ e.insert(0U, 2U - e.size(), '0');
+ }
+
+ if(my_exp < 0)
+ {
+ e.insert(0U, 1U, '-');
+ }
+ else
+ {
+ e.insert(0U, 1U, '+');
+ }
+
+ str.append(e);
+ }
+
+ if(b_neg)
+ {
+ str.insert(0U, 1U, '-');
+ }
+ else if(showpos)
+ {
+ str.insert(0U, 1U, '+');
+ }
+ }
+
+ template<class float_type, class type_a> inline void eval_convert_to(type_a* pa, const float_type& cb) { *pa = static_cast<type_a>(cb); }
+ template<class float_type, class type_a> inline void eval_add (float_type& b, const type_a& a) { b += a; }
+ template<class float_type, class type_a> inline void eval_subtract (float_type& b, const type_a& a) { b -= a; }
+ template<class float_type, class type_a> inline void eval_multiply (float_type& b, const type_a& a) { b *= a; }
+ template<class float_type> inline void eval_multiply (float_type& b, const float_type& cb, const float_type& cb2) { b = (cb * cb2); }
+ template<class float_type, class type_a> inline void eval_divide (float_type& b, const type_a& a) { b /= a; }
+ template<class float_type> inline void eval_log10 (float_type& b, const float_type& cb) { b = std::log10(cb); }
+ template<class float_type> inline void eval_floor (float_type& b, const float_type& cb) { b = std::floor(cb); }
+
+ inline void round_string_up_at(std::string& s, int pos, int& expon)
+ {
+ // This subroutine rounds up a string representation of a
+ // number at the given position pos.
+
+ if(pos < 0)
+ {
+ s.insert(0U, 1U, '1');
+ s.erase(s.size() - 1U);
+ ++expon;
+ }
+ else if(s[pos] == '9')
+ {
+ s[pos] = '0';
+ round_string_up_at(s, pos - 1, expon);
+ }
+ else
+ {
+ if((pos == 0) && (s[pos] == '0') && (s.size() == 1))
+ {
+ ++expon;
+ }
+
+ ++s[pos];
+ }
+ }
+
+ template<class float_type>
+ std::string convert_to_string(float_type& x,
+ std::streamsize digits,
+ const std::ios_base::fmtflags f)
+ {
+ const bool isneg = (x < 0);
+ const bool iszero = ((!isneg) ? bool(+x < (std::numeric_limits<float_type>::min)())
+ : bool(-x < (std::numeric_limits<float_type>::min)()));
+ const bool isnan = (x != x);
+ const bool isinf = ((!isneg) ? bool(+x > (std::numeric_limits<float_type>::max)())
+ : bool(-x > (std::numeric_limits<float_type>::max)()));
+
+ int expon = 0;
+
+ if(digits <= 0) { digits = std::numeric_limits<float_type>::max_digits10; }
+
+ const int org_digits = static_cast<int>(digits);
+
+ std::string result;
+
+ if(iszero)
+ {
+ result = "0";
+ }
+ else if(isinf)
+ {
+ if(x < 0)
+ {
+ return "-inf";
+ }
+ else
+ {
+ return ((f & std::ios_base::showpos) == std::ios_base::showpos) ? "+inf" : "inf";
+ }
+ }
+ else if(isnan)
+ {
+ return "nan";
+ }
+ else
+ {
+ // Start by figuring out the base-10 exponent.
+ if(isneg) { x = -x; }
+
+ float_type t;
+ float_type ten = 10;
+
+ eval_log10(t, x);
+ eval_floor(t, t);
+ eval_convert_to(&expon, t);
+
+ if(-expon > std::numeric_limits<float_type>::max_exponent10 - 3)
+ {
+ int e = -expon / 2;
+
+ const float_type t2 = boost::math::cstdfloat::detail::pown(ten, e);
+
+ eval_multiply(t, t2, x);
+ eval_multiply(t, t2);
+
+ if((expon & 1) != 0)
+ {
+ eval_multiply(t, ten);
+ }
+ }
+ else
+ {
+ t = boost::math::cstdfloat::detail::pown(ten, -expon);
+ eval_multiply(t, x);
+ }
+
+ // Make sure that the value lies between [1, 10), and adjust if not.
+ if(t < 1)
+ {
+ eval_multiply(t, 10);
+
+ --expon;
+ }
+ else if(t >= 10)
+ {
+ eval_divide(t, 10);
+
+ ++expon;
+ }
+
+ float_type digit;
+ int cdigit;
+
+ // Adjust the number of digits required based on formatting options.
+ if(((f & std::ios_base::fixed) == std::ios_base::fixed) && (expon != -1))
+ {
+ digits += (expon + 1);
+ }
+
+ if((f & std::ios_base::scientific) == std::ios_base::scientific)
+ {
+ ++digits;
+ }
+
+ // Extract the base-10 digits one at a time.
+ for(int i = 0; i < digits; ++i)
+ {
+ eval_floor(digit, t);
+ eval_convert_to(&cdigit, digit);
+
+ result += static_cast<char>('0' + cdigit);
+
+ eval_subtract(t, digit);
+ eval_multiply(t, ten);
+ }
+
+ // Possibly round the result.
+ if(digits >= 0)
+ {
+ eval_floor(digit, t);
+ eval_convert_to(&cdigit, digit);
+ eval_subtract(t, digit);
+
+ if((cdigit == 5) && (t == 0))
+ {
+ // Use simple bankers rounding.
+
+ if((static_cast<int>(*result.rbegin() - '0') & 1) != 0)
+ {
+ round_string_up_at(result, static_cast<int>(result.size() - 1U), expon);
+ }
+ }
+ else if(cdigit >= 5)
+ {
+ round_string_up_at(result, static_cast<int>(result.size() - 1), expon);
+ }
+ }
+ }
+
+ while((result.size() > static_cast<std::string::size_type>(digits)) && result.size())
+ {
+ // We may get here as a result of rounding.
+
+ if(result.size() > 1U)
+ {
+ result.erase(result.size() - 1U);
+ }
+ else
+ {
+ if(expon > 0)
+ {
+ --expon; // so we put less padding in the result.
+ }
+ else
+ {
+ ++expon;
+ }
+
+ ++digits;
+ }
+ }
+
+ if(isneg)
+ {
+ result.insert(0U, 1U, '-');
+ }
+
+ format_float_string(result, expon, org_digits, f, iszero);
+
+ return result;
+ }
+
+ template <class float_type>
+ bool convert_from_string(float_type& value, const char* p)
+ {
+ value = 0;
+
+ if((p == static_cast<const char*>(0U)) || (*p == static_cast<char>(0)))
+ {
+ return;
+ }
+
+ bool is_neg = false;
+ bool is_neg_expon = false;
+
+ constexpr int ten = 10;
+
+ int expon = 0;
+ int digits_seen = 0;
+
+ constexpr int max_digits = std::numeric_limits<float_type>::max_digits10 + 1;
+
+ if(*p == static_cast<char>('+'))
+ {
+ ++p;
+ }
+ else if(*p == static_cast<char>('-'))
+ {
+ is_neg = true;
+ ++p;
+ }
+
+ const bool isnan = ((std::strcmp(p, "nan") == 0) || (std::strcmp(p, "NaN") == 0) || (std::strcmp(p, "NAN") == 0));
+
+ if(isnan)
+ {
+ eval_divide(value, 0);
+
+ if(is_neg)
+ {
+ value = -value;
+ }
+
+ return true;
+ }
+
+ const bool isinf = ((std::strcmp(p, "inf") == 0) || (std::strcmp(p, "Inf") == 0) || (std::strcmp(p, "INF") == 0));
+
+ if(isinf)
+ {
+ value = 1;
+ eval_divide(value, 0);
+
+ if(is_neg)
+ {
+ value = -value;
+ }
+
+ return true;
+ }
+
+ // Grab all the leading digits before the decimal point.
+ while(std::isdigit(*p))
+ {
+ eval_multiply(value, ten);
+ eval_add(value, static_cast<int>(*p - '0'));
+ ++p;
+ ++digits_seen;
+ }
+
+ if(*p == static_cast<char>('.'))
+ {
+ // Grab everything after the point, stop when we've seen
+ // enough digits, even if there are actually more available.
+
+ ++p;
+
+ while(std::isdigit(*p))
+ {
+ eval_multiply(value, ten);
+ eval_add(value, static_cast<int>(*p - '0'));
+ ++p;
+ --expon;
+
+ if(++digits_seen > max_digits)
+ {
+ break;
+ }
+ }
+
+ while(std::isdigit(*p))
+ {
+ ++p;
+ }
+ }
+
+ // Parse the exponent.
+ if((*p == static_cast<char>('e')) || (*p == static_cast<char>('E')))
+ {
+ ++p;
+
+ if(*p == static_cast<char>('+'))
+ {
+ ++p;
+ }
+ else if(*p == static_cast<char>('-'))
+ {
+ is_neg_expon = true;
+ ++p;
+ }
+
+ int e2 = 0;
+
+ while(std::isdigit(*p))
+ {
+ e2 *= 10;
+ e2 += (*p - '0');
+ ++p;
+ }
+
+ if(is_neg_expon)
+ {
+ e2 = -e2;
+ }
+
+ expon += e2;
+ }
+
+ if(expon)
+ {
+ // Scale by 10^expon. Note that 10^expon can be outside the range
+ // of our number type, even though the result is within range.
+ // If that looks likely, then split the calculation in two parts.
+ float_type t;
+ t = ten;
+
+ if(expon > (std::numeric_limits<float_type>::min_exponent10 + 2))
+ {
+ t = boost::math::cstdfloat::detail::pown(t, expon);
+ eval_multiply(value, t);
+ }
+ else
+ {
+ t = boost::math::cstdfloat::detail::pown(t, (expon + digits_seen + 1));
+ eval_multiply(value, t);
+ t = ten;
+ t = boost::math::cstdfloat::detail::pown(t, (-digits_seen - 1));
+ eval_multiply(value, t);
+ }
+ }
+
+ if(is_neg)
+ {
+ value = -value;
+ }
+
+ return (*p == static_cast<char>(0));
+ }
+ } } } } // boost::math::cstdfloat::detail
+
+ namespace std
+ {
+ template<typename char_type, class traits_type>
+ inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const boost::math::cstdfloat::detail::float_internal128_t& x)
+ {
+ boost::math::cstdfloat::detail::float_internal128_t non_const_x = x;
+
+ const std::string str = boost::math::cstdfloat::detail::convert_to_string(non_const_x,
+ os.precision(),
+ os.flags());
+
+ std::basic_ostringstream<char_type, traits_type> ostr;
+ ostr.flags(os.flags());
+ ostr.imbue(os.getloc());
+ ostr.precision(os.precision());
+
+ static_cast<void>(ostr << str);
+
+ return (os << ostr.str());
+ }
+
+ template<typename char_type, class traits_type>
+ inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, boost::math::cstdfloat::detail::float_internal128_t& x)
+ {
+ std::string str;
+
+ static_cast<void>(is >> str);
+
+ const bool conversion_is_ok = boost::math::cstdfloat::detail::convert_from_string(x, str.c_str());
+
+ if(false == conversion_is_ok)
+ {
+ for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it)
+ {
+ static_cast<void>(is.putback(*it));
+ }
+
+ is.setstate(ios_base::failbit);
+
+ BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
+ }
+
+ return is;
+ }
+ }
+
+ #endif // Use __GNUC__ or __INTEL_COMPILER libquadmath
+
+ #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
+
+#endif // BOOST_MATH_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
diff --git a/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_limits.hpp b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_limits.hpp
new file mode 100644
index 0000000000..ef26a99d6f
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_limits.hpp
@@ -0,0 +1,86 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2014.
+// Copyright John Maddock 2014.
+// Copyright Paul Bristow 2014.
+// 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)
+//
+
+// Implement quadruple-precision std::numeric_limits<> support.
+
+#ifndef BOOST_MATH_CSTDFLOAT_LIMITS_2014_01_09_HPP_
+ #define BOOST_MATH_CSTDFLOAT_LIMITS_2014_01_09_HPP_
+
+ #include <boost/math/cstdfloat/cstdfloat_types.hpp>
+
+#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
+//
+// This is the only way we can avoid
+// warning: non-standard suffix on floating constant [-Wpedantic]
+// when building with -Wall -pedantic. Neither __extension__
+// nor #pragma diagnostic ignored work :(
+//
+#pragma GCC system_header
+#endif
+
+ #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+
+ #include <limits>
+
+ // Define the name of the global quadruple-precision function to be used for
+ // calculating quiet_NaN() in the specialization of std::numeric_limits<>.
+ #if defined(__INTEL_COMPILER)
+ #define BOOST_CSTDFLOAT_FLOAT128_SQRT __sqrtq
+ #elif defined(__GNUC__)
+ #define BOOST_CSTDFLOAT_FLOAT128_SQRT sqrtq
+ #endif
+
+ // Forward declaration of the quadruple-precision square root function.
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(boost::math::cstdfloat::detail::float_internal128_t) noexcept;
+
+ namespace std
+ {
+ template<>
+ class numeric_limits<boost::math::cstdfloat::detail::float_internal128_t>
+ {
+ public:
+ static constexpr bool is_specialized = true;
+ static boost::math::cstdfloat::detail::float_internal128_t (min) () noexcept { return BOOST_CSTDFLOAT_FLOAT128_MIN; }
+ static boost::math::cstdfloat::detail::float_internal128_t (max) () noexcept { return BOOST_CSTDFLOAT_FLOAT128_MAX; }
+ static boost::math::cstdfloat::detail::float_internal128_t lowest() noexcept { return -(max)(); }
+ static constexpr int digits = 113;
+ static constexpr int digits10 = 33;
+ static constexpr int max_digits10 = 36;
+ static constexpr bool is_signed = true;
+ static constexpr bool is_integer = false;
+ static constexpr bool is_exact = false;
+ static constexpr int radix = 2;
+ static boost::math::cstdfloat::detail::float_internal128_t epsilon () { return BOOST_CSTDFLOAT_FLOAT128_EPS; }
+ static boost::math::cstdfloat::detail::float_internal128_t round_error() { return BOOST_FLOAT128_C(0.5); }
+ static constexpr int min_exponent = -16381;
+ static constexpr int min_exponent10 = static_cast<int>((min_exponent * 301L) / 1000L);
+ static constexpr int max_exponent = +16384;
+ static constexpr int max_exponent10 = static_cast<int>((max_exponent * 301L) / 1000L);
+ static constexpr bool has_infinity = true;
+ static constexpr bool has_quiet_NaN = true;
+ static constexpr bool has_signaling_NaN = false;
+ static constexpr float_denorm_style has_denorm = denorm_present;
+ static constexpr bool has_denorm_loss = false;
+ static boost::math::cstdfloat::detail::float_internal128_t infinity () { return BOOST_FLOAT128_C(1.0) / BOOST_FLOAT128_C(0.0); }
+ static boost::math::cstdfloat::detail::float_internal128_t quiet_NaN () { return -(::BOOST_CSTDFLOAT_FLOAT128_SQRT(BOOST_FLOAT128_C(-1.0))); }
+ static boost::math::cstdfloat::detail::float_internal128_t signaling_NaN() { return BOOST_FLOAT128_C(0.0); }
+ static boost::math::cstdfloat::detail::float_internal128_t denorm_min () { return BOOST_CSTDFLOAT_FLOAT128_DENORM_MIN; }
+ static constexpr bool is_iec559 = true;
+ static constexpr bool is_bounded = true;
+ static constexpr bool is_modulo = false;
+ static constexpr bool traps = false;
+ static constexpr bool tinyness_before = false;
+ static constexpr float_round_style round_style = round_to_nearest;
+ };
+ } // namespace std
+
+ #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
+
+#endif // BOOST_MATH_CSTDFLOAT_LIMITS_2014_01_09_HPP_
+
diff --git a/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_types.hpp b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_types.hpp
new file mode 100644
index 0000000000..bc32c71fe9
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/cstdfloat/cstdfloat_types.hpp
@@ -0,0 +1,441 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2014.
+// Copyright John Maddock 2014.
+// Copyright Paul Bristow 2014.
+// 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)
+//
+
+// Implement the types for floating-point typedefs having specified widths.
+
+#ifndef BOOST_MATH_CSTDFLOAT_TYPES_2014_01_09_HPP_
+ #define BOOST_MATH_CSTDFLOAT_TYPES_2014_01_09_HPP_
+
+ #include <float.h>
+ #include <limits>
+ #include <boost/math/tools/config.hpp>
+
+ // This is the beginning of the preamble.
+
+ // In this preamble, the preprocessor is used to query certain
+ // preprocessor definitions from <float.h>. Based on the results
+ // of these queries, an attempt is made to automatically detect
+ // the presence of built-in floating-point types having specified
+ // widths. These are *thought* to be conformant with IEEE-754,
+ // whereby an unequivocal test based on std::numeric_limits<>
+ // follows below.
+
+ // In addition, various macros that are used for initializing
+ // floating-point literal values having specified widths and
+ // some basic min/max values are defined.
+
+ // First, we will pre-load certain preprocessor definitions
+ // with a dummy value.
+
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 0
+
+ #define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 0
+ #define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 0
+ #define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 0
+ #define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 0
+ #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 0
+
+ // Ensure that the compiler has a radix-2 floating-point representation.
+ #if (!defined(FLT_RADIX) || ((defined(FLT_RADIX) && (FLT_RADIX != 2))))
+ #error The compiler does not support any radix-2 floating-point types required for <boost/cstdfloat.hpp>.
+ #endif
+
+ // Check if built-in float is equivalent to float16_t, float32_t, float64_t, float80_t, or float128_t.
+ #if(defined(FLT_MANT_DIG) && defined(FLT_MAX_EXP))
+ #if ((FLT_MANT_DIG == 11) && (FLT_MAX_EXP == 16) && (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE float
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 16
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 1
+ #define BOOST_FLOAT16_C(x) (x ## F)
+ #define BOOST_CSTDFLOAT_FLOAT_16_MIN FLT_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_16_MAX FLT_MAX
+ #elif((FLT_MANT_DIG == 24) && (FLT_MAX_EXP == 128) && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE float
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 32
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 1
+ #define BOOST_FLOAT32_C(x) (x ## F)
+ #define BOOST_CSTDFLOAT_FLOAT_32_MIN FLT_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_32_MAX FLT_MAX
+ #elif((FLT_MANT_DIG == 53) && (FLT_MAX_EXP == 1024) && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE float
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 1
+ #define BOOST_FLOAT64_C(x) (x ## F)
+ #define BOOST_CSTDFLOAT_FLOAT_64_MIN FLT_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_64_MAX FLT_MAX
+ #elif((FLT_MANT_DIG == 64) && (FLT_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE float
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 80
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 1
+ #define BOOST_FLOAT80_C(x) (x ## F)
+ #define BOOST_CSTDFLOAT_FLOAT_80_MIN FLT_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_80_MAX FLT_MAX
+ #elif((FLT_MANT_DIG == 113) && (FLT_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE float
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1
+ #define BOOST_FLOAT128_C(x) (x ## F)
+ #define BOOST_CSTDFLOAT_FLOAT_128_MIN FLT_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_128_MAX FLT_MAX
+ #endif
+ #endif
+
+ // Check if built-in double is equivalent to float16_t, float32_t, float64_t, float80_t, or float128_t.
+ #if(defined(DBL_MANT_DIG) && defined(DBL_MAX_EXP))
+ #if ((DBL_MANT_DIG == 11) && (DBL_MAX_EXP == 16) && (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 16
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 1
+ #define BOOST_FLOAT16_C(x) (x)
+ #define BOOST_CSTDFLOAT_FLOAT_16_MIN DBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_16_MAX DBL_MAX
+ #elif((DBL_MANT_DIG == 24) && (DBL_MAX_EXP == 128) && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 32
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 1
+ #define BOOST_FLOAT32_C(x) (x)
+ #define BOOST_CSTDFLOAT_FLOAT_32_MIN DBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_32_MAX DBL_MAX
+ #elif((DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024) && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 1
+ #define BOOST_FLOAT64_C(x) (x)
+ #define BOOST_CSTDFLOAT_FLOAT_64_MIN DBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_64_MAX DBL_MAX
+ #elif((DBL_MANT_DIG == 64) && (DBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 80
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 1
+ #define BOOST_FLOAT80_C(x) (x)
+ #define BOOST_CSTDFLOAT_FLOAT_80_MIN DBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_80_MAX DBL_MAX
+ #elif((DBL_MANT_DIG == 113) && (DBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1
+ #define BOOST_FLOAT128_C(x) (x)
+ #define BOOST_CSTDFLOAT_FLOAT_128_MIN DBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_128_MAX DBL_MAX
+ #endif
+ #endif
+
+ // Disable check long double capability even if supported by compiler since some math runtime
+ // implementations are broken for long double.
+ #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
+ // Check if built-in long double is equivalent to float16_t, float32_t, float64_t, float80_t, or float128_t.
+ #if(defined(LDBL_MANT_DIG) && defined(LDBL_MAX_EXP))
+ #if ((LDBL_MANT_DIG == 11) && (LDBL_MAX_EXP == 16) && (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE long double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 16
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 1
+ #define BOOST_FLOAT16_C(x) (x ## L)
+ #define BOOST_CSTDFLOAT_FLOAT_16_MIN LDBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_16_MAX LDBL_MAX
+ #elif((LDBL_MANT_DIG == 24) && (LDBL_MAX_EXP == 128) && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE long double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 32
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 1
+ #define BOOST_FLOAT32_C(x) (x ## L)
+ #define BOOST_CSTDFLOAT_FLOAT_32_MIN LDBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_32_MAX LDBL_MAX
+ #elif((LDBL_MANT_DIG == 53) && (LDBL_MAX_EXP == 1024) && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE long double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 1
+ #define BOOST_FLOAT64_C(x) (x ## L)
+ #define BOOST_CSTDFLOAT_FLOAT_64_MIN LDBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_64_MAX LDBL_MAX
+ #elif((LDBL_MANT_DIG == 64) && (LDBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE long double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 80
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 1
+ #define BOOST_FLOAT80_C(x) (x ## L)
+ #define BOOST_CSTDFLOAT_FLOAT_80_MIN LDBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_80_MAX LDBL_MAX
+ #elif((LDBL_MANT_DIG == 113) && (LDBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0))
+ #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE long double
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1
+ #define BOOST_FLOAT128_C(x) (x ## L)
+ #define BOOST_CSTDFLOAT_FLOAT_128_MIN LDBL_MIN
+ #define BOOST_CSTDFLOAT_FLOAT_128_MAX LDBL_MAX
+ #endif
+ #endif
+ #endif
+
+ // Check if quadruple-precision is supported. Here, we are checking
+ // for the presence of __float128 from GCC's quadmath.h or _Quad
+ // from ICC's /Qlong-double flag). To query these, we use the
+ // BOOST_MATH_USE_FLOAT128 pre-processor definition from
+ // <boost/math/tools/config.hpp>.
+
+ #if (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+
+ // Specify the underlying name of the internal 128-bit floating-point type definition.
+ namespace boost { namespace math { namespace cstdfloat { namespace detail {
+ #if defined(__GNUC__)
+ typedef __float128 float_internal128_t;
+ #elif defined(__INTEL_COMPILER)
+ typedef _Quad float_internal128_t;
+ #else
+ #error "Sorry, the compiler is neither GCC, nor Intel, I don't know how to configure <boost/cstdfloat.hpp>."
+ #endif
+ } } } } // boost::math::cstdfloat::detail
+
+ #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE boost::math::cstdfloat::detail::float_internal128_t
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
+ #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1
+ #define BOOST_FLOAT128_C(x) (x ## Q)
+ #define BOOST_CSTDFLOAT_FLOAT128_MIN 3.36210314311209350626267781732175260e-4932Q
+ #define BOOST_CSTDFLOAT_FLOAT128_MAX 1.18973149535723176508575932662800702e+4932Q
+ #define BOOST_CSTDFLOAT_FLOAT128_EPS 1.92592994438723585305597794258492732e-0034Q
+ #define BOOST_CSTDFLOAT_FLOAT128_DENORM_MIN 6.475175119438025110924438958227646552e-4966Q
+
+ #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
+
+ // This is the end of the preamble, and also the end of the
+ // sections providing support for the C++ standard library
+ // for quadruple-precision.
+
+ // Now we use the results of the queries that have been obtained
+ // in the preamble (far above) for the final type definitions in
+ // the namespace boost.
+
+ // Make sure that the compiler has any floating-point type(s) whatsoever.
+ #if ( (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0) \
+ && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0) \
+ && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0) \
+ && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0) \
+ && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0))
+ #error The compiler does not support any of the floating-point types required for <boost/cstdfloat.hpp>.
+ #endif
+
+ // The following section contains the various min/max macros
+ // for the *leastN and *fastN types.
+
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 1)
+ #define BOOST_FLOAT_FAST16_MIN BOOST_CSTDFLOAT_FLOAT_16_MIN
+ #define BOOST_FLOAT_LEAST16_MIN BOOST_CSTDFLOAT_FLOAT_16_MIN
+ #define BOOST_FLOAT_FAST16_MAX BOOST_CSTDFLOAT_FLOAT_16_MAX
+ #define BOOST_FLOAT_LEAST16_MAX BOOST_CSTDFLOAT_FLOAT_16_MAX
+ #endif
+
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 1)
+ #define BOOST_FLOAT_FAST32_MIN BOOST_CSTDFLOAT_FLOAT_32_MIN
+ #define BOOST_FLOAT_LEAST32_MIN BOOST_CSTDFLOAT_FLOAT_32_MIN
+ #define BOOST_FLOAT_FAST32_MAX BOOST_CSTDFLOAT_FLOAT_32_MAX
+ #define BOOST_FLOAT_LEAST32_MAX BOOST_CSTDFLOAT_FLOAT_32_MAX
+ #endif
+
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 1)
+ #define BOOST_FLOAT_FAST64_MIN BOOST_CSTDFLOAT_FLOAT_64_MIN
+ #define BOOST_FLOAT_LEAST64_MIN BOOST_CSTDFLOAT_FLOAT_64_MIN
+ #define BOOST_FLOAT_FAST64_MAX BOOST_CSTDFLOAT_FLOAT_64_MAX
+ #define BOOST_FLOAT_LEAST64_MAX BOOST_CSTDFLOAT_FLOAT_64_MAX
+ #endif
+
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 1)
+ #define BOOST_FLOAT_FAST80_MIN BOOST_CSTDFLOAT_FLOAT_80_MIN
+ #define BOOST_FLOAT_LEAST80_MIN BOOST_CSTDFLOAT_FLOAT_80_MIN
+ #define BOOST_FLOAT_FAST80_MAX BOOST_CSTDFLOAT_FLOAT_80_MAX
+ #define BOOST_FLOAT_LEAST80_MAX BOOST_CSTDFLOAT_FLOAT_80_MAX
+ #endif
+
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 1)
+ #define BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T
+
+ #define BOOST_FLOAT_FAST128_MIN BOOST_CSTDFLOAT_FLOAT_128_MIN
+ #define BOOST_FLOAT_LEAST128_MIN BOOST_CSTDFLOAT_FLOAT_128_MIN
+ #define BOOST_FLOAT_FAST128_MAX BOOST_CSTDFLOAT_FLOAT_128_MAX
+ #define BOOST_FLOAT_LEAST128_MAX BOOST_CSTDFLOAT_FLOAT_128_MAX
+ #endif
+
+ // The following section contains the various min/max macros
+ // for the *floatmax types.
+
+ #if (BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 16)
+ #define BOOST_FLOATMAX_C(x) BOOST_FLOAT16_C(x)
+ #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_16_MIN
+ #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_16_MAX
+ #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 32)
+ #define BOOST_FLOATMAX_C(x) BOOST_FLOAT32_C(x)
+ #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_32_MIN
+ #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_32_MAX
+ #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 64)
+ #define BOOST_FLOATMAX_C(x) BOOST_FLOAT64_C(x)
+ #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_64_MIN
+ #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_64_MAX
+ #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 80)
+ #define BOOST_FLOATMAX_C(x) BOOST_FLOAT80_C(x)
+ #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_80_MIN
+ #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_80_MAX
+ #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 128)
+ #define BOOST_FLOATMAX_C(x) BOOST_FLOAT128_C(x)
+ #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_128_MIN
+ #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_128_MAX
+ #else
+ #error The maximum available floating-point width for <boost/cstdfloat.hpp> is undefined.
+ #endif
+
+ // And finally..., we define the floating-point typedefs having
+ // specified widths. The types are defined in the namespace boost.
+
+ // For simplicity, the least and fast types are type defined identically
+ // as the corresponding fixed-width type. This behavior may, however,
+ // be modified when being optimized for a given compiler implementation.
+
+ // In addition, a clear assessment of IEEE-754 conformance is carried out
+ // using compile-time assertion.
+
+ namespace boost
+ {
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 1)
+ typedef BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE float16_t;
+ typedef boost::float16_t float_fast16_t;
+ typedef boost::float16_t float_least16_t;
+
+ static_assert(std::numeric_limits<boost::float16_t>::is_iec559 == true, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float16_t>::radix == 2, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float16_t>::digits == 11, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float16_t>::max_exponent == 16, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+
+ #undef BOOST_CSTDFLOAT_FLOAT_16_MIN
+ #undef BOOST_CSTDFLOAT_FLOAT_16_MAX
+ #endif
+
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 1)
+ typedef BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE float32_t;
+ typedef boost::float32_t float_fast32_t;
+ typedef boost::float32_t float_least32_t;
+
+ static_assert(std::numeric_limits<boost::float32_t>::is_iec559 == true, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float32_t>::radix == 2, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float32_t>::digits == 24, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float32_t>::max_exponent == 128, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+
+ #undef BOOST_CSTDFLOAT_FLOAT_32_MIN
+ #undef BOOST_CSTDFLOAT_FLOAT_32_MAX
+ #endif
+
+#if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && defined(__SUNPRO_CC)
+#undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
+#define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 0
+#undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
+#define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 0
+#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64
+#endif
+
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 1)
+ typedef BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE float64_t;
+ typedef boost::float64_t float_fast64_t;
+ typedef boost::float64_t float_least64_t;
+
+ static_assert(std::numeric_limits<boost::float64_t>::is_iec559 == true, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float64_t>::radix == 2, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float64_t>::digits == 53, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float64_t>::max_exponent == 1024, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+
+ #undef BOOST_CSTDFLOAT_FLOAT_64_MIN
+ #undef BOOST_CSTDFLOAT_FLOAT_64_MAX
+ #endif
+
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 1)
+ typedef BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE float80_t;
+ typedef boost::float80_t float_fast80_t;
+ typedef boost::float80_t float_least80_t;
+
+ static_assert(std::numeric_limits<boost::float80_t>::is_iec559 == true, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float80_t>::radix == 2, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float80_t>::digits == 64, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float80_t>::max_exponent == 16384, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+
+ #undef BOOST_CSTDFLOAT_FLOAT_80_MIN
+ #undef BOOST_CSTDFLOAT_FLOAT_80_MAX
+ #endif
+
+ #if(BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 1)
+ typedef BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE float128_t;
+ typedef boost::float128_t float_fast128_t;
+ typedef boost::float128_t float_least128_t;
+
+ #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+ // This configuration does not *yet* support std::numeric_limits<boost::float128_t>.
+ // Support for std::numeric_limits<boost::float128_t> is added in the detail
+ // file <boost/math/cstdfloat/cstdfloat_limits.hpp>.
+ #else
+ static_assert(std::numeric_limits<boost::float128_t>::is_iec559 == true, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float128_t>::radix == 2, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float128_t>::digits == 113, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ static_assert(std::numeric_limits<boost::float128_t>::max_exponent == 16384, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ #endif
+
+ #undef BOOST_CSTDFLOAT_FLOAT_128_MIN
+ #undef BOOST_CSTDFLOAT_FLOAT_128_MAX
+ #endif
+
+ #if (BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 16)
+ typedef boost::float16_t floatmax_t;
+ #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 32)
+ typedef boost::float32_t floatmax_t;
+ #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 64)
+ typedef boost::float64_t floatmax_t;
+ #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 80)
+ typedef boost::float80_t floatmax_t;
+ #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 128)
+ typedef boost::float128_t floatmax_t;
+ #else
+ #error The maximum available floating-point width for <boost/cstdfloat.hpp> is undefined.
+ #endif
+
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
+ #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
+
+ #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
+ }
+ // namespace boost
+
+#endif // BOOST_MATH_CSTDFLOAT_BASE_TYPES_2014_01_09_HPP_
+
diff --git a/contrib/restricted/boost/math/include/boost/math/policies/error_handling.hpp b/contrib/restricted/boost/math/include/boost/math/policies/error_handling.hpp
index 124337ee87..3af1f976b5 100644
--- a/contrib/restricted/boost/math/include/boost/math/policies/error_handling.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/policies/error_handling.hpp
@@ -8,21 +8,25 @@
#ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP
#define BOOST_MATH_POLICY_ERROR_HANDLING_HPP
-#include <stdexcept>
+#include <boost/math/tools/config.hpp>
#include <iomanip>
#include <string>
#include <cstring>
+#ifndef BOOST_NO_RTTI
#include <typeinfo>
+#endif
#include <cerrno>
-#include <boost/config/no_tr1/complex.hpp>
-#include <boost/config/no_tr1/cmath.hpp>
-#include <stdexcept>
-#include <boost/math/tools/config.hpp>
+#include <complex>
+#include <cmath>
+#include <cstdint>
#include <boost/math/policies/policy.hpp>
#include <boost/math/tools/precision.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/cstdint.hpp>
-#ifdef BOOST_MSVC
+#ifndef BOOST_NO_EXCEPTIONS
+#include <stdexcept>
+#include <boost/math/tools/throw_exception.hpp>
+#endif
+
+#ifdef _MSC_VER
# pragma warning(push) // Quiet warnings in boost/format.hpp
# pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE
# pragma warning(disable: 4512) // assignment operator could not be generated.
@@ -36,6 +40,8 @@
namespace boost{ namespace math{
+#ifndef BOOST_NO_EXCEPTIONS
+
class evaluation_error : public std::runtime_error
{
public:
@@ -48,6 +54,8 @@ public:
rounding_error(const std::string& s) : std::runtime_error(s){}
};
+#endif
+
namespace policies{
//
// Forward declarations of user error handlers,
@@ -120,6 +128,7 @@ inline const char* name_of<BOOST_MATH_FLOAT128_TYPE>()
}
#endif
+#ifndef BOOST_NO_EXCEPTIONS
template <class E, class T>
void raise_error(const char* pfunction, const char* message)
{
@@ -140,7 +149,7 @@ void raise_error(const char* pfunction, const char* message)
msg += message;
E e(msg);
- boost::throw_exception(e);
+ BOOST_MATH_THROW_EXCEPTION(e)
}
template <class E, class T>
@@ -167,8 +176,9 @@ void raise_error(const char* pfunction, const char* pmessage, const T& val)
msg += message;
E e(msg);
- boost::throw_exception(e);
+ BOOST_MATH_THROW_EXCEPTION(e)
}
+#endif
template <class T>
inline T raise_domain_error(
@@ -177,13 +187,17 @@ inline T raise_domain_error(
const T& val,
const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
{
+#ifdef BOOST_NO_EXCEPTIONS
+ static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
+#else
raise_error<std::domain_error, T>(function, message, val);
// we never get here:
return std::numeric_limits<T>::quiet_NaN();
+#endif
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T raise_domain_error(
+inline constexpr T raise_domain_error(
const char* ,
const char* ,
const T& ,
@@ -224,11 +238,15 @@ inline T raise_pole_error(
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
{
+#ifdef BOOST_NO_EXCEPTIONS
+ static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
+#else
return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
+#endif
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T raise_pole_error(
+inline constexpr T raise_pole_error(
const char* function,
const char* message,
const T& val,
@@ -238,7 +256,7 @@ inline BOOST_MATH_CONSTEXPR T raise_pole_error(
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T raise_pole_error(
+inline constexpr T raise_pole_error(
const char* function,
const char* message,
const T& val,
@@ -257,16 +275,19 @@ inline T raise_pole_error(
return user_pole_error(function, message, val);
}
-
template <class T>
inline T raise_overflow_error(
const char* function,
const char* message,
const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
{
+#ifdef BOOST_NO_EXCEPTIONS
+ static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
+#else
raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
// We should never get here:
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
+#endif
}
template <class T>
@@ -276,13 +297,17 @@ inline T raise_overflow_error(
const T& val,
const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
{
+#ifdef BOOST_NO_EXCEPTIONS
+ static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
+#else
raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow", val);
// We should never get here:
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
+#endif
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T raise_overflow_error(
+inline constexpr T raise_overflow_error(
const char* ,
const char* ,
const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
@@ -293,7 +318,7 @@ inline BOOST_MATH_CONSTEXPR T raise_overflow_error(
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T raise_overflow_error(
+inline constexpr T raise_overflow_error(
const char* ,
const char* ,
const T&,
@@ -358,13 +383,17 @@ inline T raise_underflow_error(
const char* message,
const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
{
+#ifdef BOOST_NO_EXCEPTIONS
+ static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
+#else
raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
// We should never get here:
return 0;
+#endif
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T raise_underflow_error(
+inline constexpr T raise_underflow_error(
const char* ,
const char* ,
const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
@@ -402,13 +431,17 @@ inline T raise_denorm_error(
const T& /* val */,
const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
{
+#ifdef BOOST_NO_EXCEPTIONS
+ static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
+#else
raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");
// we never get here:
return T(0);
+#endif
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T raise_denorm_error(
+inline constexpr T raise_denorm_error(
const char* ,
const char* ,
const T& val,
@@ -449,13 +482,17 @@ inline T raise_evaluation_error(
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
{
+#ifdef BOOST_NO_EXCEPTIONS
+ static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
+#else
raise_error<boost::math::evaluation_error, T>(function, message, val);
// we never get here:
return T(0);
+#endif
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T raise_evaluation_error(
+inline constexpr T raise_evaluation_error(
const char* ,
const char* ,
const T& val,
@@ -497,13 +534,17 @@ inline TargetType raise_rounding_error(
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
{
+#ifdef BOOST_NO_EXCEPTIONS
+ static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
+#else
raise_error<boost::math::rounding_error, T>(function, message, val);
// we never get here:
return TargetType(0);
+#endif
}
template <class T, class TargetType>
-inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(
+inline constexpr TargetType raise_rounding_error(
const char* ,
const char* ,
const T& val,
@@ -512,7 +553,7 @@ inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
- BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
+ static_assert(std::numeric_limits<TargetType>::is_specialized, "The target type must be specialized.");
return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
}
@@ -527,7 +568,7 @@ inline TargetType raise_rounding_error(
errno = ERANGE;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
- BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
+ static_assert(std::numeric_limits<TargetType>::is_specialized, "The target type must be specialized.");
return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
}
@@ -564,13 +605,17 @@ inline T raise_indeterminate_result_error(
const R& ,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)
{
+#ifdef BOOST_NO_EXCEPTIONS
+ static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
+#else
raise_error<std::domain_error, T>(function, message, val);
// we never get here:
return std::numeric_limits<T>::quiet_NaN();
+#endif
}
template <class T, class R>
-inline BOOST_MATH_CONSTEXPR T raise_indeterminate_result_error(
+inline constexpr T raise_indeterminate_result_error(
const char* ,
const char* ,
const T& ,
@@ -610,7 +655,7 @@ inline T raise_indeterminate_result_error(
} // namespace detail
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T raise_domain_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
+inline constexpr T raise_domain_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::domain_error_type policy_type;
return detail::raise_domain_error(
@@ -619,7 +664,7 @@ inline BOOST_MATH_CONSTEXPR T raise_domain_error(const char* function, const cha
}
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T raise_pole_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
+inline constexpr T raise_pole_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::pole_error_type policy_type;
return detail::raise_pole_error(
@@ -628,7 +673,7 @@ inline BOOST_MATH_CONSTEXPR T raise_pole_error(const char* function, const char*
}
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const char* message, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
+inline constexpr T raise_overflow_error(const char* function, const char* message, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::overflow_error_type policy_type;
return detail::raise_overflow_error<T>(
@@ -637,7 +682,7 @@ inline BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const c
}
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
+inline constexpr T raise_overflow_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::overflow_error_type policy_type;
return detail::raise_overflow_error(
@@ -646,7 +691,7 @@ inline BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const c
}
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T raise_underflow_error(const char* function, const char* message, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
+inline constexpr T raise_underflow_error(const char* function, const char* message, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::underflow_error_type policy_type;
return detail::raise_underflow_error<T>(
@@ -655,7 +700,7 @@ inline BOOST_MATH_CONSTEXPR T raise_underflow_error(const char* function, const
}
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
+inline constexpr T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::denorm_error_type policy_type;
return detail::raise_denorm_error<T>(
@@ -665,7 +710,7 @@ inline BOOST_MATH_CONSTEXPR T raise_denorm_error(const char* function, const cha
}
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
+inline constexpr T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::evaluation_error_type policy_type;
return detail::raise_evaluation_error(
@@ -674,7 +719,7 @@ inline BOOST_MATH_CONSTEXPR T raise_evaluation_error(const char* function, const
}
template <class T, class TargetType, class Policy>
-inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
+inline constexpr TargetType raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::rounding_error_type policy_type;
return detail::raise_rounding_error(
@@ -683,7 +728,7 @@ inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(const char* function
}
template <class T, class R, class Policy>
-inline BOOST_MATH_CONSTEXPR T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
+inline constexpr T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::indeterminate_result_error_type policy_type;
return detail::raise_indeterminate_result_error(
@@ -698,7 +743,7 @@ namespace detail
{
template <class R, class T, class Policy>
-inline bool check_overflow(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
+inline bool check_overflow(T val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
BOOST_MATH_STD_USING
if(fabs(val) > tools::max_value<R>())
@@ -710,7 +755,7 @@ inline bool check_overflow(T val, R* result, const char* function, const Policy&
return false;
}
template <class R, class T, class Policy>
-inline bool check_overflow(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
+inline bool check_overflow(std::complex<T> val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
typedef typename R::value_type r_type;
r_type re, im;
@@ -720,7 +765,7 @@ inline bool check_overflow(std::complex<T> val, R* result, const char* function,
return r;
}
template <class R, class T, class Policy>
-inline bool check_underflow(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
+inline bool check_underflow(T val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
if((val != 0) && (static_cast<R>(val) == 0))
{
@@ -730,7 +775,7 @@ inline bool check_underflow(T val, R* result, const char* function, const Policy
return false;
}
template <class R, class T, class Policy>
-inline bool check_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
+inline bool check_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
typedef typename R::value_type r_type;
r_type re, im;
@@ -740,7 +785,7 @@ inline bool check_underflow(std::complex<T> val, R* result, const char* function
return r;
}
template <class R, class T, class Policy>
-inline bool check_denorm(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
+inline bool check_denorm(T val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
BOOST_MATH_STD_USING
if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))
@@ -751,7 +796,7 @@ inline bool check_denorm(T val, R* result, const char* function, const Policy& p
return false;
}
template <class R, class T, class Policy>
-inline bool check_denorm(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
+inline bool check_denorm(std::complex<T> val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
typedef typename R::value_type r_type;
r_type re, im;
@@ -763,28 +808,28 @@ inline bool check_denorm(std::complex<T> val, R* result, const char* function, c
// Default instantiations with ignore_error policy.
template <class R, class T>
-inline BOOST_MATH_CONSTEXPR bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
+inline constexpr bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
-inline BOOST_MATH_CONSTEXPR bool check_overflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
+inline constexpr bool check_overflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
-inline BOOST_MATH_CONSTEXPR bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
+inline constexpr bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
-inline BOOST_MATH_CONSTEXPR bool check_underflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
+inline constexpr bool check_underflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
-inline BOOST_MATH_CONSTEXPR bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
+inline constexpr bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
-inline BOOST_MATH_CONSTEXPR bool check_denorm(std::complex<T> /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
+inline constexpr bool check_denorm(std::complex<T> /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
} // namespace detail
template <class R, class Policy, class T>
-inline R checked_narrowing_cast(T val, const char* function) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
+inline R checked_narrowing_cast(T val, const char* function) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
{
typedef typename Policy::overflow_error_type overflow_type;
typedef typename Policy::underflow_error_type underflow_type;
@@ -804,7 +849,7 @@ inline R checked_narrowing_cast(T val, const char* function) BOOST_NOEXCEPT_IF(B
}
template <class T, class Policy>
-inline void check_series_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
+inline void check_series_iterations(const char* function, std::uintmax_t max_iter, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
{
if(max_iter >= policies::get_max_series_iterations<Policy>())
raise_evaluation_error<T>(
@@ -813,7 +858,7 @@ inline void check_series_iterations(const char* function, boost::uintmax_t max_i
}
template <class T, class Policy>
-inline void check_root_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
+inline void check_root_iterations(const char* function, std::uintmax_t max_iter, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
{
if(max_iter >= policies::get_max_root_iterations<Policy>())
raise_evaluation_error<T>(
@@ -837,7 +882,7 @@ std::pair<T, T> pair_from_single(const T& val) BOOST_MATH_NOEXCEPT(T)
}
-#ifdef BOOST_MSVC
+#ifdef _MSC_VER
# pragma warning(pop)
#endif
diff --git a/contrib/restricted/boost/math/include/boost/math/policies/policy.hpp b/contrib/restricted/boost/math/include/boost/math/policies/policy.hpp
index c1e1a7be4a..ed4f58a7e4 100644
--- a/contrib/restricted/boost/math/include/boost/math/policies/policy.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/policies/policy.hpp
@@ -1,4 +1,5 @@
// Copyright John Maddock 2007.
+// Copyright Matt Borland 2021.
// Use, modification and distribution are subject to 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)
@@ -6,36 +7,24 @@
#ifndef BOOST_MATH_POLICY_HPP
#define BOOST_MATH_POLICY_HPP
-#include <boost/mpl/list.hpp>
-#include <boost/mpl/contains.hpp>
-#include <boost/mpl/if.hpp>
-#include <boost/mpl/find_if.hpp>
-#include <boost/mpl/remove_if.hpp>
-#include <boost/mpl/vector.hpp>
-#include <boost/mpl/push_back.hpp>
-#include <boost/mpl/at.hpp>
-#include <boost/mpl/size.hpp>
-#include <boost/mpl/comparison.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/assert.hpp>
#include <boost/math/tools/config.hpp>
+#include <boost/math/tools/mp.hpp>
#include <limits>
-// Sadly we do need the .h versions of these to be sure of getting
-// FLT_MANT_DIG etc.
-#include <limits.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <type_traits>
+#include <cmath>
+#include <cstdint>
+#include <cstddef>
namespace boost{ namespace math{
+namespace mp = tools::meta_programming;
+
namespace tools{
template <class T>
-BOOST_MATH_CONSTEXPR int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT;
+constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept;
template <class T>
-BOOST_MATH_CONSTEXPR T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T);
+constexpr T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value);
}
@@ -116,81 +105,64 @@ namespace policies{
#define BOOST_MATH_MAX_ROOT_ITERATION_POLICY 200
#endif
-#if !defined(__BORLANDC__)
-#define BOOST_MATH_META_INT(type, name, Default)\
- template <type N = Default> struct name : public boost::mpl::int_<N>{};\
- namespace detail{\
- template <type N>\
- char test_is_valid_arg(const name<N>*);\
- char test_is_default_arg(const name<Default>*);\
- template <class T> struct is_##name##_imp\
- {\
- template <type N> static char test(const name<N>*);\
- static double test(...);\
- BOOST_STATIC_CONSTANT(bool, value = sizeof(test(static_cast<T*>(0))) == 1);\
- };\
- }\
- template <class T> struct is_##name : public boost::mpl::bool_< ::boost::math::policies::detail::is_##name##_imp<T>::value>{};
-
-#define BOOST_MATH_META_BOOL(name, Default)\
- template <bool N = Default> struct name : public boost::mpl::bool_<N>{};\
- namespace detail{\
- template <bool N>\
- char test_is_valid_arg(const name<N>*);\
- char test_is_default_arg(const name<Default>*);\
- template <class T> struct is_##name##_imp\
- {\
- template <bool N> static char test(const name<N>*);\
- static double test(...);\
- BOOST_STATIC_CONSTANT(bool, value = sizeof(test(static_cast<T*>(0))) == 1);\
- };\
- }\
- template <class T> struct is_##name : public boost::mpl::bool_< ::boost::math::policies::detail::is_##name##_imp<T>::value>{};
-#else
-#define BOOST_MATH_META_INT(Type, name, Default)\
- template <Type N = Default> struct name : public boost::mpl::int_<N>{};\
- namespace detail{\
- template <Type N>\
- char test_is_valid_arg(const name<N>*);\
- char test_is_default_arg(const name<Default>*);\
- template <class T> struct is_##name##_tester\
- {\
- template <Type N> static char test(const name<N>&);\
- static double test(...);\
- };\
- template <class T> struct is_##name##_imp\
- {\
- static T inst;\
- BOOST_STATIC_CONSTANT(bool, value = sizeof( ::boost::math::policies::detail::is_##name##_tester<T>::test(inst)) == 1);\
- };\
- }\
- template <class T> struct is_##name : public boost::mpl::bool_< ::boost::math::policies::detail::is_##name##_imp<T>::value>\
- {\
- template <class U> struct apply{ typedef is_##name<U> type; };\
+#define BOOST_MATH_META_INT(Type, name, Default) \
+ template <Type N = Default> \
+ class name : public std::integral_constant<int, N>{}; \
+ \
+ namespace detail{ \
+ template <Type N> \
+ char test_is_valid_arg(const name<N>* = nullptr); \
+ char test_is_default_arg(const name<Default>* = nullptr); \
+ \
+ template <typename T> \
+ class is_##name##_imp \
+ { \
+ private: \
+ template <Type N> \
+ static char test(const name<N>* = nullptr); \
+ static double test(...); \
+ public: \
+ static constexpr bool value = sizeof(test(static_cast<T*>(0))) == sizeof(char); \
+ }; \
+ } \
+ \
+ template <typename T> \
+ class is_##name \
+ { \
+ public: \
+ static constexpr bool value = boost::math::policies::detail::is_##name##_imp<T>::value; \
+ using type = std::integral_constant<bool, value>; \
};
-#define BOOST_MATH_META_BOOL(name, Default)\
- template <bool N = Default> struct name : public boost::mpl::bool_<N>{};\
- namespace detail{\
- template <bool N>\
- char test_is_valid_arg(const name<N>*);\
- char test_is_default_arg(const name<Default>*);\
- template <class T> struct is_##name##_tester\
- {\
- template <bool N> static char test(const name<N>&);\
- static double test(...);\
- };\
- template <class T> struct is_##name##_imp\
- {\
- static T inst;\
- BOOST_STATIC_CONSTANT(bool, value = sizeof( ::boost::math::policies::detail::is_##name##_tester<T>::test(inst)) == 1);\
- };\
- }\
- template <class T> struct is_##name : public boost::mpl::bool_< ::boost::math::policies::detail::is_##name##_imp<T>::value>\
- {\
- template <class U> struct apply{ typedef is_##name<U> type; };\
+#define BOOST_MATH_META_BOOL(name, Default) \
+ template <bool N = Default> \
+ class name : public std::integral_constant<bool, N>{}; \
+ \
+ namespace detail{ \
+ template <bool N> \
+ char test_is_valid_arg(const name<N>* = nullptr); \
+ char test_is_default_arg(const name<Default>* = nullptr); \
+ \
+ template <typename T> \
+ class is_##name##_imp \
+ { \
+ private: \
+ template <bool N> \
+ static char test(const name<N>* = nullptr); \
+ static double test(...); \
+ public: \
+ static constexpr bool value = sizeof(test(static_cast<T*>(0))) == sizeof(char); \
+ }; \
+ } \
+ \
+ template <typename T> \
+ class is_##name \
+ { \
+ public: \
+ static constexpr bool value = boost::math::policies::detail::is_##name##_imp<T>::value; \
+ using type = std::integral_constant<bool, value>; \
};
-#endif
+
//
// Begin by defining policy types for error handling:
//
@@ -260,90 +232,73 @@ struct precision
//
// Now work out the precision:
//
- typedef typename mpl::if_c<
+ using digits2_type = typename std::conditional<
(Digits10::value == 0),
digits2<0>,
digits2<((Digits10::value + 1) * 1000L) / 301L>
- >::type digits2_type;
+ >::type;
public:
-#ifdef __BORLANDC__
- typedef typename mpl::if_c<
+#ifdef BOOST_BORLANDC
+ using type = typename std::conditional<
(Digits2::value > ::boost::math::policies::detail::precision<Digits10,Digits2>::digits2_type::value),
- Digits2, digits2_type>::type type;
+ Digits2, digits2_type>::type;
#else
- typedef typename mpl::if_c<
+ using type = typename std::conditional<
(Digits2::value > digits2_type::value),
- Digits2, digits2_type>::type type;
+ Digits2, digits2_type>::type;
#endif
};
-template <class A, class B, bool b>
-struct select_result
-{
- typedef A type;
-};
-template <class A, class B>
-struct select_result<A, B, false>
-{
- typedef typename mpl::deref<B>::type type;
-};
-
-template <class Seq, class Pred, class DefaultType>
-struct find_arg
-{
-private:
- typedef typename mpl::find_if<Seq, Pred>::type iter;
- typedef typename mpl::end<Seq>::type end_type;
-public:
- typedef typename select_result<
- DefaultType, iter,
- ::boost::is_same<iter, end_type>::value>::type type;
-};
-
double test_is_valid_arg(...);
double test_is_default_arg(...);
char test_is_valid_arg(const default_policy*);
char test_is_default_arg(const default_policy*);
-template <class T>
-struct is_valid_policy_imp
+template <typename T>
+class is_valid_policy_imp
{
- BOOST_STATIC_CONSTANT(bool, value = sizeof(::boost::math::policies::detail::test_is_valid_arg(static_cast<T*>(0))) == 1);
+public:
+ static constexpr bool value = sizeof(boost::math::policies::detail::test_is_valid_arg(static_cast<T*>(0))) == sizeof(char);
};
-template <class T>
-struct is_default_policy_imp
+template <typename T>
+class is_valid_policy
{
- BOOST_STATIC_CONSTANT(bool, value = sizeof(::boost::math::policies::detail::test_is_default_arg(static_cast<T*>(0))) == 1);
+public:
+ static constexpr bool value = boost::math::policies::detail::is_valid_policy_imp<T>::value;
};
-template <class T> struct is_valid_policy
-: public mpl::bool_<
- ::boost::math::policies::detail::is_valid_policy_imp<T>::value>
-{};
+template <typename T>
+class is_default_policy_imp
+{
+public:
+ static constexpr bool value = sizeof(boost::math::policies::detail::test_is_default_arg(static_cast<T*>(0))) == sizeof(char);
+};
-template <class T> struct is_default_policy
-: public mpl::bool_<
- ::boost::math::policies::detail::is_default_policy_imp<T>::value>
+template <typename T>
+class is_default_policy
{
- template <class U>
+public:
+ static constexpr bool value = boost::math::policies::detail::is_default_policy_imp<T>::value;
+ using type = std::integral_constant<bool, value>;
+
+ template <typename U>
struct apply
{
- typedef is_default_policy<U> type;
+ using type = is_default_policy<U>;
};
};
-template <class Seq, class T, int N>
+template <class Seq, class T, std::size_t N>
struct append_N
{
- typedef typename mpl::push_back<Seq, T>::type new_seq;
- typedef typename append_N<new_seq, T, N-1>::type type;
+ using type = typename append_N<mp::mp_push_back<Seq, T>, T, N-1>::type;
};
template <class Seq, class T>
struct append_N<Seq, T, 0>
{
- typedef Seq type;
+ using type = Seq;
};
//
@@ -382,192 +337,233 @@ typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_
typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg2 forwarding_arg2;
} // detail
+
//
// Now define the policy type with enough arguments to handle all
// the policies:
//
-template <class A1 = default_policy,
- class A2 = default_policy,
- class A3 = default_policy,
- class A4 = default_policy,
- class A5 = default_policy,
- class A6 = default_policy,
- class A7 = default_policy,
- class A8 = default_policy,
- class A9 = default_policy,
- class A10 = default_policy,
- class A11 = default_policy,
- class A12 = default_policy,
- class A13 = default_policy>
-struct policy
+template <typename A1 = default_policy,
+ typename A2 = default_policy,
+ typename A3 = default_policy,
+ typename A4 = default_policy,
+ typename A5 = default_policy,
+ typename A6 = default_policy,
+ typename A7 = default_policy,
+ typename A8 = default_policy,
+ typename A9 = default_policy,
+ typename A10 = default_policy,
+ typename A11 = default_policy,
+ typename A12 = default_policy,
+ typename A13 = default_policy>
+class policy
{
private:
//
// Validate all our arguments:
//
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A1>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A2>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A3>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A4>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A5>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A6>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A7>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A8>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A9>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A10>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A11>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A12>::value);
- BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A13>::value);
+ static_assert(::boost::math::policies::detail::is_valid_policy<A1>::value, "::boost::math::policies::detail::is_valid_policy<A1>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A2>::value, "::boost::math::policies::detail::is_valid_policy<A2>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A3>::value, "::boost::math::policies::detail::is_valid_policy<A3>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A4>::value, "::boost::math::policies::detail::is_valid_policy<A4>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A5>::value, "::boost::math::policies::detail::is_valid_policy<A5>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A6>::value, "::boost::math::policies::detail::is_valid_policy<A6>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A7>::value, "::boost::math::policies::detail::is_valid_policy<A7>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A8>::value, "::boost::math::policies::detail::is_valid_policy<A8>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A9>::value, "::boost::math::policies::detail::is_valid_policy<A9>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A10>::value, "::boost::math::policies::detail::is_valid_policy<A10>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A11>::value, "::boost::math::policies::detail::is_valid_policy<A11>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A12>::value, "::boost::math::policies::detail::is_valid_policy<A12>::value");
+ static_assert(::boost::math::policies::detail::is_valid_policy<A13>::value, "::boost::math::policies::detail::is_valid_policy<A13>::value");
//
// Typelist of the arguments:
//
- typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
+ using arg_list = mp::mp_list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13>;
+ static constexpr std::size_t arg_list_size = mp::mp_size<arg_list>::value;
+
+ template<typename A, typename B, bool b>
+ struct pick_arg
+ {
+ using type = A;
+ };
+
+ template<typename A, typename B>
+ struct pick_arg<A, B, false>
+ {
+ using type = mp::mp_at<arg_list, B>;
+ };
+
+ template<typename Fn, typename Default>
+ class arg_type
+ {
+ private:
+ using index = mp::mp_find_if_q<arg_list, Fn>;
+ static constexpr bool end = (index::value >= arg_list_size);
+ public:
+ using type = typename pick_arg<Default, index, end>::type;
+ };
+
+ // Work out the base 2 and 10 precisions to calculate the public precision_type:
+ using digits10_type = typename arg_type<mp::mp_quote_trait<is_digits10>, digits10<>>::type;
+ using bits_precision_type = typename arg_type<mp::mp_quote_trait<is_digits2>, digits2<>>::type;
public:
- typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, domain_error<> >::type domain_error_type;
- typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, pole_error<> >::type pole_error_type;
- typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, overflow_error<> >::type overflow_error_type;
- typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, underflow_error<> >::type underflow_error_type;
- typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, denorm_error<> >::type denorm_error_type;
- typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, evaluation_error<> >::type evaluation_error_type;
- typedef typename detail::find_arg<arg_list, is_rounding_error<mpl::_1>, rounding_error<> >::type rounding_error_type;
- typedef typename detail::find_arg<arg_list, is_indeterminate_result_error<mpl::_1>, indeterminate_result_error<> >::type indeterminate_result_error_type;
-private:
- //
- // Now work out the precision:
- //
- typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
- typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, digits2<> >::type bits_precision_type;
-public:
- typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
- //
+
+ // Error Types:
+ using domain_error_type = typename arg_type<mp::mp_quote_trait<is_domain_error>, domain_error<>>::type;
+ using pole_error_type = typename arg_type<mp::mp_quote_trait<is_pole_error>, pole_error<>>::type;
+ using overflow_error_type = typename arg_type<mp::mp_quote_trait<is_overflow_error>, overflow_error<>>::type;
+ using underflow_error_type = typename arg_type<mp::mp_quote_trait<is_underflow_error>, underflow_error<>>::type;
+ using denorm_error_type = typename arg_type<mp::mp_quote_trait<is_denorm_error>, denorm_error<>>::type;
+ using evaluation_error_type = typename arg_type<mp::mp_quote_trait<is_evaluation_error>, evaluation_error<>>::type;
+ using rounding_error_type = typename arg_type<mp::mp_quote_trait<is_rounding_error>, rounding_error<>>::type;
+ using indeterminate_result_error_type = typename arg_type<mp::mp_quote_trait<is_indeterminate_result_error>, indeterminate_result_error<>>::type;
+
+ // Precision:
+ using precision_type = typename detail::precision<digits10_type, bits_precision_type>::type;
+
// Internal promotion:
- //
- typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, promote_float<> >::type promote_float_type;
- typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, promote_double<> >::type promote_double_type;
- //
+ using promote_float_type = typename arg_type<mp::mp_quote_trait<is_promote_float>, promote_float<>>::type;
+ using promote_double_type = typename arg_type<mp::mp_quote_trait<is_promote_double>, promote_double<>>::type;
+
// Discrete quantiles:
- //
- typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, discrete_quantile<> >::type discrete_quantile_type;
- //
+ using discrete_quantile_type = typename arg_type<mp::mp_quote_trait<is_discrete_quantile>, discrete_quantile<>>::type;
+
// Mathematically undefined properties:
- //
- typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, assert_undefined<> >::type assert_undefined_type;
- //
+ using assert_undefined_type = typename arg_type<mp::mp_quote_trait<is_assert_undefined>, assert_undefined<>>::type;
+
// Max iterations:
- //
- typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, max_series_iterations<> >::type max_series_iterations_type;
- typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, max_root_iterations<> >::type max_root_iterations_type;
+ using max_series_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_series_iterations>, max_series_iterations<>>::type;
+ using max_root_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_root_iterations>, max_root_iterations<>>::type;
};
+
//
// These full specializations are defined to reduce the amount of
// template instantiations that have to take place when using the default
// policies, they have quite a large impact on compile times:
//
template <>
-struct policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
+class policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
{
public:
- typedef domain_error<> domain_error_type;
- typedef pole_error<> pole_error_type;
- typedef overflow_error<> overflow_error_type;
- typedef underflow_error<> underflow_error_type;
- typedef denorm_error<> denorm_error_type;
- typedef evaluation_error<> evaluation_error_type;
- typedef rounding_error<> rounding_error_type;
- typedef indeterminate_result_error<> indeterminate_result_error_type;
+ using domain_error_type = domain_error<>;
+ using pole_error_type = pole_error<>;
+ using overflow_error_type = overflow_error<>;
+ using underflow_error_type = underflow_error<>;
+ using denorm_error_type = denorm_error<>;
+ using evaluation_error_type = evaluation_error<>;
+ using rounding_error_type = rounding_error<>;
+ using indeterminate_result_error_type = indeterminate_result_error<>;
#if BOOST_MATH_DIGITS10_POLICY == 0
- typedef digits2<> precision_type;
+ using precision_type = digits2<>;
#else
- typedef detail::precision<digits10<>, digits2<> >::type precision_type;
+ using precision_type = detail::precision<digits10<>, digits2<>>::type;
#endif
- typedef promote_float<> promote_float_type;
- typedef promote_double<> promote_double_type;
- typedef discrete_quantile<> discrete_quantile_type;
- typedef assert_undefined<> assert_undefined_type;
- typedef max_series_iterations<> max_series_iterations_type;
- typedef max_root_iterations<> max_root_iterations_type;
+ using promote_float_type = promote_float<>;
+ using promote_double_type = promote_double<>;
+ using discrete_quantile_type = discrete_quantile<>;
+ using assert_undefined_type = assert_undefined<>;
+ using max_series_iterations_type = max_series_iterations<>;
+ using max_root_iterations_type = max_root_iterations<>;
};
template <>
struct policy<detail::forwarding_arg1, detail::forwarding_arg2, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
{
public:
- typedef domain_error<> domain_error_type;
- typedef pole_error<> pole_error_type;
- typedef overflow_error<> overflow_error_type;
- typedef underflow_error<> underflow_error_type;
- typedef denorm_error<> denorm_error_type;
- typedef evaluation_error<> evaluation_error_type;
- typedef rounding_error<> rounding_error_type;
- typedef indeterminate_result_error<> indeterminate_result_error_type;
+ using domain_error_type = domain_error<>;
+ using pole_error_type = pole_error<>;
+ using overflow_error_type = overflow_error<>;
+ using underflow_error_type = underflow_error<>;
+ using denorm_error_type = denorm_error<>;
+ using evaluation_error_type = evaluation_error<>;
+ using rounding_error_type = rounding_error<>;
+ using indeterminate_result_error_type = indeterminate_result_error<>;
#if BOOST_MATH_DIGITS10_POLICY == 0
- typedef digits2<> precision_type;
+ using precision_type = digits2<>;
#else
- typedef detail::precision<digits10<>, digits2<> >::type precision_type;
+ using precision_type = detail::precision<digits10<>, digits2<>>::type;
#endif
- typedef promote_float<false> promote_float_type;
- typedef promote_double<false> promote_double_type;
- typedef discrete_quantile<> discrete_quantile_type;
- typedef assert_undefined<> assert_undefined_type;
- typedef max_series_iterations<> max_series_iterations_type;
- typedef max_root_iterations<> max_root_iterations_type;
-};
-
-template <class Policy,
- class A1 = default_policy,
- class A2 = default_policy,
- class A3 = default_policy,
- class A4 = default_policy,
- class A5 = default_policy,
- class A6 = default_policy,
- class A7 = default_policy,
- class A8 = default_policy,
- class A9 = default_policy,
- class A10 = default_policy,
- class A11 = default_policy,
- class A12 = default_policy,
- class A13 = default_policy>
-struct normalise
+ using promote_float_type = promote_float<false>;
+ using promote_double_type = promote_double<false>;
+ using discrete_quantile_type = discrete_quantile<>;
+ using assert_undefined_type = assert_undefined<>;
+ using max_series_iterations_type = max_series_iterations<>;
+ using max_root_iterations_type = max_root_iterations<>;
+};
+
+template <typename Policy,
+ typename A1 = default_policy,
+ typename A2 = default_policy,
+ typename A3 = default_policy,
+ typename A4 = default_policy,
+ typename A5 = default_policy,
+ typename A6 = default_policy,
+ typename A7 = default_policy,
+ typename A8 = default_policy,
+ typename A9 = default_policy,
+ typename A10 = default_policy,
+ typename A11 = default_policy,
+ typename A12 = default_policy,
+ typename A13 = default_policy>
+class normalise
{
private:
- typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
- typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, typename Policy::domain_error_type >::type domain_error_type;
- typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, typename Policy::pole_error_type >::type pole_error_type;
- typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, typename Policy::overflow_error_type >::type overflow_error_type;
- typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, typename Policy::underflow_error_type >::type underflow_error_type;
- typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, typename Policy::denorm_error_type >::type denorm_error_type;
- typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, typename Policy::evaluation_error_type >::type evaluation_error_type;
- typedef typename detail::find_arg<arg_list, is_rounding_error<mpl::_1>, typename Policy::rounding_error_type >::type rounding_error_type;
- typedef typename detail::find_arg<arg_list, is_indeterminate_result_error<mpl::_1>, typename Policy::indeterminate_result_error_type >::type indeterminate_result_error_type;
- //
- // Now work out the precision:
- //
- typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
- typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, typename Policy::precision_type >::type bits_precision_type;
- typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
- //
+ using arg_list = mp::mp_list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13>;
+ static constexpr std::size_t arg_list_size = mp::mp_size<arg_list>::value;
+
+ template<typename A, typename B, bool b>
+ struct pick_arg
+ {
+ using type = A;
+ };
+
+ template<typename A, typename B>
+ struct pick_arg<A, B, false>
+ {
+ using type = mp::mp_at<arg_list, B>;
+ };
+
+ template<typename Fn, typename Default>
+ class arg_type
+ {
+ private:
+ using index = mp::mp_find_if_q<arg_list, Fn>;
+ static constexpr bool end = (index::value >= arg_list_size);
+ public:
+ using type = typename pick_arg<Default, index, end>::type;
+ };
+
+ // Error types:
+ using domain_error_type = typename arg_type<mp::mp_quote_trait<is_domain_error>, typename Policy::domain_error_type>::type;
+ using pole_error_type = typename arg_type<mp::mp_quote_trait<is_pole_error>, typename Policy::pole_error_type>::type;
+ using overflow_error_type = typename arg_type<mp::mp_quote_trait<is_overflow_error>, typename Policy::overflow_error_type>::type;
+ using underflow_error_type = typename arg_type<mp::mp_quote_trait<is_underflow_error>, typename Policy::underflow_error_type>::type;
+ using denorm_error_type = typename arg_type<mp::mp_quote_trait<is_denorm_error>, typename Policy::denorm_error_type>::type;
+ using evaluation_error_type = typename arg_type<mp::mp_quote_trait<is_evaluation_error>, typename Policy::evaluation_error_type>::type;
+ using rounding_error_type = typename arg_type<mp::mp_quote_trait<is_rounding_error>, typename Policy::rounding_error_type>::type;
+ using indeterminate_result_error_type = typename arg_type<mp::mp_quote_trait<is_indeterminate_result_error>, typename Policy::indeterminate_result_error_type>::type;
+
+ // Precision:
+ using digits10_type = typename arg_type<mp::mp_quote_trait<is_digits10>, digits10<>>::type;
+ using bits_precision_type = typename arg_type<mp::mp_quote_trait<is_digits2>, typename Policy::precision_type>::type;
+ using precision_type = typename detail::precision<digits10_type, bits_precision_type>::type;
+
// Internal promotion:
- //
- typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, typename Policy::promote_float_type >::type promote_float_type;
- typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, typename Policy::promote_double_type >::type promote_double_type;
- //
+ using promote_float_type = typename arg_type<mp::mp_quote_trait<is_promote_float>, typename Policy::promote_float_type>::type;
+ using promote_double_type = typename arg_type<mp::mp_quote_trait<is_promote_double>, typename Policy::promote_double_type>::type;
+
// Discrete quantiles:
- //
- typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, typename Policy::discrete_quantile_type >::type discrete_quantile_type;
- //
+ using discrete_quantile_type = typename arg_type<mp::mp_quote_trait<is_discrete_quantile>, typename Policy::discrete_quantile_type>::type;
+
// Mathematically undefined properties:
- //
- typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, typename Policy::assert_undefined_type >::type assert_undefined_type;
- //
+ using assert_undefined_type = typename arg_type<mp::mp_quote_trait<is_assert_undefined>, typename Policy::assert_undefined_type>::type;
+
// Max iterations:
- //
- typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, typename Policy::max_series_iterations_type>::type max_series_iterations_type;
- typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, typename Policy::max_root_iterations_type>::type max_root_iterations_type;
- //
+ using max_series_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_series_iterations>, typename Policy::max_series_iterations_type>::type;
+ using max_root_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_root_iterations>, typename Policy::max_root_iterations_type>::type;
+
// Define a typelist of the policies:
- //
- typedef mpl::vector<
+ using result_list = mp::mp_list<
domain_error_type,
pole_error_type,
overflow_error_type,
@@ -582,34 +578,34 @@ private:
discrete_quantile_type,
assert_undefined_type,
max_series_iterations_type,
- max_root_iterations_type> result_list;
- //
+ max_root_iterations_type>;
+
// Remove all the policies that are the same as the default:
- //
- typedef typename mpl::remove_if<result_list, detail::is_default_policy<mpl::_> >::type reduced_list;
- //
+ using fn = mp::mp_quote_trait<detail::is_default_policy>;
+ using reduced_list = mp::mp_remove_if_q<result_list, fn>;
+
// Pad out the list with defaults:
- //
- typedef typename detail::append_N<reduced_list, default_policy, (14 - ::boost::mpl::size<reduced_list>::value)>::type result_type;
+ using result_type = typename detail::append_N<reduced_list, default_policy, (14UL - mp::mp_size<reduced_list>::value)>::type;
+
public:
- typedef policy<
- typename mpl::at<result_type, mpl::int_<0> >::type,
- typename mpl::at<result_type, mpl::int_<1> >::type,
- typename mpl::at<result_type, mpl::int_<2> >::type,
- typename mpl::at<result_type, mpl::int_<3> >::type,
- typename mpl::at<result_type, mpl::int_<4> >::type,
- typename mpl::at<result_type, mpl::int_<5> >::type,
- typename mpl::at<result_type, mpl::int_<6> >::type,
- typename mpl::at<result_type, mpl::int_<7> >::type,
- typename mpl::at<result_type, mpl::int_<8> >::type,
- typename mpl::at<result_type, mpl::int_<9> >::type,
- typename mpl::at<result_type, mpl::int_<10> >::type,
- typename mpl::at<result_type, mpl::int_<11> >::type,
- typename mpl::at<result_type, mpl::int_<12> >::type > type;
+ using type = policy<
+ mp::mp_at_c<result_type, 0>,
+ mp::mp_at_c<result_type, 1>,
+ mp::mp_at_c<result_type, 2>,
+ mp::mp_at_c<result_type, 3>,
+ mp::mp_at_c<result_type, 4>,
+ mp::mp_at_c<result_type, 5>,
+ mp::mp_at_c<result_type, 6>,
+ mp::mp_at_c<result_type, 7>,
+ mp::mp_at_c<result_type, 8>,
+ mp::mp_at_c<result_type, 9>,
+ mp::mp_at_c<result_type, 10>,
+ mp::mp_at_c<result_type, 11>,
+ mp::mp_at_c<result_type, 12>
+ >;
};
-//
+
// Full specialisation to speed up compilation of the common case:
-//
template <>
struct normalise<policy<>,
promote_float<false>,
@@ -624,7 +620,7 @@ struct normalise<policy<>,
default_policy,
default_policy>
{
- typedef policy<detail::forwarding_arg1, detail::forwarding_arg2> type;
+ using type = policy<detail::forwarding_arg1, detail::forwarding_arg2>;
};
template <>
@@ -641,84 +637,84 @@ struct normalise<policy<detail::forwarding_arg1, detail::forwarding_arg2>,
default_policy,
default_policy>
{
- typedef policy<detail::forwarding_arg1, detail::forwarding_arg2> type;
+ using type = policy<detail::forwarding_arg1, detail::forwarding_arg2>;
};
-inline BOOST_MATH_CONSTEXPR policy<> make_policy() BOOST_NOEXCEPT
+inline constexpr policy<> make_policy() noexcept
{ return policy<>(); }
template <class A1>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1>::type make_policy(const A1&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1>::type make_policy(const A1&) noexcept
{
typedef typename normalise<policy<>, A1>::type result_type;
return result_type();
}
template <class A1, class A2>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2>::type make_policy(const A1&, const A2&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2>::type make_policy(const A1&, const A2&) noexcept
{
typedef typename normalise<policy<>, A1, A2>::type result_type;
return result_type();
}
template <class A1, class A2, class A3>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&) noexcept
{
typedef typename normalise<policy<>, A1, A2, A3>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&) noexcept
{
typedef typename normalise<policy<>, A1, A2, A3, A4>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4, A5>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&) noexcept
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&) noexcept
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&) noexcept
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&) noexcept
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&) noexcept
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&) noexcept
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type result_type;
return result_type();
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>
-inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&, const A11&) BOOST_NOEXCEPT
+inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&, const A11&) noexcept
{
typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type result_type;
return result_type();
@@ -736,110 +732,60 @@ struct evaluation
template <class Policy>
struct evaluation<float, Policy>
{
- typedef typename mpl::if_<typename Policy::promote_float_type, double, float>::type type;
+ using type = typename std::conditional<Policy::promote_float_type::value, double, float>::type;
};
template <class Policy>
struct evaluation<double, Policy>
{
- typedef typename mpl::if_<typename Policy::promote_double_type, long double, double>::type type;
+ using type = typename std::conditional<Policy::promote_double_type::value, long double, double>::type;
};
-#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
-
-template <class Real>
-struct basic_digits : public mpl::int_<0>{ };
-template <>
-struct basic_digits<float> : public mpl::int_<FLT_MANT_DIG>{ };
-template <>
-struct basic_digits<double> : public mpl::int_<DBL_MANT_DIG>{ };
-template <>
-struct basic_digits<long double> : public mpl::int_<LDBL_MANT_DIG>{ };
-
template <class Real, class Policy>
struct precision
{
- BOOST_STATIC_ASSERT( ::std::numeric_limits<Real>::radix == 2);
- typedef typename Policy::precision_type precision_type;
- typedef basic_digits<Real> digits_t;
- typedef typename mpl::if_<
- mpl::equal_to<digits_t, mpl::int_<0> >,
+ static_assert((std::numeric_limits<Real>::radix == 2) || ((std::numeric_limits<Real>::is_specialized == 0) || (std::numeric_limits<Real>::digits == 0)),
+ "(std::numeric_limits<Real>::radix == 2) || ((std::numeric_limits<Real>::is_specialized == 0) || (std::numeric_limits<Real>::digits == 0))");
+#ifndef BOOST_BORLANDC
+ using precision_type = typename Policy::precision_type;
+ using type = typename std::conditional<
+ ((std::numeric_limits<Real>::is_specialized == 0) || (std::numeric_limits<Real>::digits == 0)),
// Possibly unknown precision:
precision_type,
- typename mpl::if_<
- mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, mpl::int_<0> > >,
- // Default case, full precision for RealType:
- digits2< ::std::numeric_limits<Real>::digits>,
- // User customised precision:
- precision_type
- >::type
- >::type type;
-};
-
-template <class Policy>
-struct precision<float, Policy>
-{
- typedef digits2<FLT_MANT_DIG> type;
-};
-template <class Policy>
-struct precision<double, Policy>
-{
- typedef digits2<DBL_MANT_DIG> type;
-};
-template <class Policy>
-struct precision<long double, Policy>
-{
- typedef digits2<LDBL_MANT_DIG> type;
-};
-
-#else
-
-template <class Real, class Policy>
-struct precision
-{
- BOOST_STATIC_ASSERT((::std::numeric_limits<Real>::radix == 2) || ((::std::numeric_limits<Real>::is_specialized == 0) || (::std::numeric_limits<Real>::digits == 0)));
-#ifndef __BORLANDC__
- typedef typename Policy::precision_type precision_type;
- typedef typename mpl::if_c<
- ((::std::numeric_limits<Real>::is_specialized == 0) || (::std::numeric_limits<Real>::digits == 0)),
- // Possibly unknown precision:
- precision_type,
- typename mpl::if_c<
- ((::std::numeric_limits<Real>::digits <= precision_type::value)
+ typename std::conditional<
+ ((std::numeric_limits<Real>::digits <= precision_type::value)
|| (Policy::precision_type::value <= 0)),
// Default case, full precision for RealType:
- digits2< ::std::numeric_limits<Real>::digits>,
+ digits2< std::numeric_limits<Real>::digits>,
// User customised precision:
precision_type
>::type
- >::type type;
+ >::type;
#else
- typedef typename Policy::precision_type precision_type;
- typedef mpl::int_< ::std::numeric_limits<Real>::digits> digits_t;
- typedef mpl::bool_< ::std::numeric_limits<Real>::is_specialized> spec_t;
- typedef typename mpl::if_<
- mpl::or_<mpl::equal_to<spec_t, mpl::false_>, mpl::equal_to<digits_t, mpl::int_<0> > >,
+ using precision_type = typename Policy::precision_type;
+ using digits_t = std::integral_constant<int, std::numeric_limits<Real>::digits>;
+ using spec_t = std::integral_constant<bool, std::numeric_limits<Real>::is_specialized>;
+ using type = typename std::conditional<
+ (spec_t::value == true std::true_type || digits_t::value == 0),
// Possibly unknown precision:
precision_type,
- typename mpl::if_<
- mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, mpl::int_<0> > >,
+ typename std::conditional<
+ (digits_t::value <= precision_type::value || precision_type::value <= 0),
// Default case, full precision for RealType:
- digits2< ::std::numeric_limits<Real>::digits>,
+ digits2< std::numeric_limits<Real>::digits>,
// User customised precision:
precision_type
>::type
- >::type type;
+ >::type;
#endif
};
-#endif
-
#ifdef BOOST_MATH_USE_FLOAT128
template <class Policy>
struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>
{
- typedef mpl::int_<113> type;
+ typedef std::integral_constant<int, 113> type;
};
#endif
@@ -847,19 +793,15 @@ struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>
namespace detail{
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR int digits_imp(mpl::true_ const&) BOOST_NOEXCEPT
+inline constexpr int digits_imp(std::true_type const&) noexcept
{
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
-#else
- BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
-#endif
+ static_assert( std::numeric_limits<T>::is_specialized, "std::numeric_limits<T>::is_specialized");
typedef typename boost::math::policies::precision<T, Policy>::type p_t;
return p_t::value;
}
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR int digits_imp(mpl::false_ const&) BOOST_NOEXCEPT
+inline constexpr int digits_imp(std::false_type const&) noexcept
{
return tools::digits<T>();
}
@@ -867,26 +809,26 @@ inline BOOST_MATH_CONSTEXPR int digits_imp(mpl::false_ const&) BOOST_NOEXCEPT
} // namespace detail
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT
+inline constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept
{
- typedef mpl::bool_< std::numeric_limits<T>::is_specialized > tag_type;
+ typedef std::integral_constant<bool, std::numeric_limits<T>::is_specialized > tag_type;
return detail::digits_imp<T, Policy>(tag_type());
}
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR int digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT
+inline constexpr int digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept
{
return boost::math::policies::digits<T, Policy>() * 301 / 1000L;
}
template <class Policy>
-inline BOOST_MATH_CONSTEXPR unsigned long get_max_series_iterations() BOOST_NOEXCEPT
+inline constexpr unsigned long get_max_series_iterations() noexcept
{
typedef typename Policy::max_series_iterations_type iter_type;
return iter_type::value;
}
template <class Policy>
-inline BOOST_MATH_CONSTEXPR unsigned long get_max_root_iterations() BOOST_NOEXCEPT
+inline constexpr unsigned long get_max_root_iterations() noexcept
{
typedef typename Policy::max_root_iterations_type iter_type;
return iter_type::value;
@@ -897,55 +839,51 @@ namespace detail{
template <class T, class Digits, class Small, class Default>
struct series_factor_calc
{
- static T get() BOOST_MATH_NOEXCEPT(T)
+ static T get() noexcept(std::is_floating_point<T>::value)
{
return ldexp(T(1.0), 1 - Digits::value);
}
};
template <class T, class Digits>
-struct series_factor_calc<T, Digits, mpl::true_, mpl::true_>
+struct series_factor_calc<T, Digits, std::true_type, std::true_type>
{
- static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
+ static constexpr T get() noexcept(std::is_floating_point<T>::value)
{
return boost::math::tools::epsilon<T>();
}
};
template <class T, class Digits>
-struct series_factor_calc<T, Digits, mpl::true_, mpl::false_>
+struct series_factor_calc<T, Digits, std::true_type, std::false_type>
{
- static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
+ static constexpr T get() noexcept(std::is_floating_point<T>::value)
{
- return 1 / static_cast<T>(static_cast<boost::uintmax_t>(1u) << (Digits::value - 1));
+ return 1 / static_cast<T>(static_cast<std::uintmax_t>(1u) << (Digits::value - 1));
}
};
template <class T, class Digits>
-struct series_factor_calc<T, Digits, mpl::false_, mpl::true_>
+struct series_factor_calc<T, Digits, std::false_type, std::true_type>
{
- static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
+ static constexpr T get() noexcept(std::is_floating_point<T>::value)
{
return boost::math::tools::epsilon<T>();
}
};
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T get_epsilon_imp(mpl::true_ const&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T get_epsilon_imp(std::true_type const&) noexcept(std::is_floating_point<T>::value)
{
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
- BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::radix == 2);
-#else
- BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
- BOOST_ASSERT(::std::numeric_limits<T>::radix == 2);
-#endif
+ static_assert(std::numeric_limits<T>::is_specialized, "std::numeric_limits<T>::is_specialized");
+ static_assert(std::numeric_limits<T>::radix == 2, "std::numeric_limits<T>::radix == 2");
+
typedef typename boost::math::policies::precision<T, Policy>::type p_t;
- typedef mpl::bool_<p_t::value <= std::numeric_limits<boost::uintmax_t>::digits> is_small_int;
- typedef mpl::bool_<p_t::value >= std::numeric_limits<T>::digits> is_default_value;
+ typedef std::integral_constant<bool, p_t::value <= std::numeric_limits<std::uintmax_t>::digits> is_small_int;
+ typedef std::integral_constant<bool, p_t::value >= std::numeric_limits<T>::digits> is_default_value;
return series_factor_calc<T, p_t, is_small_int, is_default_value>::get();
}
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T get_epsilon_imp(mpl::false_ const&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T get_epsilon_imp(std::false_type const&) noexcept(std::is_floating_point<T>::value)
{
return tools::epsilon<T>();
}
@@ -953,9 +891,9 @@ inline BOOST_MATH_CONSTEXPR T get_epsilon_imp(mpl::false_ const&) BOOST_MATH_NOE
} // namespace detail
template <class T, class Policy>
-inline BOOST_MATH_CONSTEXPR T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
- typedef mpl::bool_< (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2)) > tag_type;
+ typedef std::integral_constant<bool, (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2)) > tag_type;
return detail::get_epsilon_imp<T, Policy>(tag_type());
}
@@ -975,16 +913,22 @@ template <class A1,
char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
double test_is_policy(...);
-template <class P>
-struct is_policy_imp
+template <typename P>
+class is_policy_imp
{
- BOOST_STATIC_CONSTANT(bool, value = (sizeof(::boost::math::policies::detail::test_is_policy(static_cast<P*>(0))) == 1));
+public:
+ static constexpr bool value = (sizeof(::boost::math::policies::detail::test_is_policy(static_cast<P*>(0))) == sizeof(char));
};
}
-template <class P>
-struct is_policy : public mpl::bool_< ::boost::math::policies::detail::is_policy_imp<P>::value> {};
+template <typename P>
+class is_policy
+{
+public:
+ static constexpr bool value = boost::math::policies::detail::is_policy_imp<P>::value;
+ using type = std::integral_constant<bool, value>;
+};
//
// Helper traits class for distribution error handling:
@@ -992,21 +936,21 @@ struct is_policy : public mpl::bool_< ::boost::math::policies::detail::is_policy
template <class Policy>
struct constructor_error_check
{
- typedef typename Policy::domain_error_type domain_error_type;
- typedef typename mpl::if_c<
+ using domain_error_type = typename Policy::domain_error_type;
+ using type = typename std::conditional<
(domain_error_type::value == throw_on_error) || (domain_error_type::value == user_error) || (domain_error_type::value == errno_on_error),
- mpl::true_,
- mpl::false_>::type type;
+ std::true_type,
+ std::false_type>::type;
};
template <class Policy>
struct method_error_check
{
- typedef typename Policy::domain_error_type domain_error_type;
- typedef typename mpl::if_c<
+ using domain_error_type = typename Policy::domain_error_type;
+ using type = typename std::conditional<
(domain_error_type::value == throw_on_error) && (domain_error_type::value != user_error),
- mpl::false_,
- mpl::true_>::type type;
+ std::false_type,
+ std::true_type>::type;
};
//
// Does the Policy ever throw on error?
@@ -1023,7 +967,7 @@ struct is_noexcept_error_policy
typedef typename Policy::rounding_error_type t7;
typedef typename Policy::indeterminate_result_error_type t8;
- BOOST_STATIC_CONSTANT(bool, value =
+ static constexpr bool value =
((t1::value != throw_on_error) && (t1::value != user_error)
&& (t2::value != throw_on_error) && (t2::value != user_error)
&& (t3::value != throw_on_error) && (t3::value != user_error)
@@ -1031,7 +975,7 @@ struct is_noexcept_error_policy
&& (t5::value != throw_on_error) && (t5::value != user_error)
&& (t6::value != throw_on_error) && (t6::value != user_error)
&& (t7::value != throw_on_error) && (t7::value != user_error)
- && (t8::value != throw_on_error) && (t8::value != user_error)));
+ && (t8::value != throw_on_error) && (t8::value != user_error));
};
}}} // namespaces
diff --git a/contrib/restricted/boost/math/include/boost/math/special_functions/detail/fp_traits.hpp b/contrib/restricted/boost/math/include/boost/math/special_functions/detail/fp_traits.hpp
index c957022223..ee98bc51fc 100644
--- a/contrib/restricted/boost/math/include/boost/math/special_functions/detail/fp_traits.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/special_functions/detail/fp_traits.hpp
@@ -21,12 +21,46 @@ With these techniques, the code could be simplified.
#endif
#include <cstring>
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+#include <boost/math/tools/is_standalone.hpp>
+#include <boost/math/tools/assert.hpp>
-#include <boost/assert.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/detail/endian.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/type_traits/is_floating_point.hpp>
+// Determine endianness
+#ifndef BOOST_MATH_STANDALONE
+
+#include <boost/predef/other/endian.h>
+#define BOOST_MATH_ENDIAN_BIG_BYTE BOOST_ENDIAN_BIG_BYTE
+#define BOOST_MATH_ENDIAN_LITTLE_BYTE BOOST_ENDIAN_LITTLE_BYTE
+
+#elif (__cplusplus >= 202002L || _MSVC_LANG >= 202002L)
+
+#if __has_include(<bit>)
+#include <bit>
+#define BOOST_MATH_ENDIAN_BIG_BYTE (std::endian::native == std::endian::big)
+#define BOOST_MATH_ENDIAN_LITTLE_BYTE (std::endian::native == std::endian::little)
+#else
+#error Missing <bit> header. Please disable standalone mode, and file an issue at https://github.com/boostorg/math
+#endif
+
+#elif defined(_WIN32)
+
+#define BOOST_MATH_ENDIAN_BIG_BYTE 0
+#define BOOST_MATH_ENDIAN_LITTLE_BYTE 1
+
+#elif defined(__BYTE_ORDER__)
+
+#define BOOST_MATH_ENDIAN_BIG_BYTE (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define BOOST_MATH_ENDIAN_LITTLE_BYTE (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+
+#else
+#error Could not determine endian type. Please disable standalone mode, and file an issue at https://github.com/boostorg/math
+#endif // Determine endianness
+
+static_assert((BOOST_MATH_ENDIAN_BIG_BYTE || BOOST_MATH_ENDIAN_LITTLE_BYTE)
+ && !(BOOST_MATH_ENDIAN_BIG_BYTE && BOOST_MATH_ENDIAN_LITTLE_BYTE),
+ "Inconsistent endianness detected. Please disable standalone mode, and file an issue at https://github.com/boostorg/math");
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{ using ::memcpy; }
@@ -51,9 +85,9 @@ With these techniques, the code could be simplified.
&& (_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC != 0))
# ifdef _STLP_VENDOR_CSTD
# if _STLPORT_VERSION >= 0x520
-# define BOOST_FPCLASSIFY_PREFIX ::__std_alias::
+# define BOOST_FPCLASSIFY_PREFIX ::__std_alias::
# else
-# define BOOST_FPCLASSIFY_PREFIX ::_STLP_VENDOR_CSTD::
+# define BOOST_FPCLASSIFY_PREFIX ::_STLP_VENDOR_CSTD::
# endif
# else
# define BOOST_FPCLASSIFY_PREFIX ::std::
@@ -84,7 +118,7 @@ namespace detail {
//------------------------------------------------------------------------------
-/*
+/*
The following classes are used to tag the different methods that are used
for floating point classification
*/
@@ -178,10 +212,10 @@ template<> struct fp_traits_non_native<float, single_precision>
{
typedef ieee_copy_all_bits_tag method;
- BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
- BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7f800000);
- BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
- BOOST_STATIC_CONSTANT(uint32_t, significand = 0x007fffff);
+ static constexpr uint32_t sign = 0x80000000u;
+ static constexpr uint32_t exponent = 0x7f800000;
+ static constexpr uint32_t flag = 0x00000000;
+ static constexpr uint32_t significand = 0x007fffff;
typedef uint32_t bits;
static void get_bits(float x, uint32_t& a) { std::memcpy(&a, &x, 4); }
@@ -191,16 +225,16 @@ template<> struct fp_traits_non_native<float, single_precision>
// ieee_tag version, double (64 bits) ----------------------------------------------
#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) \
- || defined(__BORLANDC__) || defined(__CODEGEAR__)
+ || defined(BOOST_BORLANDC) || defined(__CODEGEAR__)
template<> struct fp_traits_non_native<double, double_precision>
{
typedef ieee_copy_leading_bits_tag method;
- BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
- BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
- BOOST_STATIC_CONSTANT(uint32_t, flag = 0);
- BOOST_STATIC_CONSTANT(uint32_t, significand = 0x000fffff);
+ static constexpr uint32_t sign = 0x80000000u;
+ static constexpr uint32_t exponent = 0x7ff00000;
+ static constexpr uint32_t flag = 0;
+ static constexpr uint32_t significand = 0x000fffff;
typedef uint32_t bits;
@@ -215,14 +249,7 @@ template<> struct fp_traits_non_native<double, double_precision>
}
private:
-
-#if defined(BOOST_BIG_ENDIAN)
- BOOST_STATIC_CONSTANT(int, offset_ = 0);
-#elif defined(BOOST_LITTLE_ENDIAN)
- BOOST_STATIC_CONSTANT(int, offset_ = 4);
-#else
- BOOST_STATIC_ASSERT(false);
-#endif
+ static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 4;
};
//..............................................................................
@@ -233,11 +260,11 @@ template<> struct fp_traits_non_native<double, double_precision>
{
typedef ieee_copy_all_bits_tag method;
- static const uint64_t sign = ((uint64_t)0x80000000u) << 32;
- static const uint64_t exponent = ((uint64_t)0x7ff00000) << 32;
- static const uint64_t flag = 0;
- static const uint64_t significand
- = (((uint64_t)0x000fffff) << 32) + ((uint64_t)0xffffffffu);
+ static constexpr uint64_t sign = static_cast<uint64_t>(0x80000000u) << 32;
+ static constexpr uint64_t exponent = static_cast<uint64_t>(0x7ff00000) << 32;
+ static constexpr uint64_t flag = 0;
+ static constexpr uint64_t significand
+ = (static_cast<uint64_t>(0x000fffff) << 32) + static_cast<uint64_t>(0xffffffffu);
typedef uint64_t bits;
static void get_bits(double x, uint64_t& a) { std::memcpy(&a, &x, 8); }
@@ -251,16 +278,16 @@ template<> struct fp_traits_non_native<double, double_precision>
// long double (64 bits) -------------------------------------------------------
#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)\
- || defined(__BORLANDC__) || defined(__CODEGEAR__)
+ || defined(BOOST_BORLANDC) || defined(__CODEGEAR__)
template<> struct fp_traits_non_native<long double, double_precision>
{
typedef ieee_copy_leading_bits_tag method;
- BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
- BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
- BOOST_STATIC_CONSTANT(uint32_t, flag = 0);
- BOOST_STATIC_CONSTANT(uint32_t, significand = 0x000fffff);
+ static constexpr uint32_t sign = 0x80000000u;
+ static constexpr uint32_t exponent = 0x7ff00000;
+ static constexpr uint32_t flag = 0;
+ static constexpr uint32_t significand = 0x000fffff;
typedef uint32_t bits;
@@ -275,14 +302,7 @@ template<> struct fp_traits_non_native<long double, double_precision>
}
private:
-
-#if defined(BOOST_BIG_ENDIAN)
- BOOST_STATIC_CONSTANT(int, offset_ = 0);
-#elif defined(BOOST_LITTLE_ENDIAN)
- BOOST_STATIC_CONSTANT(int, offset_ = 4);
-#else
- BOOST_STATIC_ASSERT(false);
-#endif
+ static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 4;
};
//..............................................................................
@@ -293,11 +313,11 @@ template<> struct fp_traits_non_native<long double, double_precision>
{
typedef ieee_copy_all_bits_tag method;
- static const uint64_t sign = (uint64_t)0x80000000u << 32;
- static const uint64_t exponent = (uint64_t)0x7ff00000 << 32;
+ static const uint64_t sign = static_cast<uint64_t>(0x80000000u) << 32;
+ static const uint64_t exponent = static_cast<uint64_t>(0x7ff00000) << 32;
static const uint64_t flag = 0;
static const uint64_t significand
- = ((uint64_t)0x000fffff << 32) + (uint64_t)0xffffffffu;
+ = (static_cast<uint64_t>(0x000fffff) << 32) + static_cast<uint64_t>(0xffffffffu);
typedef uint64_t bits;
static void get_bits(long double x, uint64_t& a) { std::memcpy(&a, &x, 8); }
@@ -320,10 +340,10 @@ struct fp_traits_non_native<long double, extended_double_precision>
{
typedef ieee_copy_leading_bits_tag method;
- BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
- BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
- BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000);
- BOOST_STATIC_CONSTANT(uint32_t, significand = 0x00007fff);
+ static constexpr uint32_t sign = 0x80000000u;
+ static constexpr uint32_t exponent = 0x7fff0000;
+ static constexpr uint32_t flag = 0x00008000;
+ static constexpr uint32_t significand = 0x00007fff;
typedef uint32_t bits;
@@ -371,10 +391,10 @@ struct fp_traits_non_native<long double, extended_double_precision>
{
typedef ieee_copy_leading_bits_tag method;
- BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
- BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
- BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
- BOOST_STATIC_CONSTANT(uint32_t, significand = 0x000fffff);
+ static constexpr uint32_t sign = 0x80000000u;
+ static constexpr uint32_t exponent = 0x7ff00000;
+ static constexpr uint32_t flag = 0x00000000;
+ static constexpr uint32_t significand = 0x000fffff;
typedef uint32_t bits;
@@ -389,14 +409,7 @@ struct fp_traits_non_native<long double, extended_double_precision>
}
private:
-
-#if defined(BOOST_BIG_ENDIAN)
- BOOST_STATIC_CONSTANT(int, offset_ = 0);
-#elif defined(BOOST_LITTLE_ENDIAN)
- BOOST_STATIC_CONSTANT(int, offset_ = 12);
-#else
- BOOST_STATIC_ASSERT(false);
-#endif
+ static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 12;
};
@@ -416,10 +429,10 @@ struct fp_traits_non_native<long double, extended_double_precision>
{
typedef ieee_copy_leading_bits_tag method;
- BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
- BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
- BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000);
- BOOST_STATIC_CONSTANT(uint32_t, significand = 0x00007fff);
+ static constexpr uint32_t sign = 0x80000000u;
+ static constexpr uint32_t exponent = 0x7fff0000;
+ static constexpr uint32_t flag = 0x00008000;
+ static constexpr uint32_t significand = 0x00007fff;
// copy 1st, 2nd, 5th and 6th byte. 3rd and 4th byte are padding.
@@ -452,10 +465,10 @@ struct fp_traits_non_native<long double, extended_double_precision>
{
typedef ieee_copy_leading_bits_tag method;
- BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
- BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
- BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
- BOOST_STATIC_CONSTANT(uint32_t, significand = 0x0000ffff);
+ static constexpr uint32_t sign = 0x80000000u;
+ static constexpr uint32_t exponent = 0x7fff0000;
+ static constexpr uint32_t flag = 0x00000000;
+ static constexpr uint32_t significand = 0x0000ffff;
typedef uint32_t bits;
@@ -470,14 +483,7 @@ struct fp_traits_non_native<long double, extended_double_precision>
}
private:
-
-#if defined(BOOST_BIG_ENDIAN)
- BOOST_STATIC_CONSTANT(int, offset_ = 0);
-#elif defined(BOOST_LITTLE_ENDIAN)
- BOOST_STATIC_CONSTANT(int, offset_ = 12);
-#else
- BOOST_STATIC_ASSERT(false);
-#endif
+ static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 12;
};
#endif
@@ -525,7 +531,7 @@ template<> struct size_to_precision<16, true>
template <class T>
struct select_native
{
- typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T), ::boost::is_floating_point<T>::value>::type precision;
+ typedef typename size_to_precision<sizeof(T), ::std::is_floating_point<T>::value>::type precision;
typedef fp_traits_non_native<T, precision> type;
};
template<>
@@ -555,15 +561,15 @@ struct select_native<long double>
&& !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)\
&& !defined(__FAST_MATH__)\
&& !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)\
- && !defined(BOOST_INTEL)\
+ && !defined(__INTEL_COMPILER)\
&& !defined(sun)\
- && !defined(__VXWORKS__)
+ && !defined(__VXWORKS__)
# define BOOST_MATH_USE_STD_FPCLASSIFY
#endif
template<class T> struct fp_traits
{
- typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T), ::boost::is_floating_point<T>::value>::type precision;
+ typedef typename size_to_precision<sizeof(T), ::std::is_floating_point<T>::value>::type precision;
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
typedef typename select_native<T>::type type;
#else
diff --git a/contrib/restricted/boost/math/include/boost/math/special_functions/detail/round_fwd.hpp b/contrib/restricted/boost/math/include/boost/math/special_functions/detail/round_fwd.hpp
index 8c45a7d75a..c58459e36d 100644
--- a/contrib/restricted/boost/math/include/boost/math/special_functions/detail/round_fwd.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/special_functions/detail/round_fwd.hpp
@@ -8,7 +8,7 @@
#ifndef BOOST_MATH_SPECIAL_ROUND_FWD_HPP
#define BOOST_MATH_SPECIAL_ROUND_FWD_HPP
-#include <boost/config.hpp>
+#include <boost/math/tools/config.hpp>
#include <boost/math/tools/promotion.hpp>
#ifdef _MSC_VER
@@ -32,12 +32,10 @@ namespace boost
long ltrunc(const T& v, const Policy& pol);
template <class T>
long ltrunc(const T& v);
-#ifdef BOOST_HAS_LONG_LONG
template <class T, class Policy>
- boost::long_long_type lltrunc(const T& v, const Policy& pol);
+ long long lltrunc(const T& v, const Policy& pol);
template <class T>
- boost::long_long_type lltrunc(const T& v);
-#endif
+ long long lltrunc(const T& v);
template <class T, class Policy>
typename tools::promote_args<T>::type round(const T& v, const Policy& pol);
template <class T>
@@ -50,12 +48,10 @@ namespace boost
long lround(const T& v, const Policy& pol);
template <class T>
long lround(const T& v);
-#ifdef BOOST_HAS_LONG_LONG
template <class T, class Policy>
- boost::long_long_type llround(const T& v, const Policy& pol);
+ long long llround(const T& v, const Policy& pol);
template <class T>
- boost::long_long_type llround(const T& v);
-#endif
+ long long llround(const T& v);
template <class T, class Policy>
T modf(const T& v, T* ipart, const Policy& pol);
template <class T>
@@ -68,13 +64,10 @@ namespace boost
T modf(const T& v, long* ipart, const Policy& pol);
template <class T>
T modf(const T& v, long* ipart);
-#ifdef BOOST_HAS_LONG_LONG
template <class T, class Policy>
- T modf(const T& v, boost::long_long_type* ipart, const Policy& pol);
+ T modf(const T& v, long long* ipart, const Policy& pol);
template <class T>
- T modf(const T& v, boost::long_long_type* ipart);
-#endif
-
+ T modf(const T& v, long long* ipart);
}
}
diff --git a/contrib/restricted/boost/math/include/boost/math/special_functions/fpclassify.hpp b/contrib/restricted/boost/math/include/boost/math/special_functions/fpclassify.hpp
index d83e111c48..09fcf2924c 100644
--- a/contrib/restricted/boost/math/include/boost/math/special_functions/fpclassify.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/special_functions/fpclassify.hpp
@@ -11,11 +11,10 @@
#pragma once
#endif
-#include <math.h>
-#include <boost/config/no_tr1/cmath.hpp>
-#include <boost/limits.hpp>
+#include <limits>
+#include <type_traits>
+#include <cmath>
#include <boost/math/tools/real_cast.hpp>
-#include <boost/type_traits/is_floating_point.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/detail/fp_traits.hpp>
/*!
@@ -77,7 +76,7 @@ is used.
*/
-#if defined(_MSC_VER) || defined(__BORLANDC__)
+#if defined(_MSC_VER) || defined(BOOST_BORLANDC)
#include <float.h>
#endif
#ifdef BOOST_MATH_USE_FLOAT128
@@ -102,13 +101,13 @@ namespace boost{
//
namespace math_detail{
-#ifdef BOOST_MSVC
+#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4800)
#endif
template <class T>
-inline bool is_nan_helper(T t, const boost::true_type&)
+inline bool is_nan_helper(T t, const std::true_type&)
{
#ifdef isnan
return isnan(t);
@@ -120,26 +119,26 @@ inline bool is_nan_helper(T t, const boost::true_type&)
#endif
}
-#ifdef BOOST_MSVC
+#ifdef _MSC_VER
#pragma warning(pop)
#endif
template <class T>
-inline bool is_nan_helper(T, const boost::false_type&)
+inline bool is_nan_helper(T, const std::false_type&)
{
return false;
}
#if defined(BOOST_MATH_USE_FLOAT128)
#if defined(BOOST_MATH_HAS_QUADMATH_H)
-inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnanq(f); }
-inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnanq(f); }
+inline bool is_nan_helper(__float128 f, const std::true_type&) { return ::isnanq(f); }
+inline bool is_nan_helper(__float128 f, const std::false_type&) { return ::isnanq(f); }
#elif defined(BOOST_GNU_STDLIB) && BOOST_GNU_STDLIB && \
_GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
-inline bool is_nan_helper(__float128 f, const boost::true_type&) { return std::isnan(static_cast<double>(f)); }
-inline bool is_nan_helper(__float128 f, const boost::false_type&) { return std::isnan(static_cast<double>(f)); }
+inline bool is_nan_helper(__float128 f, const std::true_type&) { return std::isnan(static_cast<double>(f)); }
+inline bool is_nan_helper(__float128 f, const std::false_type&) { return std::isnan(static_cast<double>(f)); }
#else
-inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnan(static_cast<double>(f)); }
-inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnan(static_cast<double>(f)); }
+inline bool is_nan_helper(__float128 f, const std::true_type&) { return boost::math::isnan(static_cast<double>(f)); }
+inline bool is_nan_helper(__float128 f, const std::false_type&) { return boost::math::isnan(static_cast<double>(f)); }
#endif
#endif
}
@@ -163,12 +162,12 @@ inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&)
// whenever possible check for Nan's first:
#if defined(BOOST_HAS_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
- if(::boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>()))
+ if(::boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))
return FP_NAN;
#elif defined(isnan)
- if(boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>()))
+ if(boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))
return FP_NAN;
-#elif defined(_MSC_VER) || defined(__BORLANDC__)
+#elif defined(_MSC_VER) || defined(BOOST_BORLANDC)
if(::_isnan(boost::math::tools::real_cast<double>(t)))
return FP_NAN;
#endif
@@ -211,11 +210,11 @@ inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
template<class T>
int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
+ typedef typename fp_traits<T>::type traits;
BOOST_MATH_INSTRUMENT_VARIABLE(x);
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
BOOST_MATH_INSTRUMENT_VARIABLE(a);
a &= traits::exponent | traits::flag | traits::significand;
@@ -240,11 +239,11 @@ int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
template<class T>
int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
+ typedef typename fp_traits<T>::type traits;
BOOST_MATH_INSTRUMENT_VARIABLE(x);
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::flag | traits::significand;
@@ -336,8 +335,8 @@ namespace detail {
template<class T>
inline bool isfinite_impl(T x, ieee_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typedef typename detail::fp_traits<T>::type traits;
+ typename traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent;
return a != traits::exponent;
@@ -407,8 +406,8 @@ namespace detail {
template<class T>
inline bool isnormal_impl(T x, ieee_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typedef typename detail::fp_traits<T>::type traits;
+ typename traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::flag;
return (a != 0) && (a < traits::exponent);
@@ -480,9 +479,9 @@ namespace detail {
template<class T>
inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
+ typedef typename fp_traits<T>::type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::significand;
return a == traits::exponent;
@@ -491,9 +490,9 @@ namespace detail {
template<class T>
inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
+ typedef typename fp_traits<T>::type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::significand;
if(a != traits::exponent)
@@ -575,9 +574,9 @@ namespace detail {
template<class T>
inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
+ typedef typename fp_traits<T>::type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::significand;
return a > traits::exponent;
@@ -586,9 +585,9 @@ namespace detail {
template<class T>
inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
+ typedef typename fp_traits<T>::type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::significand;
@@ -612,9 +611,9 @@ inline bool (isnan)(T x)
}
#ifdef isnan
-template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
-template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
-template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
+template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
+template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
+template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
#elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
template<>
inline bool (isnan)(long double x)
@@ -635,6 +634,5 @@ inline bool (isnan)(__float128 x)
} // namespace math
} // namespace boost
-
#endif // BOOST_MATH_FPCLASSIFY_HPP
diff --git a/contrib/restricted/boost/math/include/boost/math/special_functions/hypot.hpp b/contrib/restricted/boost/math/include/boost/math/special_functions/hypot.hpp
new file mode 100644
index 0000000000..bfa797de80
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/special_functions/hypot.hpp
@@ -0,0 +1,82 @@
+// (C) Copyright John Maddock 2005-2006.
+// Use, modification and distribution are subject to 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_MATH_HYPOT_INCLUDED
+#define BOOST_MATH_HYPOT_INCLUDED
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include <boost/math/tools/config.hpp>
+#include <boost/math/tools/precision.hpp>
+#include <boost/math/policies/error_handling.hpp>
+#include <boost/math/special_functions/math_fwd.hpp>
+#include <algorithm> // for swap
+#include <cmath>
+
+namespace boost{ namespace math{ namespace detail{
+
+template <class T, class Policy>
+T hypot_imp(T x, T y, const Policy& pol)
+{
+ //
+ // Normalize x and y, so that both are positive and x >= y:
+ //
+ using std::fabs; using std::sqrt; // ADL of std names
+
+ x = fabs(x);
+ y = fabs(y);
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127)
+#endif
+ // special case, see C99 Annex F:
+ if(std::numeric_limits<T>::has_infinity
+ && ((x == std::numeric_limits<T>::infinity())
+ || (y == std::numeric_limits<T>::infinity())))
+ return policies::raise_overflow_error<T>("boost::math::hypot<%1%>(%1%,%1%)", 0, pol);
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+ if(y > x)
+ (std::swap)(x, y);
+
+ if(x * tools::epsilon<T>() >= y)
+ return x;
+
+ T rat = y / x;
+ return x * sqrt(1 + rat*rat);
+} // template <class T> T hypot(T x, T y)
+
+}
+
+template <class T1, class T2>
+inline typename tools::promote_args<T1, T2>::type
+ hypot(T1 x, T2 y)
+{
+ typedef typename tools::promote_args<T1, T2>::type result_type;
+ return detail::hypot_imp(
+ static_cast<result_type>(x), static_cast<result_type>(y), policies::policy<>());
+}
+
+template <class T1, class T2, class Policy>
+inline typename tools::promote_args<T1, T2>::type
+ hypot(T1 x, T2 y, const Policy& pol)
+{
+ typedef typename tools::promote_args<T1, T2>::type result_type;
+ return detail::hypot_imp(
+ static_cast<result_type>(x), static_cast<result_type>(y), pol);
+}
+
+} // namespace math
+} // namespace boost
+
+#endif // BOOST_MATH_HYPOT_INCLUDED
+
+
+
diff --git a/contrib/restricted/boost/math/include/boost/math/special_functions/math_fwd.hpp b/contrib/restricted/boost/math/include/boost/math/special_functions/math_fwd.hpp
index 4f44f56113..6f9d739e1e 100644
--- a/contrib/restricted/boost/math/include/boost/math/special_functions/math_fwd.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/special_functions/math_fwd.hpp
@@ -24,12 +24,11 @@
#endif
#include <vector>
+#include <complex>
+#include <type_traits>
#include <boost/math/special_functions/detail/round_fwd.hpp>
#include <boost/math/tools/promotion.hpp> // for argument promotion.
#include <boost/math/policies/policy.hpp>
-#include <boost/mpl/comparison.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/config/no_tr1/complex.hpp>
#define BOOST_NO_MACRO_EXPAND /**/
@@ -193,22 +192,21 @@ namespace boost
template <class T>
inline std::vector<T> legendre_p_zeros(int l);
-#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
template <class T, class Policy>
- typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
+ typename std::enable_if<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
legendre_p(int l, T x, const Policy& pol);
template <class T, class Policy>
- inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
+ inline typename std::enable_if<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
legendre_p_prime(int l, T x, const Policy& pol);
-#endif
+
template <class T>
typename tools::promote_args<T>::type
legendre_q(unsigned l, T x);
-#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
+
template <class T, class Policy>
- typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
+ typename std::enable_if<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
legendre_q(unsigned l, T x, const Policy& pol);
-#endif
+
template <class T1, class T2, class T3>
typename tools::promote_args<T1, T2, T3>::type
legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1);
@@ -240,11 +238,11 @@ namespace boost
template <class T1, class T2>
struct laguerre_result
{
- typedef typename mpl::if_<
- policies::is_policy<T2>,
+ using type = typename std::conditional<
+ policies::is_policy<T2>::value,
typename tools::promote_args<T1>::type,
typename tools::promote_args<T2>::type
- >::type type;
+ >::type;
};
template <class T1, class T2>
@@ -396,11 +394,11 @@ namespace boost
template <class T, class U, class V>
struct ellint_3_result
{
- typedef typename mpl::if_<
- policies::is_policy<V>,
+ using type = typename std::conditional<
+ policies::is_policy<V>::value,
typename tools::promote_args<T, U>::type,
typename tools::promote_args<T, U, V>::type
- >::type type;
+ >::type;
};
} // namespace detail
@@ -639,43 +637,40 @@ namespace boost
namespace detail{
- typedef mpl::int_<0> bessel_no_int_tag; // No integer optimisation possible.
- typedef mpl::int_<1> bessel_maybe_int_tag; // Maybe integer optimisation.
- typedef mpl::int_<2> bessel_int_tag; // Definite integer optimistaion.
+ typedef std::integral_constant<int, 0> bessel_no_int_tag; // No integer optimisation possible.
+ typedef std::integral_constant<int, 1> bessel_maybe_int_tag; // Maybe integer optimisation.
+ typedef std::integral_constant<int, 2> bessel_int_tag; // Definite integer optimisation.
template <class T1, class T2, class Policy>
struct bessel_traits
{
- typedef typename mpl::if_<
- is_integral<T1>,
+ using result_type = typename std::conditional<
+ std::is_integral<T1>::value,
typename tools::promote_args<T2>::type,
typename tools::promote_args<T1, T2>::type
- >::type result_type;
+ >::type;
typedef typename policies::precision<result_type, Policy>::type precision_type;
- typedef typename mpl::if_<
- mpl::or_<
- mpl::less_equal<precision_type, mpl::int_<0> >,
- mpl::greater<precision_type, mpl::int_<64> > >,
+ using optimisation_tag = typename std::conditional<
+ (precision_type::value <= 0 || precision_type::value > 64),
bessel_no_int_tag,
- typename mpl::if_<
- is_integral<T1>,
+ typename std::conditional<
+ std::is_integral<T1>::value,
bessel_int_tag,
bessel_maybe_int_tag
>::type
- >::type optimisation_tag;
- typedef typename mpl::if_<
- mpl::or_<
- mpl::less_equal<precision_type, mpl::int_<0> >,
- mpl::greater<precision_type, mpl::int_<113> > >,
+ >::type;
+
+ using optimisation_tag128 = typename std::conditional<
+ (precision_type::value <= 0 || precision_type::value > 113),
bessel_no_int_tag,
- typename mpl::if_<
- is_integral<T1>,
+ typename std::conditional<
+ std::is_integral<T1>::value,
bessel_int_tag,
bessel_maybe_int_tag
>::type
- >::type optimisation_tag128;
+ >::type;
};
} // detail
@@ -905,8 +900,8 @@ namespace boost
template <class T, class U>
struct expint_result
{
- typedef typename mpl::if_<
- policies::is_policy<U>,
+ typedef typename std::conditional<
+ policies::is_policy<U>::value,
typename tools::promote_args<T>::type,
typename tools::promote_args<U>::type
>::type type;
@@ -1013,16 +1008,89 @@ namespace boost
template <class T, class U>
typename tools::promote_args<T, U>::type jacobi_cs(T k, U theta);
+ // Jacobi Theta Functions:
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta1(T z, U q, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta1(T z, U q);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta2(T z, U q, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta2(T z, U q);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta3(T z, U q, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta3(T z, U q);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta4(T z, U q, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta4(T z, U q);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta1tau(T z, U tau, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta1tau(T z, U tau);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta2tau(T z, U tau, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta2tau(T z, U tau);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta3tau(T z, U tau, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta3tau(T z, U tau);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta4tau(T z, U tau, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta4tau(T z, U tau);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta3m1(T z, U q, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta3m1(T z, U q);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta4m1(T z, U q, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta4m1(T z, U q);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta3m1tau(T z, U tau, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta3m1tau(T z, U tau);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_theta4m1tau(T z, U tau, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_theta4m1tau(T z, U tau);
+
template <class T>
typename tools::promote_args<T>::type zeta(T s);
// pow:
template <int N, typename T, class Policy>
- typename tools::promote_args<T>::type pow(T base, const Policy& policy);
+ BOOST_CXX14_CONSTEXPR typename tools::promote_args<T>::type pow(T base, const Policy& policy);
template <int N, typename T>
- typename tools::promote_args<T>::type pow(T base);
+ BOOST_CXX14_CONSTEXPR typename tools::promote_args<T>::type pow(T base);
// next:
template <class T, class U, class Policy>
@@ -1085,28 +1153,61 @@ namespace boost
const unsigned number_of_bernoullis_b2n,
OutputIterator out_it);
+ // Lambert W:
+ template <class T, class Policy>
+ typename boost::math::tools::promote_args<T>::type lambert_w0(T z, const Policy& pol);
+ template <class T>
+ typename boost::math::tools::promote_args<T>::type lambert_w0(T z);
+ template <class T, class Policy>
+ typename boost::math::tools::promote_args<T>::type lambert_wm1(T z, const Policy& pol);
+ template <class T>
+ typename boost::math::tools::promote_args<T>::type lambert_wm1(T z);
+ template <class T, class Policy>
+ typename boost::math::tools::promote_args<T>::type lambert_w0_prime(T z, const Policy& pol);
+ template <class T>
+ typename boost::math::tools::promote_args<T>::type lambert_w0_prime(T z);
+ template <class T, class Policy>
+ typename boost::math::tools::promote_args<T>::type lambert_wm1_prime(T z, const Policy& pol);
+ template <class T>
+ typename boost::math::tools::promote_args<T>::type lambert_wm1_prime(T z);
+
+ // Hypergeometrics:
+ template <class T1, class T2> typename tools::promote_args<T1, T2>::type hypergeometric_1F0(T1 a, T2 z);
+ template <class T1, class T2, class Policy> typename tools::promote_args<T1, T2>::type hypergeometric_1F0(T1 a, T2 z, const Policy&);
+
+ template <class T1, class T2> typename tools::promote_args<T1, T2>::type hypergeometric_0F1(T1 b, T2 z);
+ template <class T1, class T2, class Policy> typename tools::promote_args<T1, T2>::type hypergeometric_0F1(T1 b, T2 z, const Policy&);
+
+ template <class T1, class T2, class T3> typename tools::promote_args<T1, T2, T3>::type hypergeometric_2F0(T1 a1, T2 a2, T3 z);
+ template <class T1, class T2, class T3, class Policy> typename tools::promote_args<T1, T2, T3>::type hypergeometric_2F0(T1 a1, T2 a2, T3 z, const Policy&);
+
+ template <class T1, class T2, class T3> typename tools::promote_args<T1, T2, T3>::type hypergeometric_1F1(T1 a, T2 b, T3 z);
+ template <class T1, class T2, class T3, class Policy> typename tools::promote_args<T1, T2, T3>::type hypergeometric_1F1(T1 a, T2 b, T3 z, const Policy&);
+
+
} // namespace math
} // namespace boost
-#ifdef BOOST_HAS_LONG_LONG
#define BOOST_MATH_DETAIL_LL_FUNC(Policy)\
\
template <class T>\
- inline T modf(const T& v, boost::long_long_type* ipart){ using boost::math::modf; return modf(v, ipart, Policy()); }\
+ inline T modf(const T& v, long long* ipart){ using boost::math::modf; return modf(v, ipart, Policy()); }\
\
template <class T>\
- inline boost::long_long_type lltrunc(const T& v){ using boost::math::lltrunc; return lltrunc(v, Policy()); }\
+ inline long long lltrunc(const T& v){ using boost::math::lltrunc; return lltrunc(v, Policy()); }\
\
template <class T>\
- inline boost::long_long_type llround(const T& v){ using boost::math::llround; return llround(v, Policy()); }\
+ inline long long llround(const T& v){ using boost::math::llround; return llround(v, Policy()); }\
-#else
-#define BOOST_MATH_DETAIL_LL_FUNC(Policy)
-#endif
+# define BOOST_MATH_DETAIL_11_FUNC(Policy)\
+ template <class T, class U, class V>\
+ inline typename boost::math::tools::promote_args<T, U>::type hypergeometric_1F1(const T& a, const U& b, const V& z)\
+ { return boost::math::hypergeometric_1F1(a, b, z, Policy()); }\
#define BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(Policy)\
\
BOOST_MATH_DETAIL_LL_FUNC(Policy)\
+ BOOST_MATH_DETAIL_11_FUNC(Policy)\
\
template <class RT1, class RT2>\
inline typename boost::math::tools::promote_args<RT1, RT2>::type \
@@ -1467,10 +1568,10 @@ template <class OutputIterator, class T>\
{ boost::math::cyl_neumann_zero(v, start_index, number_of_zeros, out_it, Policy()); }\
\
template <class T>\
- inline typename boost::math::tools::promote_args<T>::type sin_pi(T x){ return boost::math::sin_pi(x); }\
+ inline typename boost::math::tools::promote_args<T>::type sin_pi(T x){ return boost::math::sin_pi(x, Policy()); }\
\
template <class T>\
- inline typename boost::math::tools::promote_args<T>::type cos_pi(T x){ return boost::math::cos_pi(x); }\
+ inline typename boost::math::tools::promote_args<T>::type cos_pi(T x){ return boost::math::cos_pi(x, Policy()); }\
\
using boost::math::fpclassify;\
using boost::math::isfinite;\
@@ -1599,6 +1700,54 @@ template <class OutputIterator, class T>\
inline typename boost::math::tools::promote_args<T, U>::type jacobi_cs(T k, U theta)\
{ return boost::math::jacobi_cs(k, theta, Policy()); }\
\
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta1(T z, U q)\
+ { return boost::math::jacobi_theta1(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta2(T z, U q)\
+ { return boost::math::jacobi_theta2(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta3(T z, U q)\
+ { return boost::math::jacobi_theta3(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta4(T z, U q)\
+ { return boost::math::jacobi_theta4(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta1tau(T z, U q)\
+ { return boost::math::jacobi_theta1tau(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta2tau(T z, U q)\
+ { return boost::math::jacobi_theta2tau(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta3tau(T z, U q)\
+ { return boost::math::jacobi_theta3tau(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta4tau(T z, U q)\
+ { return boost::math::jacobi_theta4tau(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta3m1(T z, U q)\
+ { return boost::math::jacobi_theta3m1(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta4m1(T z, U q)\
+ { return boost::math::jacobi_theta4m1(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta3m1tau(T z, U q)\
+ { return boost::math::jacobi_theta3m1tau(z, q, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_theta4m1tau(T z, U q)\
+ { return boost::math::jacobi_theta4m1tau(z, q, Policy()); }\
+ \
template <class T>\
inline typename boost::math::tools::promote_args<T>::type airy_ai(T x)\
{ return boost::math::airy_ai(x, Policy()); }\
@@ -1643,6 +1792,24 @@ template <class OutputIterator, class T>\
OutputIterator tangent_t2n(int start_index, unsigned number_of_bernoullis_b2n, OutputIterator out_it)\
{ return boost::math::tangent_t2n<T>(start_index, number_of_bernoullis_b2n, out_it, Policy()); }\
\
+ template <class T> inline typename boost::math::tools::promote_args<T>::type lambert_w0(T z) { return boost::math::lambert_w0(z, Policy()); }\
+ template <class T> inline typename boost::math::tools::promote_args<T>::type lambert_wm1(T z) { return boost::math::lambert_w0(z, Policy()); }\
+ template <class T> inline typename boost::math::tools::promote_args<T>::type lambert_w0_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\
+ template <class T> inline typename boost::math::tools::promote_args<T>::type lambert_wm1_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type hypergeometric_1F0(const T& a, const U& z)\
+ { return boost::math::hypergeometric_1F0(a, z, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type hypergeometric_0F1(const T& a, const U& z)\
+ { return boost::math::hypergeometric_0F1(a, z, Policy()); }\
+ \
+ template <class T, class U, class V>\
+ inline typename boost::math::tools::promote_args<T, U>::type hypergeometric_2F0(const T& a1, const U& a2, const V& z)\
+ { return boost::math::hypergeometric_2F0(a1, a2, z, Policy()); }\
+ \
+
diff --git a/contrib/restricted/boost/math/include/boost/math/special_functions/next.hpp b/contrib/restricted/boost/math/include/boost/math/special_functions/next.hpp
index a63983e1c3..238766cfc9 100644
--- a/contrib/restricted/boost/math/include/boost/math/special_functions/next.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/special_functions/next.hpp
@@ -15,8 +15,10 @@
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <boost/math/special_functions/trunc.hpp>
+#include <boost/math/tools/traits.hpp>
+#include <type_traits>
+#include <cfloat>
-#include <float.h>
#if !defined(_CRAYC) && !defined(__CUDACC__) && (!defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 3)))
#if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(__SSE2__)
@@ -39,24 +41,24 @@ namespace detail{
template <class T>
struct has_hidden_guard_digits;
template <>
-struct has_hidden_guard_digits<float> : public mpl::false_ {};
+struct has_hidden_guard_digits<float> : public std::false_type {};
template <>
-struct has_hidden_guard_digits<double> : public mpl::false_ {};
+struct has_hidden_guard_digits<double> : public std::false_type {};
template <>
-struct has_hidden_guard_digits<long double> : public mpl::false_ {};
+struct has_hidden_guard_digits<long double> : public std::false_type {};
#ifdef BOOST_HAS_FLOAT128
template <>
-struct has_hidden_guard_digits<__float128> : public mpl::false_ {};
+struct has_hidden_guard_digits<__float128> : public std::false_type {};
#endif
template <>
-struct has_hidden_guard_digits<boost::math::concepts::real_concept> : public mpl::false_ {};
+struct has_hidden_guard_digits<boost::math::concepts::real_concept> : public std::false_type {};
template <>
-struct has_hidden_guard_digits<boost::math::concepts::std_real_concept> : public mpl::false_ {};
+struct has_hidden_guard_digits<boost::math::concepts::std_real_concept> : public std::false_type {};
template <class T, bool b>
-struct has_hidden_guard_digits_10 : public mpl::false_ {};
+struct has_hidden_guard_digits_10 : public std::false_type {};
template <class T>
-struct has_hidden_guard_digits_10<T, true> : public mpl::bool_<(std::numeric_limits<T>::digits10 != std::numeric_limits<T>::max_digits10)> {};
+struct has_hidden_guard_digits_10<T, true> : public std::integral_constant<bool, (std::numeric_limits<T>::digits10 != std::numeric_limits<T>::max_digits10)> {};
template <class T>
struct has_hidden_guard_digits
@@ -66,21 +68,21 @@ struct has_hidden_guard_digits
{};
template <class T>
-inline const T& normalize_value(const T& val, const mpl::false_&) { return val; }
+inline const T& normalize_value(const T& val, const std::false_type&) { return val; }
template <class T>
-inline T normalize_value(const T& val, const mpl::true_&)
+inline T normalize_value(const T& val, const std::true_type&)
{
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+ static_assert(std::numeric_limits<T>::is_specialized, "Type T must be specialized.");
+ static_assert(std::numeric_limits<T>::radix != 2, "Type T must be specialized.");
- boost::intmax_t shift = std::numeric_limits<T>::digits - ilogb(val) - 1;
+ std::intmax_t shift = (std::intmax_t)std::numeric_limits<T>::digits - (std::intmax_t)ilogb(val) - 1;
T result = scalbn(val, shift);
result = round(result);
return scalbn(result, -shift);
}
template <class T>
-inline T get_smallest_value(mpl::true_ const&)
+inline T get_smallest_value(std::true_type const&)
{
//
// numeric_limits lies about denorms being present - particularly
@@ -89,14 +91,14 @@ inline T get_smallest_value(mpl::true_ const&)
//
static const T m = std::numeric_limits<T>::denorm_min();
#ifdef BOOST_MATH_CHECK_SSE2
- return (_mm_getcsr() & (_MM_FLUSH_ZERO_ON | 0x40)) ? tools::min_value<T>() : m;;
+ return (_mm_getcsr() & (_MM_FLUSH_ZERO_ON | 0x40)) ? tools::min_value<T>() : m;
#else
return ((tools::min_value<T>() / 2) == 0) ? tools::min_value<T>() : m;
#endif
}
template <class T>
-inline T get_smallest_value(mpl::false_ const&)
+inline T get_smallest_value(std::false_type const&)
{
return tools::min_value<T>();
}
@@ -105,9 +107,9 @@ template <class T>
inline T get_smallest_value()
{
#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1310)
- return get_smallest_value<T>(mpl::bool_<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == 1)>());
+ return get_smallest_value<T>(std::integral_constant<bool, std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == 1)>());
#else
- return get_smallest_value<T>(mpl::bool_<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == std::denorm_present)>());
+ return get_smallest_value<T>(std::integral_constant<bool, std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == std::denorm_present)>());
#endif
}
@@ -144,16 +146,16 @@ template <class T>
const typename min_shift_initializer<T>::init min_shift_initializer<T>::initializer;
template <class T>
-inline T calc_min_shifted(const mpl::true_&)
+inline T calc_min_shifted(const std::true_type&)
{
BOOST_MATH_STD_USING
return ldexp(tools::min_value<T>(), tools::digits<T>() + 1);
}
template <class T>
-inline T calc_min_shifted(const mpl::false_&)
+inline T calc_min_shifted(const std::false_type&)
{
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+ static_assert(std::numeric_limits<T>::is_specialized, "Type T must be specialized.");
+ static_assert(std::numeric_limits<T>::radix != 2, "Type T must be specialized.");
return scalbn(tools::min_value<T>(), std::numeric_limits<T>::digits + 1);
}
@@ -162,17 +164,31 @@ inline T calc_min_shifted(const mpl::false_&)
template <class T>
inline T get_min_shift_value()
{
- static const T val = calc_min_shifted<T>(mpl::bool_<!std::numeric_limits<T>::is_specialized || std::numeric_limits<T>::radix == 2>());
+ static const T val = calc_min_shifted<T>(std::integral_constant<bool, !std::numeric_limits<T>::is_specialized || std::numeric_limits<T>::radix == 2>());
min_shift_initializer<T>::force_instantiate();
return val;
}
+template <class T, bool b = boost::math::tools::detail::has_backend_type<T>::value>
+struct exponent_type
+{
+ typedef int type;
+};
+
+template <class T>
+struct exponent_type<T, true>
+{
+ typedef typename T::backend_type::exponent_type type;
+};
+
template <class T, class Policy>
-T float_next_imp(const T& val, const mpl::true_&, const Policy& pol)
+T float_next_imp(const T& val, const std::true_type&, const Policy& pol)
{
+ typedef typename exponent_type<T>::type exponent_type;
+
BOOST_MATH_STD_USING
- int expon;
+ exponent_type expon;
static const char* function = "float_next<%1%>(%1%)";
int fpclass = (boost::math::fpclassify)(val);
@@ -213,13 +229,15 @@ T float_next_imp(const T& val, const mpl::true_&, const Policy& pol)
// Special version for some base other than 2:
//
template <class T, class Policy>
-T float_next_imp(const T& val, const mpl::false_&, const Policy& pol)
+T float_next_imp(const T& val, const std::false_type&, const Policy& pol)
{
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+ typedef typename exponent_type<T>::type exponent_type;
+
+ static_assert(std::numeric_limits<T>::is_specialized, "Type T must be specialized.");
+ static_assert(std::numeric_limits<T>::radix != 2, "Type T must be specialized.");
BOOST_MATH_STD_USING
- boost::intmax_t expon;
+ exponent_type expon;
static const char* function = "float_next<%1%>(%1%)";
int fpclass = (boost::math::fpclassify)(val);
@@ -264,7 +282,7 @@ template <class T, class Policy>
inline typename tools::promote_args<T>::type float_next(const T& val, const Policy& pol)
{
typedef typename tools::promote_args<T>::type result_type;
- return detail::float_next_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
+ return detail::float_next_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), std::integral_constant<bool, !std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
}
#if 0 //def BOOST_MSVC
@@ -299,10 +317,12 @@ inline typename tools::promote_args<T>::type float_next(const T& val)
namespace detail{
template <class T, class Policy>
-T float_prior_imp(const T& val, const mpl::true_&, const Policy& pol)
+T float_prior_imp(const T& val, const std::true_type&, const Policy& pol)
{
+ typedef typename exponent_type<T>::type exponent_type;
+
BOOST_MATH_STD_USING
- int expon;
+ exponent_type expon;
static const char* function = "float_prior<%1%>(%1%)";
int fpclass = (boost::math::fpclassify)(val);
@@ -344,13 +364,15 @@ T float_prior_imp(const T& val, const mpl::true_&, const Policy& pol)
// Special version for bases other than 2:
//
template <class T, class Policy>
-T float_prior_imp(const T& val, const mpl::false_&, const Policy& pol)
+T float_prior_imp(const T& val, const std::false_type&, const Policy& pol)
{
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+ typedef typename exponent_type<T>::type exponent_type;
+
+ static_assert(std::numeric_limits<T>::is_specialized, "Type T must be specialized.");
+ static_assert(std::numeric_limits<T>::radix != 2, "Type T must be specialized.");
BOOST_MATH_STD_USING
- boost::intmax_t expon;
+ exponent_type expon;
static const char* function = "float_prior<%1%>(%1%)";
int fpclass = (boost::math::fpclassify)(val);
@@ -396,7 +418,7 @@ template <class T, class Policy>
inline typename tools::promote_args<T>::type float_prior(const T& val, const Policy& pol)
{
typedef typename tools::promote_args<T>::type result_type;
- return detail::float_prior_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
+ return detail::float_prior_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), std::integral_constant<bool, !std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
}
#if 0 //def BOOST_MSVC
@@ -444,7 +466,7 @@ inline typename tools::promote_args<T, U>::type nextafter(const T& val, const U&
namespace detail{
template <class T, class Policy>
-T float_distance_imp(const T& a, const T& b, const mpl::true_&, const Policy& pol)
+T float_distance_imp(const T& a, const T& b, const std::true_type&, const Policy& pol)
{
BOOST_MATH_STD_USING
//
@@ -475,13 +497,13 @@ T float_distance_imp(const T& a, const T& b, const mpl::true_&, const Policy& po
+ fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
//
// By the time we get here, both a and b must have the same sign, we want
- // b > a and both postive for the following logic:
+ // b > a and both positive for the following logic:
//
if(a < 0)
return float_distance(static_cast<T>(-b), static_cast<T>(-a), pol);
- BOOST_ASSERT(a >= 0);
- BOOST_ASSERT(b >= a);
+ BOOST_MATH_ASSERT(a >= 0);
+ BOOST_MATH_ASSERT(b >= a);
int expon;
//
@@ -489,7 +511,7 @@ T float_distance_imp(const T& a, const T& b, const mpl::true_&, const Policy& po
// because we actually have fewer than tools::digits<T>()
// significant bits in the representation:
//
- frexp(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value<T>() : a, &expon);
+ (void)frexp(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value<T>() : a, &expon);
T upper = ldexp(T(1), expon);
T result = T(0);
//
@@ -499,7 +521,7 @@ T float_distance_imp(const T& a, const T& b, const mpl::true_&, const Policy& po
if(b > upper)
{
int expon2;
- frexp(b, &expon2);
+ (void)frexp(b, &expon2);
T upper2 = ldexp(T(0.5), expon2);
result = float_distance(upper2, b);
result += (expon2 - expon - 1) * ldexp(T(1), tools::digits<T>() - 1);
@@ -542,17 +564,17 @@ T float_distance_imp(const T& a, const T& b, const mpl::true_&, const Policy& po
//
// Result must be an integer:
//
- BOOST_ASSERT(result == floor(result));
+ BOOST_MATH_ASSERT(result == floor(result));
return result;
} // float_distance_imp
//
// Special versions for bases other than 2:
//
template <class T, class Policy>
-T float_distance_imp(const T& a, const T& b, const mpl::false_&, const Policy& pol)
+T float_distance_imp(const T& a, const T& b, const std::false_type&, const Policy& pol)
{
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+ static_assert(std::numeric_limits<T>::is_specialized, "Type T must be specialized.");
+ static_assert(std::numeric_limits<T>::radix != 2, "Type T must be specialized.");
BOOST_MATH_STD_USING
//
@@ -583,15 +605,15 @@ T float_distance_imp(const T& a, const T& b, const mpl::false_&, const Policy& p
+ fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
//
// By the time we get here, both a and b must have the same sign, we want
- // b > a and both postive for the following logic:
+ // b > a and both positive for the following logic:
//
if(a < 0)
return float_distance(static_cast<T>(-b), static_cast<T>(-a), pol);
- BOOST_ASSERT(a >= 0);
- BOOST_ASSERT(b >= a);
+ BOOST_MATH_ASSERT(a >= 0);
+ BOOST_MATH_ASSERT(b >= a);
- boost::intmax_t expon;
+ std::intmax_t expon;
//
// Note that if a is a denorm then the usual formula fails
// because we actually have fewer than tools::digits<T>()
@@ -606,7 +628,7 @@ T float_distance_imp(const T& a, const T& b, const mpl::false_&, const Policy& p
//
if(b > upper)
{
- boost::intmax_t expon2 = 1 + ilogb(b);
+ std::intmax_t expon2 = 1 + ilogb(b);
T upper2 = scalbn(T(1), expon2 - 1);
result = float_distance(upper2, b);
result += (expon2 - expon - 1) * scalbn(T(1), std::numeric_limits<T>::digits - 1);
@@ -649,7 +671,7 @@ T float_distance_imp(const T& a, const T& b, const mpl::false_&, const Policy& p
//
// Result must be an integer:
//
- BOOST_ASSERT(result == floor(result));
+ BOOST_MATH_ASSERT(result == floor(result));
return result;
} // float_distance_imp
@@ -658,8 +680,35 @@ T float_distance_imp(const T& a, const T& b, const mpl::false_&, const Policy& p
template <class T, class U, class Policy>
inline typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b, const Policy& pol)
{
- typedef typename tools::promote_args<T, U>::type result_type;
- return detail::float_distance_imp(detail::normalize_value(static_cast<result_type>(a), typename detail::has_hidden_guard_digits<result_type>::type()), detail::normalize_value(static_cast<result_type>(b), typename detail::has_hidden_guard_digits<result_type>::type()), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
+ //
+ // We allow ONE of a and b to be an integer type, otherwise both must be the SAME type.
+ //
+ static_assert(
+ (std::is_same<T, U>::value
+ || (std::is_integral<T>::value && !std::is_integral<U>::value)
+ || (!std::is_integral<T>::value && std::is_integral<U>::value)
+ || (std::numeric_limits<T>::is_specialized && std::numeric_limits<U>::is_specialized
+ && (std::numeric_limits<T>::digits == std::numeric_limits<U>::digits)
+ && (std::numeric_limits<T>::radix == std::numeric_limits<U>::radix)
+ && !std::numeric_limits<T>::is_integer && !std::numeric_limits<U>::is_integer)),
+ "Float distance between two different floating point types is undefined.");
+
+ BOOST_IF_CONSTEXPR (!std::is_same<T, U>::value)
+ {
+ BOOST_IF_CONSTEXPR(std::is_integral<T>::value)
+ {
+ return float_distance(static_cast<U>(a), b, pol);
+ }
+ else
+ {
+ return float_distance(a, static_cast<T>(b), pol);
+ }
+ }
+ else
+ {
+ typedef typename tools::promote_args<T, U>::type result_type;
+ return detail::float_distance_imp(detail::normalize_value(static_cast<result_type>(a), typename detail::has_hidden_guard_digits<result_type>::type()), detail::normalize_value(static_cast<result_type>(b), typename detail::has_hidden_guard_digits<result_type>::type()), std::integral_constant<bool, !std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
+ }
}
template <class T, class U>
@@ -671,7 +720,7 @@ typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b)
namespace detail{
template <class T, class Policy>
-T float_advance_imp(T val, int distance, const mpl::true_&, const Policy& pol)
+T float_advance_imp(T val, int distance, const std::true_type&, const Policy& pol)
{
BOOST_MATH_STD_USING
//
@@ -714,7 +763,7 @@ T float_advance_imp(T val, int distance, const mpl::true_&, const Policy& pol)
}
int expon;
- frexp(val, &expon);
+ (void)frexp(val, &expon);
T limit = ldexp((distance < 0 ? T(0.5f) : T(1)), expon);
if(val <= tools::min_value<T>())
{
@@ -754,10 +803,10 @@ T float_advance_imp(T val, int distance, const mpl::true_&, const Policy& pol)
// Special version for bases other than 2:
//
template <class T, class Policy>
-T float_advance_imp(T val, int distance, const mpl::false_&, const Policy& pol)
+T float_advance_imp(T val, int distance, const std::false_type&, const Policy& pol)
{
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+ static_assert(std::numeric_limits<T>::is_specialized, "Type T must be specialized.");
+ static_assert(std::numeric_limits<T>::radix != 2, "Type T must be specialized.");
BOOST_MATH_STD_USING
//
@@ -799,7 +848,7 @@ T float_advance_imp(T val, int distance, const mpl::false_&, const Policy& pol)
return val;
}
- boost::intmax_t expon = 1 + ilogb(val);
+ std::intmax_t expon = 1 + ilogb(val);
T limit = scalbn(T(1), distance < 0 ? expon - 1 : expon);
if(val <= tools::min_value<T>())
{
@@ -843,7 +892,7 @@ template <class T, class Policy>
inline typename tools::promote_args<T>::type float_advance(T val, int distance, const Policy& pol)
{
typedef typename tools::promote_args<T>::type result_type;
- return detail::float_advance_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), distance, mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
+ return detail::float_advance_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), distance, std::integral_constant<bool, !std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
}
template <class T>
@@ -855,4 +904,3 @@ inline typename tools::promote_args<T>::type float_advance(const T& val, int dis
}} // boost math namespaces
#endif // BOOST_MATH_SPECIAL_NEXT_HPP
-
diff --git a/contrib/restricted/boost/math/include/boost/math/special_functions/sign.hpp b/contrib/restricted/boost/math/include/boost/math/special_functions/sign.hpp
index 5cb21bac54..8f9fc4793a 100644
--- a/contrib/restricted/boost/math/include/boost/math/special_functions/sign.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/special_functions/sign.hpp
@@ -67,9 +67,9 @@ namespace detail {
template<class T>
inline int signbit_impl(T x, ieee_copy_all_bits_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
+ typedef typename fp_traits<T>::type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
return a & traits::sign ? 1 : 0;
}
@@ -77,9 +77,9 @@ namespace detail {
template<class T>
inline int signbit_impl(T x, ieee_copy_leading_bits_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
+ typedef typename fp_traits<T>::type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
return a & traits::sign ? 1 : 0;
@@ -126,9 +126,9 @@ namespace detail {
template<class T>
inline T changesign_impl(T x, ieee_copy_all_bits_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::sign_change_type traits;
+ typedef typename fp_traits<T>::sign_change_type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
a ^= traits::sign;
traits::set_bits(x,a);
@@ -138,9 +138,9 @@ namespace detail {
template<class T>
inline T (changesign_impl)(T x, ieee_copy_leading_bits_tag const&)
{
- typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::sign_change_type traits;
+ typedef typename fp_traits<T>::sign_change_type traits;
- BOOST_DEDUCED_TYPENAME traits::bits a;
+ typename traits::bits a;
traits::get_bits(x,a);
a ^= traits::sign;
traits::set_bits(x,a);
diff --git a/contrib/restricted/boost/math/include/boost/math/special_functions/trunc.hpp b/contrib/restricted/boost/math/include/boost/math/special_functions/trunc.hpp
index 3f80c96fee..46a2a991f8 100644
--- a/contrib/restricted/boost/math/include/boost/math/special_functions/trunc.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/special_functions/trunc.hpp
@@ -10,6 +10,7 @@
#pragma once
#endif
+#include <type_traits>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/tools/config.hpp>
#include <boost/math/policies/error_handling.hpp>
@@ -18,7 +19,7 @@
namespace boost{ namespace math{ namespace detail{
template <class T, class Policy>
-inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol, const mpl::false_&)
+inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol, const std::false_type&)
{
BOOST_MATH_STD_USING
typedef typename tools::promote_args<T>::type result_type;
@@ -28,7 +29,7 @@ inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol
}
template <class T, class Policy>
-inline typename tools::promote_args<T>::type trunc(const T& v, const Policy&, const mpl::true_&)
+inline typename tools::promote_args<T>::type trunc(const T& v, const Policy&, const std::true_type&)
{
return v;
}
@@ -38,7 +39,7 @@ inline typename tools::promote_args<T>::type trunc(const T& v, const Policy&, co
template <class T, class Policy>
inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol)
{
- return detail::trunc(v, pol, mpl::bool_<detail::is_integer_for_rounding<T>::value>());
+ return detail::trunc(v, pol, std::integral_constant<bool, detail::is_integer_for_rounding<T>::value>());
}
template <class T>
inline typename tools::promote_args<T>::type trunc(const T& v)
@@ -47,20 +48,24 @@ inline typename tools::promote_args<T>::type trunc(const T& v)
}
//
// The following functions will not compile unless T has an
-// implicit convertion to the integer types. For user-defined
+// implicit conversion to the integer types. For user-defined
// number types this will likely not be the case. In that case
// these functions should either be specialized for the UDT in
-// question, or else overloads should be placed in the same
+// question, or else overloads should be placed in the same
// namespace as the UDT: these will then be found via argument
// dependent lookup. See our concept archetypes for examples.
//
+// Non-standard numeric limits syntax "(std::numeric_limits<int>::max)()"
+// is to avoid macro substiution from MSVC
+// https://stackoverflow.com/questions/27442885/syntax-error-with-stdnumeric-limitsmax
+//
template <class T, class Policy>
inline int itrunc(const T& v, const Policy& pol)
{
BOOST_MATH_STD_USING
typedef typename tools::promote_args<T>::type result_type;
result_type r = boost::math::trunc(v, pol);
- if((r > (std::numeric_limits<int>::max)()) || (r < (std::numeric_limits<int>::min)()))
+ if(r > static_cast<result_type>((std::numeric_limits<int>::max)()) || r < static_cast<result_type>((std::numeric_limits<int>::min)()))
return static_cast<int>(policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", 0, static_cast<result_type>(v), 0, pol));
return static_cast<int>(r);
}
@@ -76,7 +81,7 @@ inline long ltrunc(const T& v, const Policy& pol)
BOOST_MATH_STD_USING
typedef typename tools::promote_args<T>::type result_type;
result_type r = boost::math::trunc(v, pol);
- if((r > (std::numeric_limits<long>::max)()) || (r < (std::numeric_limits<long>::min)()))
+ if(r > static_cast<result_type>((std::numeric_limits<long>::max)()) || r < static_cast<result_type>((std::numeric_limits<long>::min)()))
return static_cast<long>(policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", 0, static_cast<result_type>(v), 0L, pol));
return static_cast<long>(r);
}
@@ -86,25 +91,69 @@ inline long ltrunc(const T& v)
return ltrunc(v, policies::policy<>());
}
-#ifdef BOOST_HAS_LONG_LONG
-
template <class T, class Policy>
-inline boost::long_long_type lltrunc(const T& v, const Policy& pol)
+inline long long lltrunc(const T& v, const Policy& pol)
{
BOOST_MATH_STD_USING
typedef typename tools::promote_args<T>::type result_type;
result_type r = boost::math::trunc(v, pol);
- if((r > (std::numeric_limits<boost::long_long_type>::max)()) || (r < (std::numeric_limits<boost::long_long_type>::min)()))
- return static_cast<boost::long_long_type>(policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", 0, v, static_cast<boost::long_long_type>(0), pol));
- return static_cast<boost::long_long_type>(r);
+ if(r > static_cast<result_type>((std::numeric_limits<long long>::max)()) ||
+ r < static_cast<result_type>((std::numeric_limits<long long>::min)()))
+ {
+ return static_cast<long long>(policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", 0, v, static_cast<long long>(0), pol));
+ }
+ return static_cast<long long>(r);
}
template <class T>
-inline boost::long_long_type lltrunc(const T& v)
+inline long long lltrunc(const T& v)
{
return lltrunc(v, policies::policy<>());
}
-#endif
+template <class T, class Policy>
+inline typename std::enable_if<std::is_constructible<int, T>::value, int>::type
+ iconvert(const T& v, const Policy&)
+{
+ return static_cast<int>(v);
+}
+
+template <class T, class Policy>
+inline typename std::enable_if<!std::is_constructible<int, T>::value, int>::type
+ iconvert(const T& v, const Policy& pol)
+{
+ using boost::math::itrunc;
+ return itrunc(v, pol);
+}
+
+template <class T, class Policy>
+inline typename std::enable_if<std::is_constructible<long, T>::value, long>::type
+ lconvert(const T& v, const Policy&)
+{
+ return static_cast<long>(v);
+}
+
+template <class T, class Policy>
+inline typename std::enable_if<!std::is_constructible<long, T>::value, long>::type
+ lconvert(const T& v, const Policy& pol)
+{
+ using boost::math::ltrunc;
+ return ltrunc(v, pol);
+}
+
+template <class T, class Policy>
+inline typename std::enable_if<std::is_constructible<long long, T>::value, long long>::type
+ llconvertert(const T& v, const Policy&)
+{
+ return static_cast<long long>(v);
+}
+
+template <class T, class Policy>
+inline typename std::enable_if<!std::is_constructible<long long, T>::value, long long>::type
+ llconvertert(const T& v, const Policy& pol)
+{
+ using boost::math::lltrunc;
+ return lltrunc(v, pol);
+}
}} // namespaces
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/assert.hpp b/contrib/restricted/boost/math/include/boost/math/tools/assert.hpp
new file mode 100644
index 0000000000..3d5655923a
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/tools/assert.hpp
@@ -0,0 +1,34 @@
+// (C) Copyright Matt Borland 2021.
+// Use, modification and distribution are subject to 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)
+//
+// We deliberately use assert in here:
+//
+// boost-no-inspect
+
+#ifndef BOOST_MATH_TOOLS_ASSERT_HPP
+#define BOOST_MATH_TOOLS_ASSERT_HPP
+
+#include <boost/math/tools/is_standalone.hpp>
+
+#ifndef BOOST_MATH_STANDALONE
+
+#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
+#define BOOST_MATH_ASSERT(expr) BOOST_ASSERT(expr)
+#define BOOST_MATH_ASSERT_MSG(expr, msg) BOOST_ASSERT_MSG(expr, msg)
+#define BOOST_MATH_STATIC_ASSERT(expr) BOOST_STATIC_ASSERT(expr)
+#define BOOST_MATH_STATIC_ASSERT_MSG(expr, msg) BOOST_STATIC_ASSERT_MSG(expr, msg)
+
+#else // Standalone mode - use cassert
+
+#include <cassert>
+#define BOOST_MATH_ASSERT(expr) assert(expr)
+#define BOOST_MATH_ASSERT_MSG(expr, msg) assert((expr)&&(msg))
+#define BOOST_MATH_STATIC_ASSERT(expr) static_assert(expr, #expr " failed")
+#define BOOST_MATH_STATIC_ASSERT_MSG(expr, msg) static_assert(expr, msg)
+
+#endif
+
+#endif // BOOST_MATH_TOOLS_ASSERT_HPP
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/complex.hpp b/contrib/restricted/boost/math/include/boost/math/tools/complex.hpp
new file mode 100644
index 0000000000..d462ca8092
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/tools/complex.hpp
@@ -0,0 +1,76 @@
+// Copyright John Maddock 2018.
+// Use, modification and distribution are subject to 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)
+
+//
+// Tools for operator on complex as well as scalar types.
+//
+
+#ifndef BOOST_MATH_TOOLS_COMPLEX_HPP
+#define BOOST_MATH_TOOLS_COMPLEX_HPP
+
+#include <utility>
+#include <boost/math/tools/is_detected.hpp>
+
+namespace boost {
+ namespace math {
+ namespace tools {
+
+ namespace detail {
+ template <typename T, typename = void>
+ struct is_complex_type_impl
+ {
+ static constexpr bool value = false;
+ };
+
+ template <typename T>
+ struct is_complex_type_impl<T, void_t<decltype(std::declval<T>().real()),
+ decltype(std::declval<T>().imag())>>
+ {
+ static constexpr bool value = true;
+ };
+ } // Namespace detail
+
+ template <typename T>
+ struct is_complex_type : public detail::is_complex_type_impl<T> {};
+
+ //
+ // Use this trait to typecast integer literals to something
+ // that will interoperate with T:
+ //
+ template <class T, bool = is_complex_type<T>::value>
+ struct integer_scalar_type
+ {
+ typedef int type;
+ };
+ template <class T>
+ struct integer_scalar_type<T, true>
+ {
+ typedef typename T::value_type type;
+ };
+ template <class T, bool = is_complex_type<T>::value>
+ struct unsigned_scalar_type
+ {
+ typedef unsigned type;
+ };
+ template <class T>
+ struct unsigned_scalar_type<T, true>
+ {
+ typedef typename T::value_type type;
+ };
+ template <class T, bool = is_complex_type<T>::value>
+ struct scalar_type
+ {
+ typedef T type;
+ };
+ template <class T>
+ struct scalar_type<T, true>
+ {
+ typedef typename T::value_type type;
+ };
+
+
+} } }
+
+#endif // BOOST_MATH_TOOLS_COMPLEX_HPP
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/config.hpp b/contrib/restricted/boost/math/include/boost/math/tools/config.hpp
index 016211cfa8..09db298a88 100644
--- a/contrib/restricted/boost/math/include/boost/math/tools/config.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/tools/config.hpp
@@ -1,4 +1,5 @@
// Copyright (c) 2006-7 John Maddock
+// Copyright (c) 2021 Matt Borland
// Use, modification and distribution are subject to 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)
@@ -10,46 +11,135 @@
#pragma once
#endif
+#include <boost/math/tools/is_standalone.hpp>
+
+// Minimum language standard transition
+#ifdef _MSVC_LANG
+# if _MSVC_LANG < 201402L
+# pragma warning("The minimum language standard to use Boost.Math will be C++14 starting in July 2023 (Boost 1.82 release)");
+# endif
+#else
+# if __cplusplus < 201402L
+# warning "The minimum language standard to use Boost.Math will be C++14 starting in July 2023 (Boost 1.82 release)"
+# endif
+#endif
+
+#ifndef BOOST_MATH_STANDALONE
#include <boost/config.hpp>
-#include <boost/predef.h>
-#include <boost/cstdint.hpp> // for boost::uintmax_t
-#include <boost/detail/workaround.hpp>
-#include <boost/type_traits/is_integral.hpp>
+
+#else // Things from boost/config that are required, and easy to replicate
+
+#define BOOST_PREVENT_MACRO_SUBSTITUTION
+#define BOOST_MATH_NO_REAL_CONCEPT_TESTS
+#define BOOST_MATH_NO_DISTRIBUTION_CONCEPT_TESTS
+#define BOOST_MATH_NO_LEXICAL_CAST
+
+// Since Boost.Multiprecision is in active development some tests do not fully cooperate yet.
+#define BOOST_MATH_NO_MP_TESTS
+
+#if (__cplusplus > 201400L || _MSVC_LANG > 201400L)
+#define BOOST_CXX14_CONSTEXPR constexpr
+#else
+#define BOOST_CXX14_CONSTEXPR
+#define BOOST_NO_CXX14_CONSTEXPR
+#endif // BOOST_CXX14_CONSTEXPR
+
+#if (__cplusplus > 201700L || _MSVC_LANG > 201700L)
+#define BOOST_IF_CONSTEXPR if constexpr
+
+// Clang on mac provides the execution header with none of the functionality. TODO: Check back on this
+// https://en.cppreference.com/w/cpp/compiler_support "Standardization of Parallelism TS"
+#if !__has_include(<execution>) || (defined(__APPLE__) && defined(__clang__))
+#define BOOST_NO_CXX17_HDR_EXECUTION
+#endif
+#else
+#define BOOST_IF_CONSTEXPR if
+#define BOOST_NO_CXX17_IF_CONSTEXPR
+#define BOOST_NO_CXX17_HDR_EXECUTION
+#endif
+
+#if __cpp_lib_gcd_lcm >= 201606L
+#define BOOST_MATH_HAS_CXX17_NUMERIC
+#endif
+
+#define BOOST_JOIN(X, Y) BOOST_DO_JOIN(X, Y)
+#define BOOST_DO_JOIN(X, Y) BOOST_DO_JOIN2(X,Y)
+#define BOOST_DO_JOIN2(X, Y) X##Y
+
+#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X)
+#define BOOST_DO_STRINGIZE(X) #X
+
+#ifdef BOOST_DISABLE_THREADS // No threads, do nothing
+// Detect thread support via STL implementation
+#elif defined(__has_include)
+# if !__has_include(<thread>) || !__has_include(<mutex>) || !__has_include(<future>) || !__has_include(<atomic>)
+# define BOOST_DISABLE_THREADS
+# else
+# define BOOST_HAS_THREADS
+# endif
+#else
+# define BOOST_HAS_THREADS // The default assumption is that the machine has threads
+#endif // Thread Support
+
+#ifdef BOOST_DISABLE_THREADS
+# define BOOST_NO_CXX11_HDR_ATOMIC
+# define BOOST_NO_CXX11_HDR_FUTURE
+# define BOOST_NO_CXX11_HDR_THREAD
+# define BOOST_NO_CXX11_THREAD_LOCAL
+#endif // BOOST_DISABLE_THREADS
+
+#ifdef __GNUC__
+# if !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)
+# define BOOST_NO_EXCEPTIONS
+# endif
+ //
+ // Make sure we have some std lib headers included so we can detect __GXX_RTTI:
+ //
+# include <algorithm> // for min and max
+# include <limits>
+# ifndef __GXX_RTTI
+# ifndef BOOST_NO_TYPEID
+# define BOOST_NO_TYPEID
+# endif
+# ifndef BOOST_NO_RTTI
+# define BOOST_NO_RTTI
+# endif
+# endif
+#endif
+
+#endif // BOOST_MATH_STANDALONE
+
+// Support compilers with P0024R2 implemented without linking TBB
+// https://en.cppreference.com/w/cpp/compiler_support
+#if !defined(BOOST_NO_CXX17_HDR_EXECUTION) && defined(BOOST_HAS_THREADS)
+# define BOOST_MATH_EXEC_COMPATIBLE
+#endif
+
#include <algorithm> // for min and max
-#include <boost/config/no_tr1/cmath.hpp>
+#include <limits>
+#include <cmath>
#include <climits>
#include <cfloat>
#if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
# include <math.h>
#endif
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
-# include <limits>
-#endif
#include <boost/math/tools/user.hpp>
-#if (defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__NetBSD__) \
+#if (defined(__NetBSD__) || defined(__EMSCRIPTEN__)\
|| (defined(__hppa) && !defined(__OpenBSD__)) || (defined(__NO_LONG_DOUBLE_MATH) && (DBL_MANT_DIG != LDBL_MANT_DIG))) \
&& !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
-# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
-#endif
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
-//
-// Borland post 5.8.2 uses Dinkumware's std C lib which
-// doesn't have true long double precision. Earlier
-// versions are problematic too:
-//
-# define BOOST_MATH_NO_REAL_CONCEPT_TESTS
-# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
-# define BOOST_MATH_CONTROL_FP _control87(MCW_EM,MCW_EM)
-# include <float.h>
+//# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
#endif
+
#ifdef __IBMCPP__
//
-// For reasons I don't unserstand, the tests with IMB's compiler all
+// For reasons I don't understand, the tests with IMB's compiler all
// pass at long double precision, but fail with real_concept, those tests
// are disabled for now. (JM 2012).
+#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS
# define BOOST_MATH_NO_REAL_CONCEPT_TESTS
+#endif // BOOST_MATH_NO_REAL_CONCEPT_TESTS
#endif
#ifdef sun
// Any use of __float128 in program startup code causes a segfault (tested JM 2015, Solaris 11).
@@ -70,6 +160,13 @@
//
# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
#endif
+#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) && (LDBL_MANT_DIG == 106) && (LDBL_MIN_EXP > DBL_MIN_EXP)
+//
+// Generic catch all case for gcc's "double-double" long double type.
+// We do not support this as it's not even remotely IEEE conforming:
+//
+# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
+#endif
#if defined(unix) && defined(__INTEL_COMPILER) && (__INTEL_COMPILER <= 1000) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
//
// Intel compiler prior to version 10 has sporadic problems
@@ -94,7 +191,7 @@
#define BOOST_MATH_DISABLE_STD_FPCLASSIFY
#endif
-#if defined(BOOST_MSVC) && !defined(_WIN32_WCE)
+#if defined(_MSC_VER) && !defined(_WIN32_WCE)
// Better safe than sorry, our tests don't support hardware exceptions:
# define BOOST_MATH_CONTROL_FP _control87(MCW_EM,MCW_EM)
#endif
@@ -119,22 +216,27 @@
# define BOOST_MATH_USE_C99
#endif
-#if defined(__CYGWIN__) || defined(__HP_aCC) || defined(BOOST_INTEL) \
+#if defined(__CYGWIN__) || defined(__HP_aCC) || defined(__INTEL_COMPILER) \
|| defined(BOOST_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) \
|| (defined(__GNUC__) && !defined(BOOST_MATH_USE_C99))\
|| defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
# define BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY
#endif
-#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590)
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x590)
+
+namespace boost { namespace math { namespace tools { namespace detail {
+template <typename T>
+struct type {};
-# include "boost/type.hpp"
-# include "boost/non_type.hpp"
+template <typename T, T n>
+struct non_type {};
+}}}} // Namespace boost, math tools, detail
-# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t) boost::type<t>* = 0
-# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t) boost::type<t>*
-# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v) boost::non_type<t, v>* = 0
-# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) boost::non_type<t, v>*
+# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t) boost::math::tools::detail::type<t>* = 0
+# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t) boost::math::tools::detail::type<t>*
+# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v) boost::math::tools::detail::non_type<t, v>* = 0
+# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) boost::math::tools::detail::non_type<t, v>*
# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(t) \
, BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t)
@@ -170,24 +272,25 @@
# define BOOST_MATH_SMALL_CONSTANT(x) x
#endif
-
-#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
-//
-// Define if constants too large for a float cause "bad"
-// values to be stored in the data, rather than infinity
-// or a suitably large value.
-//
-# define BOOST_MATH_BUGGY_LARGE_FLOAT_CONSTANTS
-#endif
//
// Tune performance options for specific compilers:
//
-#ifdef BOOST_MSVC
+#ifdef _MSC_VER
# define BOOST_MATH_POLY_METHOD 2
+#if _MSC_VER <= 1900
# define BOOST_MATH_RATIONAL_METHOD 1
-#elif defined(BOOST_INTEL)
+#else
+# define BOOST_MATH_RATIONAL_METHOD 2
+#endif
+#if _MSC_VER > 1900
+# define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT
+# define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L
+#endif
+
+#elif defined(__INTEL_COMPILER)
# define BOOST_MATH_POLY_METHOD 2
# define BOOST_MATH_RATIONAL_METHOD 1
+
#elif defined(__GNUC__)
#if __GNUC__ < 4
# define BOOST_MATH_POLY_METHOD 3
@@ -196,48 +299,26 @@
# define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L
#else
# define BOOST_MATH_POLY_METHOD 3
-# define BOOST_MATH_RATIONAL_METHOD 1
-#endif
+# define BOOST_MATH_RATIONAL_METHOD 3
#endif
-#if defined(BOOST_NO_LONG_LONG) && !defined(BOOST_MATH_INT_TABLE_TYPE)
+#elif defined(__clang__)
+
+#if __clang__ > 6
+# define BOOST_MATH_POLY_METHOD 3
+# define BOOST_MATH_RATIONAL_METHOD 3
# define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT
# define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L
#endif
-//
-// constexpr support, early GCC implementations can't cope so disable
-// constexpr for them:
-//
-#if !defined(__clang) && defined(__GNUC__)
-#if (__GNUC__ * 100 + __GNUC_MINOR__) < 490
-# define BOOST_MATH_DISABLE_CONSTEXPR
-#endif
-#endif
-
-#ifdef BOOST_MATH_DISABLE_CONSTEXPR
-# define BOOST_MATH_CONSTEXPR
-#else
-# define BOOST_MATH_CONSTEXPR BOOST_CONSTEXPR
#endif
//
// noexcept support:
//
-#ifndef BOOST_NO_CXX11_NOEXCEPT
-#ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
#include <type_traits>
-# define BOOST_MATH_NOEXCEPT(T) noexcept(std::is_floating_point<T>::value)
-# define BOOST_MATH_IS_FLOAT(T) (std::is_floating_point<T>::value)
-#else
-#include <boost/type_traits/is_floating_point.hpp>
-# define BOOST_MATH_NOEXCEPT(T) noexcept(boost::is_floating_point<T>::value)
-# define BOOST_MATH_IS_FLOAT(T) (boost::is_floating_point<T>::value)
-#endif
-#else
-# define BOOST_MATH_NOEXCEPT(T)
-# define BOOST_MATH_IS_FLOAT(T) false
-#endif
+#define BOOST_MATH_NOEXCEPT(T) noexcept(std::is_floating_point<T>::value)
+#define BOOST_MATH_IS_FLOAT(T) (std::is_floating_point<T>::value)
//
// The maximum order of polynomial that will be evaluated
@@ -267,17 +348,18 @@
//
// And then the actual configuration:
//
-#if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__) \
- && !defined(BOOST_MATH_DISABLE_FLOAT128) || defined(BOOST_MATH_USE_FLOAT128)
+#if defined(BOOST_MATH_STANDALONE) && defined(_GLIBCXX_USE_FLOAT128) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && !defined(__STRICT_ANSI__) \
+ && !defined(BOOST_MATH_DISABLE_FLOAT128) && !defined(BOOST_MATH_USE_FLOAT128)
+# define BOOST_MATH_USE_FLOAT128
+#elif defined(BOOST_HAS_FLOAT128) && !defined(BOOST_MATH_USE_FLOAT128)
+# define BOOST_MATH_USE_FLOAT128
+#endif
+#ifdef BOOST_MATH_USE_FLOAT128
//
// Only enable this when the compiler really is GCC as clang and probably
// intel too don't support __float128 yet :-(
//
-#ifndef BOOST_MATH_USE_FLOAT128
-# define BOOST_MATH_USE_FLOAT128
-#endif
-
-# if defined(BOOST_INTEL) && defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION >= 1310) && defined(__GNUC__)
+# if defined(__INTEL_COMPILER) && defined(__GNUC__)
# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
# define BOOST_MATH_FLOAT128_TYPE __float128
# endif
@@ -360,11 +442,7 @@ namespace detail{
template <class T>
struct is_integer_for_rounding
{
- static const bool value = boost::is_integral<T>::value
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer)
-#endif
- ;
+ static constexpr bool value = std::is_integral<T>::value || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer);
};
}
@@ -377,7 +455,7 @@ struct is_integer_for_rounding
# endif
#endif
-#if ((defined(__linux__) && !defined(__UCLIBC__) && !defined(BOOST_MATH_HAVE_FIXED_GLIBC)) || defined(__QNX__) || defined(__IBMCPP__)) && !defined(BOOST_NO_FENV_H)
+#if ((defined(__linux__) && !defined(__UCLIBC__) && !defined(BOOST_MATH_HAVE_FIXED_GLIBC)) || defined(__QNX__) || defined(__IBMCPP__))
//
// This code was introduced in response to this glibc bug: http://sourceware.org/bugzilla/show_bug.cgi?id=2445
// Basically powl and expl can return garbage when the result is small and certain exception flags are set
@@ -385,7 +463,7 @@ struct is_integer_for_rounding
// Much more information in this message thread: https://groups.google.com/forum/#!topic/boost-list/ZT99wtIFlb4
//
- #include <boost/detail/fenv.hpp>
+#include <cfenv>
# ifdef FE_ALL_EXCEPT
@@ -433,7 +511,7 @@ namespace boost{ namespace math{
# define BOOST_MATH_INSTRUMENT_CODE(x) \
std::cout << std::setprecision(35) << __FILE__ << ":" << __LINE__ << " " << x << std::endl;
-# define BOOST_MATH_INSTRUMENT_VARIABLE(name) BOOST_MATH_INSTRUMENT_CODE(BOOST_STRINGIZE(name) << " = " << name)
+# define BOOST_MATH_INSTRUMENT_VARIABLE(name) BOOST_MATH_INSTRUMENT_CODE(#name << " = " << name)
#else
@@ -445,16 +523,25 @@ namespace boost{ namespace math{
//
// Thread local storage:
//
-#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL)
+#ifndef BOOST_DISABLE_THREADS
# define BOOST_MATH_THREAD_LOCAL thread_local
#else
-# define BOOST_MATH_THREAD_LOCAL
+# define BOOST_MATH_THREAD_LOCAL
#endif
//
+// Some mingw flavours have issues with thread_local and types with non-trivial destructors
+// See https://sourceforge.net/p/mingw-w64/bugs/527/
+//
+#if (defined(__MINGW32__) && (__GNUC__ < 9) && !defined(__clang__))
+# define BOOST_MATH_NO_THREAD_LOCAL_WITH_NON_TRIVIAL_TYPES
+#endif
+
+
+//
// Can we have constexpr tables?
//
-#if (!defined(BOOST_NO_CXX11_HDR_ARRAY) && !defined(BOOST_NO_CXX14_CONSTEXPR)) || BOOST_WORKAROUND(BOOST_MSVC, >= 1910)
+#if (!defined(BOOST_NO_CXX14_CONSTEXPR)) || (defined(_MSC_VER) && _MSC_VER >= 1910)
#define BOOST_MATH_HAVE_CONSTEXPR_TABLES
#define BOOST_MATH_CONSTEXPR_TABLE_FUNCTION constexpr
#else
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/convert_from_string.hpp b/contrib/restricted/boost/math/include/boost/math/tools/convert_from_string.hpp
new file mode 100644
index 0000000000..fa6af219ea
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/tools/convert_from_string.hpp
@@ -0,0 +1,54 @@
+// Copyright John Maddock 2016.
+// Use, modification and distribution are subject to 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_MATH_TOOLS_CONVERT_FROM_STRING_INCLUDED
+#define BOOST_MATH_TOOLS_CONVERT_FROM_STRING_INCLUDED
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include <type_traits>
+#ifndef BOOST_MATH_STANDALONE
+#include <boost/lexical_cast.hpp>
+#endif
+
+namespace boost{ namespace math{ namespace tools{
+
+ template <class T>
+ struct convert_from_string_result
+ {
+ typedef typename std::conditional<std::is_constructible<T, const char*>::value, const char*, T>::type type;
+ };
+
+ template <class Real>
+ Real convert_from_string(const char* p, const std::false_type&)
+ {
+#ifdef BOOST_MATH_NO_LEXICAL_CAST
+ // This function should not compile, we don't have the necessary functionality to support it:
+ static_assert(sizeof(Real) == 0, "boost.lexical_cast is not supported in standalone mode.");
+ (void)p; // Supresses -Wunused-parameter
+ return Real(0);
+#else
+ return boost::lexical_cast<Real>(p);
+#endif
+ }
+ template <class Real>
+ constexpr const char* convert_from_string(const char* p, const std::true_type&) noexcept
+ {
+ return p;
+ }
+ template <class Real>
+ constexpr typename convert_from_string_result<Real>::type convert_from_string(const char* p) noexcept((std::is_constructible<Real, const char*>::value))
+ {
+ return convert_from_string<Real>(p, std::is_constructible<Real, const char*>());
+ }
+
+} // namespace tools
+} // namespace math
+} // namespace boost
+
+#endif // BOOST_MATH_TOOLS_CONVERT_FROM_STRING_INCLUDED
+
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/cxx03_warn.hpp b/contrib/restricted/boost/math/include/boost/math/tools/cxx03_warn.hpp
new file mode 100644
index 0000000000..7aafea7553
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/tools/cxx03_warn.hpp
@@ -0,0 +1,95 @@
+// Copyright (c) 2020 John Maddock
+// Use, modification and distribution are subject to 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_MATH_TOOLS_CXX03_WARN_HPP
+#define BOOST_MATH_TOOLS_CXX03_WARN_HPP
+
+#include <boost/math/tools/config.hpp>
+
+#if defined(BOOST_NO_CXX11_NOEXCEPT)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_NOEXCEPT"
+#endif
+#if defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_NOEXCEPT"
+#endif
+#if defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_NOEXCEPT"
+#endif
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_RVALUE_REFERENCES"
+#endif
+#if defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_SFINAE_EXPR"
+#endif
+#if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_AUTO_DECLARATIONS"
+#endif
+#if defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_LAMBDAS"
+#endif
+#if defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX"
+#endif
+#if defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_HDR_TUPLE"
+#endif
+#if defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_HDR_INITIALIZER_LIST"
+#endif
+#if defined(BOOST_NO_CXX11_HDR_CHRONO) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_HDR_CHRONO"
+#endif
+#if defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_CONSTEXPR"
+#endif
+#if defined(BOOST_NO_CXX11_NULLPTR) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_NULLPTR"
+#endif
+#if defined(BOOST_NO_CXX11_NUMERIC_LIMITS) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_NUMERIC_LIMITS"
+#endif
+#if defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_DECLTYPE"
+#endif
+#if defined(BOOST_NO_CXX11_HDR_ARRAY) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_HDR_ARRAY"
+#endif
+#if defined(BOOST_NO_CXX11_ALLOCATOR) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_ALLOCATOR"
+#endif
+#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) && !defined(BOOST_MATH_SHOW_CXX03_WARNING)
+# define BOOST_MATH_SHOW_CXX03_WARNING
+# define BOOST_MATH_CXX03_WARN_REASON "BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS"
+#endif
+
+#ifdef BOOST_MATH_SHOW_CXX03_WARNING
+//
+// The above list includes everything we use, plus a few we're likely to use soon.
+// As from March 2020, C++03 support is deprecated, and as from March 2021 will be removed,
+// so mark up as such:
+//
+// March 2021(mborland): C++03 support has been removed. Replace warning with hard error.
+//
+#error Support for C++03 has been removed. The minimum requirement for this library is fully compliant C++11.
+#endif
+
+#endif
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/is_detected.hpp b/contrib/restricted/boost/math/include/boost/math/tools/is_detected.hpp
new file mode 100644
index 0000000000..8dfe86b740
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/tools/is_detected.hpp
@@ -0,0 +1,56 @@
+// Copyright Matt Borland 2021.
+// Use, modification and distribution are subject to 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)
+//
+// https://en.cppreference.com/w/cpp/experimental/is_detected
+
+#ifndef BOOST_MATH_TOOLS_IS_DETECTED_HPP
+#define BOOST_MATH_TOOLS_IS_DETECTED_HPP
+
+#include <type_traits>
+
+namespace boost { namespace math { namespace tools {
+
+template <typename...>
+using void_t = void;
+
+namespace detail {
+
+template <typename Default, typename AlwaysVoid, template<typename...> class Op, typename... Args>
+struct detector
+{
+ using value_t = std::false_type;
+ using type = Default;
+};
+
+template <typename Default, template<typename...> class Op, typename... Args>
+struct detector<Default, void_t<Op<Args...>>, Op, Args...>
+{
+ using value_t = std::true_type;
+ using type = Op<Args...>;
+};
+
+} // Namespace detail
+
+// Special type to indicate detection failure
+struct nonesuch
+{
+ nonesuch() = delete;
+ ~nonesuch() = delete;
+ nonesuch(const nonesuch&) = delete;
+ void operator=(const nonesuch&) = delete;
+};
+
+template <template<typename...> class Op, typename... Args>
+using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
+
+template <template<typename...> class Op, typename... Args>
+using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
+
+template <typename Default, template<typename...> class Op, typename... Args>
+using detected_or = detail::detector<Default, void, Op, Args...>;
+
+}}} // Namespaces boost math tools
+
+#endif // BOOST_MATH_TOOLS_IS_DETECTED_HPP
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/is_standalone.hpp b/contrib/restricted/boost/math/include/boost/math/tools/is_standalone.hpp
new file mode 100644
index 0000000000..343bbc20af
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/tools/is_standalone.hpp
@@ -0,0 +1,18 @@
+// Copyright Matt Borland 2021.
+// Use, modification and distribution are subject to 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_MATH_TOOLS_IS_STANDALONE_HPP
+#define BOOST_MATH_TOOLS_IS_STANDALONE_HPP
+
+#ifdef __has_include
+#if !__has_include(<boost/config.hpp>) || !__has_include(<boost/assert.hpp>) || !__has_include(<boost/lexical_cast.hpp>) || \
+ !__has_include(<boost/throw_exception.hpp>) || !__has_include(<boost/predef/other/endian.h>)
+# ifndef BOOST_MATH_STANDALONE
+# define BOOST_MATH_STANDALONE
+# endif
+#endif
+#endif
+
+#endif // BOOST_MATH_TOOLS_IS_STANDALONE_HPP
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/mp.hpp b/contrib/restricted/boost/math/include/boost/math/tools/mp.hpp
new file mode 100644
index 0000000000..3100a0bb67
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/tools/mp.hpp
@@ -0,0 +1,439 @@
+// Copyright Peter Dimov 2015-2021.
+// Copyright Matt Borland 2021.
+// Use, modification and distribution are subject to 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)
+//
+// Template metaprogramming classes and functions to replace MPL
+// Source: http://www.pdimov.com/cpp2/simple_cxx11_metaprogramming.html
+// Source: https://github.com/boostorg/mp11/
+
+#ifndef BOOST_MATH_TOOLS_MP
+#define BOOST_MATH_TOOLS_MP
+
+#include <type_traits>
+#include <cstddef>
+#include <utility>
+
+namespace boost { namespace math { namespace tools { namespace meta_programming {
+
+// Types:
+// Typelist
+template<typename... T>
+struct mp_list {};
+
+// Size_t
+template<std::size_t N>
+using mp_size_t = std::integral_constant<std::size_t, N>;
+
+// Boolean
+template<bool B>
+using mp_bool = std::integral_constant<bool, B>;
+
+// Identity
+template<typename T>
+struct mp_identity
+{
+ using type = T;
+};
+
+// Turns struct into quoted metafunction
+template<template<typename...> class F>
+struct mp_quote_trait
+{
+ template<typename... T>
+ using fn = typename F<T...>::type;
+};
+
+namespace detail {
+// Size
+template<typename L>
+struct mp_size_impl {};
+
+template<template<typename...> class L, typename... T> // Template template parameter must use class
+struct mp_size_impl<L<T...>>
+{
+ using type = std::integral_constant<std::size_t, sizeof...(T)>;
+};
+}
+
+template<typename T>
+using mp_size = typename detail::mp_size_impl<T>::type;
+
+namespace detail {
+// Front
+template<typename L>
+struct mp_front_impl {};
+
+template<template<typename...> class L, typename T1, typename... T>
+struct mp_front_impl<L<T1, T...>>
+{
+ using type = T1;
+};
+}
+
+template<typename T>
+using mp_front = typename detail::mp_front_impl<T>::type;
+
+namespace detail {
+// At
+// TODO - Use tree based lookup for larger typelists
+// http://odinthenerd.blogspot.com/2017/04/tree-based-lookup-why-kvasirmpl-is.html
+template<typename L, std::size_t>
+struct mp_at_c {};
+
+template<template<typename...> class L, typename T0, typename... T>
+struct mp_at_c<L<T0, T...>, 0>
+{
+ using type = T0;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename... T>
+struct mp_at_c<L<T0, T1, T...>, 1>
+{
+ using type = T1;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename... T>
+struct mp_at_c<L<T0, T1, T2, T...>, 2>
+{
+ using type = T2;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T...>, 3>
+{
+ using type = T3;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T4, T...>, 4>
+{
+ using type = T4;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T...>, 5>
+{
+ using type = T5;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
+ typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T...>, 6>
+{
+ using type = T6;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
+ typename T7, typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T...>, 7>
+{
+ using type = T7;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
+ typename T7, typename T8, typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T...>, 8>
+{
+ using type = T8;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
+ typename T7, typename T8, typename T9, typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>, 9>
+{
+ using type = T9;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
+ typename T7, typename T8, typename T9, typename T10, typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, 10>
+{
+ using type = T10;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
+ typename T7, typename T8, typename T9, typename T10, typename T11, typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T...>, 11>
+{
+ using type = T11;
+};
+
+template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
+ typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename... T>
+struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T...>, 12>
+{
+ using type = T12;
+};
+}
+
+template<typename L, std::size_t I>
+using mp_at_c = typename detail::mp_at_c<L, I>::type;
+
+template<typename L, typename I>
+using mp_at = typename detail::mp_at_c<L, I::value>::type;
+
+// Back
+template<typename L>
+using mp_back = mp_at_c<L, mp_size<L>::value - 1>;
+
+namespace detail {
+// Push back
+template<typename L, typename... T>
+struct mp_push_back_impl {};
+
+template<template<typename...> class L, typename... U, typename... T>
+struct mp_push_back_impl<L<U...>, T...>
+{
+ using type = L<U..., T...>;
+};
+}
+
+template<typename L, typename... T>
+using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
+
+namespace detail {
+// Push front
+template<typename L, typename... T>
+struct mp_push_front_impl {};
+
+template<template<typename...> class L, typename... U, typename... T>
+struct mp_push_front_impl<L<U...>, T...>
+{
+ using type = L<T..., U...>;
+};
+}
+
+template<typename L, typename... T>
+using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
+
+namespace detail{
+// If
+template<bool C, typename T, typename... E>
+struct mp_if_c_impl{};
+
+template<typename T, typename... E>
+struct mp_if_c_impl<true, T, E...>
+{
+ using type = T;
+};
+
+template<typename T, typename E>
+struct mp_if_c_impl<false, T, E>
+{
+ using type = E;
+};
+}
+
+template<bool C, typename T, typename... E>
+using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
+
+template<typename C, typename T, typename... E>
+using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
+
+namespace detail {
+// Find if
+template<typename L, template<typename...> class P>
+struct mp_find_if_impl {};
+
+template<template<typename...> class L, template<typename...> class P>
+struct mp_find_if_impl<L<>, P>
+{
+ using type = mp_size_t<0>;
+};
+
+template<typename L, template<typename...> class P>
+struct mp_find_if_impl_2
+{
+ using r = typename mp_find_if_impl<L, P>::type;
+ using type = mp_size_t<1 + r::value>;
+};
+
+template<template<typename...> class L, typename T1, typename... T, template<typename...> class P>
+struct mp_find_if_impl<L<T1, T...>, P>
+{
+ using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type;
+};
+}
+
+template<typename L, template<typename...> class P>
+using mp_find_if = typename detail::mp_find_if_impl<L, P>::type;
+
+template<typename L, typename Q>
+using mp_find_if_q = mp_find_if<L, Q::template fn>;
+
+namespace detail {
+// Append
+template<typename... L>
+struct mp_append_impl {};
+
+template<>
+struct mp_append_impl<>
+{
+ using type = mp_list<>;
+};
+
+template<template<typename...> class L, typename... T>
+struct mp_append_impl<L<T...>>
+{
+ using type = L<T...>;
+};
+
+template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2>
+struct mp_append_impl<L1<T1...>, L2<T2...>>
+{
+ using type = L1<T1..., T2...>;
+};
+
+template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
+ template<typename...> class L3, typename... T3>
+struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>>
+{
+ using type = L1<T1..., T2..., T3...>;
+};
+
+template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
+ template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4>
+struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>>
+{
+ using type = L1<T1..., T2..., T3..., T4...>;
+};
+
+template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
+ template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4,
+ template<typename...> class L5, typename... T5, typename... Lr>
+struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, Lr...>
+{
+ using type = typename mp_append_impl<L1<T1..., T2..., T3..., T4..., T5...>, Lr...>::type;
+};
+}
+
+template<typename... L>
+using mp_append = typename detail::mp_append_impl<L...>::type;
+
+namespace detail {
+// Remove if
+template<typename L, template<typename...> class P>
+struct mp_remove_if_impl{};
+
+template<template<typename...> class L, typename... T, template<typename...> class P>
+struct mp_remove_if_impl<L<T...>, P>
+{
+ template<typename U>
+ struct _f
+ {
+ using type = mp_if<P<U>, mp_list<>, mp_list<U>>;
+ };
+
+ using type = mp_append<L<>, typename _f<T>::type...>;
+};
+}
+
+template<typename L, template<class...> class P>
+using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;
+
+template<typename L, typename Q>
+using mp_remove_if_q = mp_remove_if<L, Q::template fn>;
+
+// Index sequence
+// Use C++14 index sequence if available
+#if defined(__cpp_lib_integer_sequence) && (__cpp_lib_integer_sequence >= 201304)
+template<std::size_t... I>
+using index_sequence = std::index_sequence<I...>;
+
+template<std::size_t N>
+using make_index_sequence = std::make_index_sequence<N>;
+
+template<typename... T>
+using index_sequence_for = std::index_sequence_for<T...>;
+
+#else
+
+template<typename T, T... I>
+struct integer_sequence {};
+
+template<std::size_t... I>
+using index_sequence = integer_sequence<std::size_t, I...>;
+
+namespace detail {
+
+template<bool C, typename T, typename E>
+struct iseq_if_c_impl {};
+
+template<typename T, typename F>
+struct iseq_if_c_impl<true, T, F>
+{
+ using type = T;
+};
+
+template<typename T, typename F>
+struct iseq_if_c_impl<false, T, F>
+{
+ using type = F;
+};
+
+template<bool C, typename T, typename F>
+using iseq_if_c = typename iseq_if_c_impl<C, T, F>::type;
+
+template<typename T>
+struct iseq_identity
+{
+ using type = T;
+};
+
+template<typename T1, typename T2>
+struct append_integer_sequence {};
+
+template<typename T, T... I, T... J>
+struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>>
+{
+ using type = integer_sequence<T, I..., (J + sizeof...(I))...>;
+};
+
+template<typename T, T N>
+struct make_integer_sequence_impl;
+
+template<typename T, T N>
+class make_integer_sequence_impl_
+{
+private:
+ static_assert(N >= 0, "N must not be negative");
+
+ static constexpr T M = N / 2;
+ static constexpr T R = N % 2;
+
+ using seq1 = typename make_integer_sequence_impl<T, M>::type;
+ using seq2 = typename append_integer_sequence<seq1, seq1>::type;
+ using seq3 = typename make_integer_sequence_impl<T, R>::type;
+ using seq4 = typename append_integer_sequence<seq2, seq3>::type;
+
+public:
+ using type = seq4;
+};
+
+template<typename T, T N>
+struct make_integer_sequence_impl
+{
+ using type = typename iseq_if_c<N == 0,
+ iseq_identity<integer_sequence<T>>,
+ iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>,
+ make_integer_sequence_impl_<T, N>>>::type;
+};
+
+} // namespace detail
+
+template<typename T, T N>
+using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;
+
+template<std::size_t N>
+using make_index_sequence = make_integer_sequence<std::size_t, N>;
+
+template<typename... T>
+using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;
+
+#endif
+
+}}}} // namespaces
+
+#endif // BOOST_MATH_TOOLS_MP
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/precision.hpp b/contrib/restricted/boost/math/include/boost/math/tools/precision.hpp
index 6538083b99..1bc35d9ae1 100644
--- a/contrib/restricted/boost/math/include/boost/math/tools/precision.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/tools/precision.hpp
@@ -10,17 +10,14 @@
#pragma once
#endif
-#include <boost/limits.hpp>
-#include <boost/assert.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/mpl/int.hpp>
-#include <boost/mpl/bool.hpp>
-#include <boost/mpl/if.hpp>
+#include <boost/math/tools/assert.hpp>
#include <boost/math/policies/policy.hpp>
-
-// These two are for LDBL_MAN_DIG:
-#include <limits.h>
-#include <math.h>
+#include <type_traits>
+#include <limits>
+#include <climits>
+#include <cmath>
+#include <cstdint>
+#include <cfloat> // LDBL_MANT_DIG
namespace boost{ namespace math
{
@@ -39,40 +36,29 @@ namespace tools
// See Conceptual Requirements for Real Number Types.
template <class T>
-inline BOOST_MATH_CONSTEXPR int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) BOOST_NOEXCEPT
+inline constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) noexcept
{
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
- BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::radix == 2 || ::std::numeric_limits<T>::radix == 10);
-#else
- BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
- BOOST_ASSERT(::std::numeric_limits<T>::radix == 2 || ::std::numeric_limits<T>::radix == 10);
-#endif
+ static_assert( ::std::numeric_limits<T>::is_specialized, "Type T must be specialized");
+ static_assert( ::std::numeric_limits<T>::radix == 2 || ::std::numeric_limits<T>::radix == 10, "Type T must have a radix of 2 or 10");
+
return std::numeric_limits<T>::radix == 2
? std::numeric_limits<T>::digits
: ((std::numeric_limits<T>::digits + 1) * 1000L) / 301L;
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
-#else
- BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
-#endif
+ static_assert( ::std::numeric_limits<T>::is_specialized, "Type T must be specialized");
return (std::numeric_limits<T>::max)();
} // Also used as a finite 'infinite' value for - and +infinity, for example:
// -max_value<double> = -1.79769e+308, max_value<double> = 1.79769e+308.
template <class T>
-inline BOOST_MATH_CONSTEXPR T min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
-#else
- BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
-#endif
+ static_assert( ::std::numeric_limits<T>::is_specialized, "Type T must be specialized");
+
return (std::numeric_limits<T>::min)();
}
@@ -86,13 +72,13 @@ namespace detail{
// For type float first:
//
template <class T>
-inline BOOST_MATH_CONSTEXPR T log_max_value(const mpl::int_<128>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T log_max_value(const std::integral_constant<int, 128>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
return 88.0f;
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T log_min_value(const mpl::int_<128>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T log_min_value(const std::integral_constant<int, 128>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
return -87.0f;
}
@@ -100,13 +86,13 @@ inline BOOST_MATH_CONSTEXPR T log_min_value(const mpl::int_<128>& BOOST_MATH_APP
// Now double:
//
template <class T>
-inline BOOST_MATH_CONSTEXPR T log_max_value(const mpl::int_<1024>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T log_max_value(const std::integral_constant<int, 1024>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
return 709.0;
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T log_min_value(const mpl::int_<1024>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T log_min_value(const std::integral_constant<int, 1024>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
return -708.0;
}
@@ -114,19 +100,19 @@ inline BOOST_MATH_CONSTEXPR T log_min_value(const mpl::int_<1024>& BOOST_MATH_AP
// 80 and 128-bit long doubles:
//
template <class T>
-inline BOOST_MATH_CONSTEXPR T log_max_value(const mpl::int_<16384>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T log_max_value(const std::integral_constant<int, 16384>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
return 11356.0L;
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T log_min_value(const mpl::int_<16384>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T log_min_value(const std::integral_constant<int, 16384>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
return -11355.0L;
}
template <class T>
-inline T log_max_value(const mpl::int_<0>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
+inline T log_max_value(const std::integral_constant<int, 0>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
{
BOOST_MATH_STD_USING
#ifdef __SUNPRO_CC
@@ -139,7 +125,7 @@ inline T log_max_value(const mpl::int_<0>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_T
}
template <class T>
-inline T log_min_value(const mpl::int_<0>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
+inline T log_min_value(const std::integral_constant<int, 0>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
{
BOOST_MATH_STD_USING
#ifdef __SUNPRO_CC
@@ -152,14 +138,14 @@ inline T log_min_value(const mpl::int_<0>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_T
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T epsilon(const mpl::true_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T epsilon(const std::true_type& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
{
return std::numeric_limits<T>::epsilon();
}
#if defined(__GNUC__) && ((LDBL_MANT_DIG == 106) || (__LDBL_MANT_DIG__ == 106))
template <>
-inline BOOST_MATH_CONSTEXPR long double epsilon<long double>(const mpl::true_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(long double)) BOOST_MATH_NOEXCEPT(long double)
+inline constexpr long double epsilon<long double>(const std::true_type& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(long double)) noexcept(std::is_floating_point<long double>::value)
{
// numeric_limits on Darwin (and elsewhere) tells lies here:
// the issue is that long double on a few platforms is
@@ -172,13 +158,13 @@ inline BOOST_MATH_CONSTEXPR long double epsilon<long double>(const mpl::true_& B
//
// This static assert fails for some unknown reason, so
// disabled for now...
- // BOOST_STATIC_ASSERT(std::numeric_limits<long double>::digits == 106);
+ // static_assert(std::numeric_limits<long double>::digits == 106);
return 2.4651903288156618919116517665087e-32L;
}
#endif
template <class T>
-inline T epsilon(const mpl::false_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
+inline T epsilon(const std::false_type& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
{
// Note: don't cache result as precision may vary at runtime:
BOOST_MATH_STD_USING // for ADL of std names
@@ -188,38 +174,38 @@ inline T epsilon(const mpl::false_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
template <class T>
struct log_limit_traits
{
- typedef typename mpl::if_c<
+ typedef typename std::conditional<
(std::numeric_limits<T>::radix == 2) &&
(std::numeric_limits<T>::max_exponent == 128
|| std::numeric_limits<T>::max_exponent == 1024
|| std::numeric_limits<T>::max_exponent == 16384),
- mpl::int_<(std::numeric_limits<T>::max_exponent > INT_MAX ? INT_MAX : static_cast<int>(std::numeric_limits<T>::max_exponent))>,
- mpl::int_<0>
+ std::integral_constant<int, (std::numeric_limits<T>::max_exponent > INT_MAX ? INT_MAX : static_cast<int>(std::numeric_limits<T>::max_exponent))>,
+ std::integral_constant<int, 0>
>::type tag_type;
- BOOST_STATIC_CONSTANT(bool, value = tag_type::value ? true : false);
- BOOST_STATIC_ASSERT(::std::numeric_limits<T>::is_specialized || (value == 0));
+ static constexpr bool value = tag_type::value ? true : false;
+ static_assert(::std::numeric_limits<T>::is_specialized || (value == 0), "Type T must be specialized or equal to 0");
};
template <class T, bool b> struct log_limit_noexcept_traits_imp : public log_limit_traits<T> {};
-template <class T> struct log_limit_noexcept_traits_imp<T, false> : public boost::integral_constant<bool, false> {};
+template <class T> struct log_limit_noexcept_traits_imp<T, false> : public std::integral_constant<bool, false> {};
template <class T>
-struct log_limit_noexcept_traits : public log_limit_noexcept_traits_imp<T, BOOST_MATH_IS_FLOAT(T)> {};
+struct log_limit_noexcept_traits : public log_limit_noexcept_traits_imp<T, std::is_floating_point<T>::value> {};
} // namespace detail
-#ifdef BOOST_MSVC
+#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4309)
#endif
template <class T>
-inline BOOST_MATH_CONSTEXPR T log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT_IF(detail::log_limit_noexcept_traits<T>::value)
+inline constexpr T log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(detail::log_limit_noexcept_traits<T>::value)
{
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
return detail::log_max_value<T>(typename detail::log_limit_traits<T>::tag_type());
#else
- BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
+ BOOST_MATH_ASSERT(::std::numeric_limits<T>::is_specialized);
BOOST_MATH_STD_USING
static const T val = log((std::numeric_limits<T>::max)());
return val;
@@ -227,56 +213,56 @@ inline BOOST_MATH_CONSTEXPR T log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT_IF(detail::log_limit_noexcept_traits<T>::value)
+inline constexpr T log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(detail::log_limit_noexcept_traits<T>::value)
{
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
return detail::log_min_value<T>(typename detail::log_limit_traits<T>::tag_type());
#else
- BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
+ BOOST_MATH_ASSERT(::std::numeric_limits<T>::is_specialized);
BOOST_MATH_STD_USING
static const T val = log((std::numeric_limits<T>::min)());
return val;
#endif
}
-#ifdef BOOST_MSVC
+#ifdef _MSC_VER
#pragma warning(pop)
#endif
template <class T>
-inline BOOST_MATH_CONSTEXPR T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) noexcept(std::is_floating_point<T>::value)
{
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- return detail::epsilon<T>(mpl::bool_< ::std::numeric_limits<T>::is_specialized>());
+ return detail::epsilon<T>(std::integral_constant<bool, ::std::numeric_limits<T>::is_specialized>());
#else
return ::std::numeric_limits<T>::is_specialized ?
- detail::epsilon<T>(mpl::true_()) :
- detail::epsilon<T>(mpl::false_());
+ detail::epsilon<T>(std::true_type()) :
+ detail::epsilon<T>(std::false_type());
#endif
}
namespace detail{
template <class T>
-inline BOOST_MATH_CONSTEXPR T root_epsilon_imp(const mpl::int_<24>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T root_epsilon_imp(const std::integral_constant<int, 24>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(0.00034526698300124390839884978618400831996329879769945L);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T root_epsilon_imp(const T*, const mpl::int_<53>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T root_epsilon_imp(const T*, const std::integral_constant<int, 53>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(0.1490116119384765625e-7L);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T root_epsilon_imp(const T*, const mpl::int_<64>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T root_epsilon_imp(const T*, const std::integral_constant<int, 64>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(0.32927225399135962333569506281281311031656150598474e-9L);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T root_epsilon_imp(const T*, const mpl::int_<113>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T root_epsilon_imp(const T*, const std::integral_constant<int, 113>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(0.1387778780781445675529539585113525390625e-16L);
}
@@ -290,32 +276,32 @@ inline T root_epsilon_imp(const T*, const Tag&)
}
template <class T>
-inline T root_epsilon_imp(const T*, const mpl::int_<0>&)
+inline T root_epsilon_imp(const T*, const std::integral_constant<int, 0>&)
{
BOOST_MATH_STD_USING
return sqrt(tools::epsilon<T>());
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T cbrt_epsilon_imp(const mpl::int_<24>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T cbrt_epsilon_imp(const std::integral_constant<int, 24>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(0.0049215666011518482998719164346805794944150447839903L);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T cbrt_epsilon_imp(const T*, const mpl::int_<53>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T cbrt_epsilon_imp(const T*, const std::integral_constant<int, 53>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(6.05545445239333906078989272793696693569753008995e-6L);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T cbrt_epsilon_imp(const T*, const mpl::int_<64>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T cbrt_epsilon_imp(const T*, const std::integral_constant<int, 64>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(4.76837158203125e-7L);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T cbrt_epsilon_imp(const T*, const mpl::int_<113>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T cbrt_epsilon_imp(const T*, const std::integral_constant<int, 113>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(5.7749313854154005630396773604745549542403508090496e-12L);
}
@@ -329,32 +315,32 @@ inline T cbrt_epsilon_imp(const T*, const Tag&)
}
template <class T>
-inline T cbrt_epsilon_imp(const T*, const mpl::int_<0>&)
+inline T cbrt_epsilon_imp(const T*, const std::integral_constant<int, 0>&)
{
BOOST_MATH_STD_USING;
return pow(tools::epsilon<T>(), T(1) / 3);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T forth_root_epsilon_imp(const T*, const mpl::int_<24>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T forth_root_epsilon_imp(const T*, const std::integral_constant<int, 24>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(0.018581361171917516667460937040007436176452688944747L);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T forth_root_epsilon_imp(const T*, const mpl::int_<53>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T forth_root_epsilon_imp(const T*, const std::integral_constant<int, 53>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(0.0001220703125L);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T forth_root_epsilon_imp(const T*, const mpl::int_<64>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T forth_root_epsilon_imp(const T*, const std::integral_constant<int, 64>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(0.18145860519450699870567321328132261891067079047605e-4L);
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T forth_root_epsilon_imp(const T*, const mpl::int_<113>&) BOOST_MATH_NOEXCEPT(T)
+inline constexpr T forth_root_epsilon_imp(const T*, const std::integral_constant<int, 113>&) noexcept(std::is_floating_point<T>::value)
{
return static_cast<T>(0.37252902984619140625e-8L);
}
@@ -368,7 +354,7 @@ inline T forth_root_epsilon_imp(const T*, const Tag&)
}
template <class T>
-inline T forth_root_epsilon_imp(const T*, const mpl::int_<0>&)
+inline T forth_root_epsilon_imp(const T*, const std::integral_constant<int, 0>&)
{
BOOST_MATH_STD_USING
return sqrt(sqrt(tools::epsilon<T>()));
@@ -377,26 +363,26 @@ inline T forth_root_epsilon_imp(const T*, const mpl::int_<0>&)
template <class T>
struct root_epsilon_traits
{
- typedef mpl::int_< (::std::numeric_limits<T>::radix == 2) ? std::numeric_limits<T>::digits : 0> tag_type;
- BOOST_STATIC_CONSTANT(bool, has_noexcept = (tag_type::value == 113) || (tag_type::value == 64) || (tag_type::value == 53) || (tag_type::value == 24));
+ typedef std::integral_constant<int, (::std::numeric_limits<T>::radix == 2) && (::std::numeric_limits<T>::digits != INT_MAX) ? std::numeric_limits<T>::digits : 0> tag_type;
+ static constexpr bool has_noexcept = (tag_type::value == 113) || (tag_type::value == 64) || (tag_type::value == 53) || (tag_type::value == 24);
};
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T root_epsilon() BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && detail::root_epsilon_traits<T>::has_noexcept)
+inline constexpr T root_epsilon() noexcept(std::is_floating_point<T>::value && detail::root_epsilon_traits<T>::has_noexcept)
{
return detail::root_epsilon_imp(static_cast<T const*>(0), typename detail::root_epsilon_traits<T>::tag_type());
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T cbrt_epsilon() BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && detail::root_epsilon_traits<T>::has_noexcept)
+inline constexpr T cbrt_epsilon() noexcept(std::is_floating_point<T>::value && detail::root_epsilon_traits<T>::has_noexcept)
{
return detail::cbrt_epsilon_imp(static_cast<T const*>(0), typename detail::root_epsilon_traits<T>::tag_type());
}
template <class T>
-inline BOOST_MATH_CONSTEXPR T forth_root_epsilon() BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && detail::root_epsilon_traits<T>::has_noexcept)
+inline constexpr T forth_root_epsilon() noexcept(std::is_floating_point<T>::value && detail::root_epsilon_traits<T>::has_noexcept)
{
return detail::forth_root_epsilon_imp(static_cast<T const*>(0), typename detail::root_epsilon_traits<T>::tag_type());
}
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/promotion.hpp b/contrib/restricted/boost/math/include/boost/math/tools/promotion.hpp
index 494d7f99e2..3e51768e6b 100644
--- a/contrib/restricted/boost/math/include/boost/math/tools/promotion.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/tools/promotion.hpp
@@ -22,22 +22,8 @@
#pragma once
#endif
-// Boost type traits:
#include <boost/math/tools/config.hpp>
-#include <boost/type_traits/is_floating_point.hpp> // for boost::is_floating_point;
-#include <boost/type_traits/is_integral.hpp> // for boost::is_integral
-#include <boost/type_traits/is_convertible.hpp> // for boost::is_convertible
-#include <boost/type_traits/is_same.hpp>// for boost::is_same
-#include <boost/type_traits/remove_cv.hpp>// for boost::remove_cv
-// Boost Template meta programming:
-#include <boost/mpl/if.hpp> // for boost::mpl::if_c.
-#include <boost/mpl/and.hpp> // for boost::mpl::if_c.
-#include <boost/mpl/or.hpp> // for boost::mpl::if_c.
-#include <boost/mpl/not.hpp> // for boost::mpl::if_c.
-
-#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
-#include <boost/static_assert.hpp>
-#endif
+#include <type_traits>
namespace boost
{
@@ -68,31 +54,31 @@ namespace boost
template <class T>
struct promote_arg
{ // If T is integral type, then promote to double.
- typedef typename mpl::if_<is_integral<T>, double, T>::type type;
+ using type = typename std::conditional<std::is_integral<T>::value, double, T>::type;
};
- // These full specialisations reduce mpl::if_ usage and speed up
+ // These full specialisations reduce std::conditional usage and speed up
// compilation:
- template <> struct promote_arg<float> { typedef float type; };
- template <> struct promote_arg<double>{ typedef double type; };
- template <> struct promote_arg<long double> { typedef long double type; };
- template <> struct promote_arg<int> { typedef double type; };
+ template <> struct promote_arg<float> { using type = float; };
+ template <> struct promote_arg<double>{ using type = double; };
+ template <> struct promote_arg<long double> { using type = long double; };
+ template <> struct promote_arg<int> { using type = double; };
template <class T1, class T2>
struct promote_args_2
{ // Promote, if necessary, & pick the wider of the two floating-point types.
// for both parameter types, if integral promote to double.
- typedef typename promote_arg<T1>::type T1P; // T1 perhaps promoted.
- typedef typename promote_arg<T2>::type T2P; // T2 perhaps promoted.
+ using T1P = typename promote_arg<T1>::type; // T1 perhaps promoted.
+ using T2P = typename promote_arg<T2>::type; // T2 perhaps promoted.
- typedef typename mpl::if_<
- typename mpl::and_<is_floating_point<T1P>, is_floating_point<T2P> >::type, // both T1P and T2P are floating-point?
+ using type = typename std::conditional<
+ std::is_floating_point<T1P>::value && std::is_floating_point<T2P>::value, // both T1P and T2P are floating-point?
#ifdef BOOST_MATH_USE_FLOAT128
- typename mpl::if_< typename mpl::or_<is_same<__float128, T1P>, is_same<__float128, T2P> >::type, // either long double?
+ typename std::conditional<std::is_same<__float128, T1P>::value || std::is_same<__float128, T2P>::value, // either long double?
__float128,
#endif
- typename mpl::if_< typename mpl::or_<is_same<long double, T1P>, is_same<long double, T2P> >::type, // either long double?
+ typename std::conditional<std::is_same<long double, T1P>::value || std::is_same<long double, T2P>::value, // either long double?
long double, // then result type is long double.
- typename mpl::if_< typename mpl::or_<is_same<double, T1P>, is_same<double, T2P> >::type, // either double?
+ typename std::conditional<std::is_same<double, T1P>::value || std::is_same<double, T2P>::value, // either double?
double, // result type is double.
float // else result type is float.
>::type
@@ -101,51 +87,51 @@ namespace boost
#endif
>::type,
// else one or the other is a user-defined type:
- typename mpl::if_< typename mpl::and_<mpl::not_<is_floating_point<T2P> >, ::boost::is_convertible<T1P, T2P> >, T2P, T1P>::type>::type type;
+ typename std::conditional<!std::is_floating_point<T2P>::value && std::is_convertible<T1P, T2P>::value, T2P, T1P>::type>::type;
}; // promote_arg2
- // These full specialisations reduce mpl::if_ usage and speed up
+ // These full specialisations reduce std::conditional usage and speed up
// compilation:
- template <> struct promote_args_2<float, float> { typedef float type; };
- template <> struct promote_args_2<double, double>{ typedef double type; };
- template <> struct promote_args_2<long double, long double> { typedef long double type; };
- template <> struct promote_args_2<int, int> { typedef double type; };
- template <> struct promote_args_2<int, float> { typedef double type; };
- template <> struct promote_args_2<float, int> { typedef double type; };
- template <> struct promote_args_2<int, double> { typedef double type; };
- template <> struct promote_args_2<double, int> { typedef double type; };
- template <> struct promote_args_2<int, long double> { typedef long double type; };
- template <> struct promote_args_2<long double, int> { typedef long double type; };
- template <> struct promote_args_2<float, double> { typedef double type; };
- template <> struct promote_args_2<double, float> { typedef double type; };
- template <> struct promote_args_2<float, long double> { typedef long double type; };
- template <> struct promote_args_2<long double, float> { typedef long double type; };
- template <> struct promote_args_2<double, long double> { typedef long double type; };
- template <> struct promote_args_2<long double, double> { typedef long double type; };
+ template <> struct promote_args_2<float, float> { using type = float; };
+ template <> struct promote_args_2<double, double>{ using type = double; };
+ template <> struct promote_args_2<long double, long double> { using type = long double; };
+ template <> struct promote_args_2<int, int> { using type = double; };
+ template <> struct promote_args_2<int, float> { using type = double; };
+ template <> struct promote_args_2<float, int> { using type = double; };
+ template <> struct promote_args_2<int, double> { using type = double; };
+ template <> struct promote_args_2<double, int> { using type = double; };
+ template <> struct promote_args_2<int, long double> { using type = long double; };
+ template <> struct promote_args_2<long double, int> { using type = long double; };
+ template <> struct promote_args_2<float, double> { using type = double; };
+ template <> struct promote_args_2<double, float> { using type = double; };
+ template <> struct promote_args_2<float, long double> { using type = long double; };
+ template <> struct promote_args_2<long double, float> { using type = long double; };
+ template <> struct promote_args_2<double, long double> { using type = long double; };
+ template <> struct promote_args_2<long double, double> { using type = long double; };
template <class T1, class T2=float, class T3=float, class T4=float, class T5=float, class T6=float>
struct promote_args
{
- typedef typename promote_args_2<
- typename remove_cv<T1>::type,
+ using type = typename promote_args_2<
+ typename std::remove_cv<T1>::type,
typename promote_args_2<
- typename remove_cv<T2>::type,
+ typename std::remove_cv<T2>::type,
typename promote_args_2<
- typename remove_cv<T3>::type,
+ typename std::remove_cv<T3>::type,
typename promote_args_2<
- typename remove_cv<T4>::type,
+ typename std::remove_cv<T4>::type,
typename promote_args_2<
- typename remove_cv<T5>::type, typename remove_cv<T6>::type
+ typename std::remove_cv<T5>::type, typename std::remove_cv<T6>::type
>::type
>::type
>::type
>::type
- >::type type;
+ >::type;
#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
//
// Guard against use of long double if it's not supported:
//
- BOOST_STATIC_ASSERT_MSG((0 == ::boost::is_same<type, long double>::value), "Sorry, but this platform does not have sufficient long double support for the special functions to be reliably implemented.");
+ static_assert((0 == std::is_same<type, long double>::value), "Sorry, but this platform does not have sufficient long double support for the special functions to be reliably implemented.");
#endif
};
@@ -157,21 +143,21 @@ namespace boost
template <class T1, class T2=float, class T3=float, class T4=float, class T5=float, class T6=float>
struct promote_args_permissive
{
- typedef typename promote_args_2<
- typename remove_cv<T1>::type,
+ using type = typename promote_args_2<
+ typename std::remove_cv<T1>::type,
typename promote_args_2<
- typename remove_cv<T2>::type,
+ typename std::remove_cv<T2>::type,
typename promote_args_2<
- typename remove_cv<T3>::type,
+ typename std::remove_cv<T3>::type,
typename promote_args_2<
- typename remove_cv<T4>::type,
+ typename std::remove_cv<T4>::type,
typename promote_args_2<
- typename remove_cv<T5>::type, typename remove_cv<T6>::type
+ typename std::remove_cv<T5>::type, typename std::remove_cv<T6>::type
>::type
>::type
>::type
>::type
- >::type type;
+ >::type;
};
} // namespace tools
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/real_cast.hpp b/contrib/restricted/boost/math/include/boost/math/tools/real_cast.hpp
index 873e60259b..a68738b347 100644
--- a/contrib/restricted/boost/math/include/boost/math/tools/real_cast.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/tools/real_cast.hpp
@@ -17,7 +17,7 @@ namespace boost{ namespace math
namespace tools
{
template <class To, class T>
- inline BOOST_MATH_CONSTEXPR To real_cast(T t) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && BOOST_MATH_IS_FLOAT(To))
+ inline constexpr To real_cast(T t) noexcept(BOOST_MATH_IS_FLOAT(T) && BOOST_MATH_IS_FLOAT(To))
{
return static_cast<To>(t);
}
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/throw_exception.hpp b/contrib/restricted/boost/math/include/boost/math/tools/throw_exception.hpp
new file mode 100644
index 0000000000..56a2c9c3e0
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/tools/throw_exception.hpp
@@ -0,0 +1,22 @@
+// (C) Copyright Matt Borland 2021.
+// Use, modification and distribution are subject to 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_MATH_TOOLS_THROW_EXCEPTION_HPP
+#define BOOST_MATH_TOOLS_THROW_EXCEPTION_HPP
+
+#include <boost/math/tools/is_standalone.hpp>
+
+#ifndef BOOST_MATH_STANDALONE
+
+#include <boost/throw_exception.hpp>
+#define BOOST_MATH_THROW_EXCEPTION(expr) boost::throw_exception(expr);
+
+#else // Standalone mode - use standard library facilities
+
+#define BOOST_MATH_THROW_EXCEPTION(expr) throw expr;
+
+#endif // BOOST_MATH_STANDALONE
+
+#endif // BOOST_MATH_TOOLS_THROW_EXCEPTION_HPP
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/traits.hpp b/contrib/restricted/boost/math/include/boost/math/tools/traits.hpp
new file mode 100644
index 0000000000..cd40f7f1f3
--- /dev/null
+++ b/contrib/restricted/boost/math/include/boost/math/tools/traits.hpp
@@ -0,0 +1,128 @@
+// Copyright John Maddock 2007.
+// Copyright Matt Borland 2021.
+// Use, modification and distribution are subject to 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)
+
+/*
+This header defines two traits classes, both in namespace boost::math::tools.
+
+is_distribution<D>::value is true iff D has overloaded "cdf" and
+"quantile" functions, plus member typedefs value_type and policy_type.
+It's not much of a definitive test frankly,
+but if it looks like a distribution and quacks like a distribution
+then it must be a distribution.
+
+is_scaled_distribution<D>::value is true iff D is a distribution
+as defined above, and has member functions "scale" and "location".
+
+*/
+
+#ifndef BOOST_STATS_IS_DISTRIBUTION_HPP
+#define BOOST_STATS_IS_DISTRIBUTION_HPP
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include <type_traits>
+
+namespace boost{ namespace math{ namespace tools{
+
+namespace detail{
+
+#define BOOST_MATH_HAS_NAMED_TRAIT(trait, name) \
+template <typename T> \
+class trait \
+{ \
+private: \
+ using yes = char; \
+ struct no { char x[2]; }; \
+ \
+ template <typename U> \
+ static yes test(typename U::name* = nullptr); \
+ \
+ template <typename U> \
+ static no test(...); \
+ \
+public: \
+ static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char)); \
+};
+
+BOOST_MATH_HAS_NAMED_TRAIT(has_value_type, value_type)
+BOOST_MATH_HAS_NAMED_TRAIT(has_policy_type, policy_type)
+BOOST_MATH_HAS_NAMED_TRAIT(has_backend_type, backend_type)
+
+template <typename D>
+char cdf(const D& ...);
+template <typename D>
+char quantile(const D& ...);
+
+template <typename D>
+struct has_cdf
+{
+ static D d;
+ static constexpr bool value = sizeof(cdf(d, 0.0f)) != 1;
+};
+
+template <typename D>
+struct has_quantile
+{
+ static D d;
+ static constexpr bool value = sizeof(quantile(d, 0.0f)) != 1;
+};
+
+template <typename D>
+struct is_distribution_imp
+{
+ static constexpr bool value =
+ has_quantile<D>::value
+ && has_cdf<D>::value
+ && has_value_type<D>::value
+ && has_policy_type<D>::value;
+};
+
+template <typename sig, sig val>
+struct result_tag{};
+
+template <typename D>
+double test_has_location(const volatile result_tag<typename D::value_type (D::*)()const, &D::location>*);
+template <typename D>
+char test_has_location(...);
+
+template <typename D>
+double test_has_scale(const volatile result_tag<typename D::value_type (D::*)()const, &D::scale>*);
+template <typename D>
+char test_has_scale(...);
+
+template <typename D, bool b>
+struct is_scaled_distribution_helper
+{
+ static constexpr bool value = false;
+};
+
+template <typename D>
+struct is_scaled_distribution_helper<D, true>
+{
+ static constexpr bool value =
+ (sizeof(test_has_location<D>(0)) != 1)
+ &&
+ (sizeof(test_has_scale<D>(0)) != 1);
+};
+
+template <typename D>
+struct is_scaled_distribution_imp
+{
+ static constexpr bool value = (::boost::math::tools::detail::is_scaled_distribution_helper<D, ::boost::math::tools::detail::is_distribution_imp<D>::value>::value);
+};
+
+} // namespace detail
+
+template <typename T> struct is_distribution : public std::integral_constant<bool, ::boost::math::tools::detail::is_distribution_imp<T>::value> {};
+template <typename T> struct is_scaled_distribution : public std::integral_constant<bool, ::boost::math::tools::detail::is_scaled_distribution_imp<T>::value> {};
+
+}}}
+
+#endif
+
+
diff --git a/contrib/restricted/boost/math/include/boost/math/tools/user.hpp b/contrib/restricted/boost/math/include/boost/math/tools/user.hpp
index 08a7e53d9e..6d3df000c0 100644
--- a/contrib/restricted/boost/math/include/boost/math/tools/user.hpp
+++ b/contrib/restricted/boost/math/include/boost/math/tools/user.hpp
@@ -54,7 +54,7 @@
//
// #define BOOST_MATH_EVALUATION_ERROR_POLICY throw_on_error
//
-// Underfow:
+// Underflow:
//
// #define BOOST_MATH_UNDERFLOW_ERROR_POLICY ignore_error
//
@@ -84,7 +84,7 @@
//
// #define BOOST_MATH_ASSERT_UNDEFINED_POLICY true
//
-// Maximum series iterstions permitted:
+// Maximum series iterations permitted:
//
// #define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 1000000
//
diff --git a/contrib/restricted/boost/multiprecision/LICENSE b/contrib/restricted/boost/multiprecision/LICENSE
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/LICENSE
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/contrib/restricted/boost/multiprecision/README.md b/contrib/restricted/boost/multiprecision/README.md
new file mode 100644
index 0000000000..07a480377f
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/README.md
@@ -0,0 +1,65 @@
+Boost Multiprecision Library
+============================
+
+>ANNOUNCEMENT: Support for C++11 will be deprecated in this library starting in July 2023 (Boost 1.82).
+>New features will require *at least* C++14, as will existing features starting with the deprecation release.
+
+| | Master | Develop |
+|------------------|----------|-------------|
+| Drone | [![Build Status](https://drone.cpp.al/api/badges/boostorg/multiprecision/status.svg?ref=refs/heads/master)](https://drone.cpp.al/boostorg/multiprecision) | [![Build Status](https://drone.cpp.al/api/badges/boostorg/multiprecision/status.svg)](https://drone.cpp.al/boostorg/multiprecision) |
+| Github Actions | [![Build Status](https://github.com/boostorg/multiprecision/workflows/multiprecision/badge.svg?branch=master)](https://github.com/boostorg/multiprecision/actions) | [![Build Status](https://github.com/boostorg/multiprecision/workflows/multiprecision/badge.svg?branch=develop)](https://github.com/boostorg/multiprecision/actions) |
+
+ The Multiprecision Library provides integer, rational, floating-point, complex and interval number types in C++ that have more range and
+ precision than C++'s ordinary built-in types. The big number types in Multiprecision can be used with a wide selection of basic
+ mathematical operations, elementary transcendental functions as well as the functions in Boost.Math. The Multiprecision types can
+ also interoperate with the built-in types in C++ using clearly defined conversion rules. This allows Boost.Multiprecision to be
+ used for all kinds of mathematical calculations involving integer, rational and floating-point types requiring extended range and precision.
+
+Multiprecision consists of a generic interface to the mathematics of large numbers as well as a selection of big number back ends, with
+support for integer, rational and floating-point types. Boost.Multiprecision provides a selection of back ends provided off-the-rack in
+including interfaces to GMP, MPFR, MPIR, TomMath as well as its own collection of Boost-licensed, header-only back ends for integers,
+rationals, floats and complex. In addition, user-defined back ends can be created and used with the interface of Multiprecision, provided the class implementation adheres to the necessary concepts.
+
+Depending upon the number type, precision may be arbitrarily large (limited only by available memory), fixed at compile time
+(for example 50 or 100 decimal digits), or a variable controlled at run-time by member functions. The types are expression-template-enabled
+for better performance than naive user-defined types.
+
+The full documentation is available on [boost.org](http://www.boost.org/doc/libs/release/libs/multiprecision/index.html).
+
+## Standalone (BETA) ##
+
+Defining BOOST_MP_STANDALONE allows Boost.Multiprecision to be used with the only dependency being [Boost.Config](https://github.com/boostorg/config). Our package on this page
+already includes a copy of Boost.Config so no other donwloads are required. Some functionality is reduced in this mode. A static_assert message will alert you if a particular feature has been disabled by standalone mode.
+[Boost.Math](https://github.com/boostorg/math) standalone mode is compatiable, and recommended if special functions is required.
+
+## Support, bugs and feature requests ##
+
+Bugs and feature requests can be reported through the [Gitub issue tracker](https://github.com/boostorg/multiprecision/issues)
+(see [open issues](https://github.com/boostorg/multiprecision/issues) and
+[closed issues](https://github.com/boostorg/multiprecision/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aclosed)).
+
+You can submit your changes through a [pull request](https://github.com/boostorg/multiprecision/pulls).
+
+There is no mailing-list specific to Boost Multiprecision, although you can use the general-purpose Boost [mailing-list](http://lists.boost.org/mailman/listinfo.cgi/boost-users) using the tag [multiprecision].
+
+
+## Development ##
+
+Clone the whole boost project, which includes the individual Boost projects as submodules ([see boost+git doc](https://github.com/boostorg/boost/wiki/Getting-Started)):
+
+ git clone https://github.com/boostorg/boost
+ cd boost
+ git submodule update --init
+
+The Boost Multiprecision Library is located in `libs/multiprecision/`.
+
+### Running tests ###
+First, build the B2 engine by running `bootstrap.sh` in the root of the boost directory. This will generate B2 configuration in `project-config.jam`.
+
+ ./bootstrap.sh
+
+Now make sure you are in `libs/multiprecision/test`. You can either run all the tests listed in `Jamfile.v2` or run a single test:
+
+ ../../../b2 <- run all tests
+ ../../../b2 test_complex <- single test
+
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int.hpp
index 59f6c955d8..103136e16b 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int.hpp
@@ -1,80 +1,98 @@
-//////////////////3/////////////////////////////////////////////
-// Copyright 2012 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_
+////////////////////////////////////////////////////////////////
+// Copyright 2012 - 2022 John Maddock.
+// Copyright 2022 Christopher Kormanyos.
+// Distributed under the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt
+// or copy at https://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MP_CPP_INT_HPP
#define BOOST_MP_CPP_INT_HPP
+#include <cstdint>
+#include <cstring>
#include <iostream>
#include <iomanip>
-#include <boost/cstdint.hpp>
+#include <type_traits>
+#include <string>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/endian.hpp>
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/detail/integer_ops.hpp>
-#include <boost/array.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/multiprecision/detail/rebind.hpp>
#include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
#include <boost/multiprecision/rational_adaptor.hpp>
#include <boost/multiprecision/traits/is_byte_container.hpp>
-#include <boost/detail/endian.hpp>
-#include <boost/integer/static_min_max.hpp>
-#include <boost/type_traits/common_type.hpp>
-#include <boost/type_traits/make_signed.hpp>
#include <boost/multiprecision/cpp_int/checked.hpp>
-#ifdef BOOST_MP_USER_DEFINED_LITERALS
+#include <boost/multiprecision/detail/constexpr.hpp>
+#include <boost/multiprecision/detail/float128_functions.hpp>
#include <boost/multiprecision/cpp_int/value_pack.hpp>
-#endif
-
-namespace boost{
-namespace multiprecision{
-namespace backends{
-
- using boost::enable_if;
+#include <boost/multiprecision/detail/empty_value.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+#include <boost/multiprecision/detail/fpclassify.hpp>
+namespace boost {
+namespace multiprecision {
+namespace backends {
#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)
+#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
+#if defined(__GNUC__) && !defined(__clang__)
+// see https://github.com/boostorg/multiprecision/issues/413
+// and https://github.com/boostorg/multiprecision/issues/431
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
-template <unsigned MinBits = 0, unsigned MaxBits = 0, boost::multiprecision::cpp_integer_type SignType = signed_magnitude, cpp_int_check_type Checked = unchecked, class Allocator = typename mpl::if_c<MinBits && (MinBits == MaxBits), void, std::allocator<limb_type> >::type >
+template <std::size_t MinBits = 0, std::size_t MaxBits = 0, boost::multiprecision::cpp_integer_type SignType = signed_magnitude, cpp_int_check_type Checked = unchecked, class Allocator = typename std::conditional<MinBits && (MinBits == MaxBits), void, std::allocator<limb_type> >::type>
struct cpp_int_backend;
} // namespace backends
namespace detail {
- template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
- struct is_byte_container<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > : public boost::false_type {};
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+struct is_byte_container<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > : public std::false_type
+{};
} // namespace detail
-namespace backends{
+namespace backends {
+
+namespace detail {
+ template <std::size_t Value1, std::size_t Value2>
+ struct static_unsigned_max
+ {
+ static constexpr std::size_t value = (Value1 > Value2) ? Value1 : Value2;
+ };
+} // Namespace detail
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, bool trivial = false>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, bool trivial = false>
struct cpp_int_base;
//
// Traits class determines the maximum and minimum precision values:
//
-template <class T> struct max_precision;
+template <class T>
+struct max_precision;
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
struct max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
{
- static const unsigned value = is_void<Allocator>::value ?
- static_unsigned_max<MinBits, MaxBits>::value
- : (((MaxBits >= MinBits) && MaxBits) ? MaxBits : UINT_MAX);
+ static constexpr std::size_t value = std::is_void<Allocator>::value ? detail::static_unsigned_max<MinBits, MaxBits>::value
+ : (((MaxBits >= MinBits) && MaxBits) ? MaxBits : SIZE_MAX);
};
-template <class T> struct min_precision;
+template <class T>
+struct min_precision;
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
struct min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
{
- static const unsigned value = (is_void<Allocator>::value ? static_unsigned_max<MinBits, MaxBits>::value : MinBits);
+ static constexpr std::size_t value = (std::is_void<Allocator>::value ? detail::static_unsigned_max<MinBits, MaxBits>::value : MinBits);
};
//
// Traits class determines whether the number of bits precision requested could fit in a native type,
@@ -83,31 +101,32 @@ struct min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Alloca
template <class T>
struct is_trivial_cpp_int
{
- static const bool value = false;
+ static constexpr bool value = false;
};
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
struct is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
{
- typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> self;
- static const bool value = is_void<Allocator>::value && (max_precision<self>::value <= (sizeof(double_limb_type) * CHAR_BIT) - (SignType == signed_packed ? 1 : 0));
+ using self = cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>;
+ static constexpr bool value = std::is_void<Allocator>::value && (max_precision<self>::value <= (sizeof(double_limb_type) * CHAR_BIT) - (SignType == signed_packed ? 1 : 0));
};
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
struct is_trivial_cpp_int<cpp_int_base<MinBits, MaxBits, SignType, Checked, Allocator, true> >
{
- static const bool value = true;
+ static constexpr bool value = true;
};
} // namespace backends
//
// Traits class to determine whether a cpp_int_backend is signed or not:
//
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
struct is_unsigned_number<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
- : public mpl::bool_<(SignType == unsigned_magnitude) || (SignType == unsigned_packed)>{};
+ : public std::integral_constant<bool, (SignType == unsigned_magnitude) || (SignType == unsigned_packed)>
+{};
-namespace backends{
+namespace backends {
//
// Traits class determines whether T should be implicitly convertible to U, or
// whether the constructor should be made explicit. The latter happens if we
@@ -116,194 +135,294 @@ namespace backends{
template <class T, class U>
struct is_implicit_cpp_int_conversion;
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
struct is_implicit_cpp_int_conversion<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >
{
- typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> t1;
- typedef cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> t2;
- static const bool value =
- (is_signed_number<t2>::value || !is_signed_number<t1>::value)
- && (max_precision<t1>::value <= max_precision<t2>::value);
+ using t1 = cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>;
+ using t2 = cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>;
+ static constexpr bool value =
+ (is_signed_number<t2>::value || !is_signed_number<t1>::value) && (max_precision<t1>::value <= max_precision<t2>::value);
};
//
// Traits class to determine whether operations on a cpp_int may throw:
//
template <class T>
-struct is_non_throwing_cpp_int : public mpl::false_{};
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType>
-struct is_non_throwing_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, unchecked, void> > : public mpl::true_ {};
+struct is_non_throwing_cpp_int : public std::integral_constant<bool, false>
+{};
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType>
+struct is_non_throwing_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, unchecked, void> > : public std::integral_constant<bool, true>
+{};
//
// Traits class, determines whether the cpp_int is fixed precision or not:
//
template <class T>
struct is_fixed_precision;
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
struct is_fixed_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
- : public mpl::bool_<max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value != UINT_MAX> {};
+ : public std::integral_constant<bool, max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value != SIZE_MAX>
+{};
-namespace detail{
+namespace detail {
-inline void verify_new_size(unsigned new_size, unsigned min_size, const mpl::int_<checked>&)
+inline BOOST_MP_CXX14_CONSTEXPR void verify_new_size(std::size_t new_size, std::size_t min_size, const std::integral_constant<int, checked>&)
{
- 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."));
+ if (new_size < min_size)
+ BOOST_MP_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_<unchecked>&){}
+inline BOOST_MP_CXX14_CONSTEXPR void verify_new_size(std::size_t /*new_size*/, std::size_t /*min_size*/, const std::integral_constant<int, unchecked>&) {}
template <class U>
-inline void verify_limb_mask(bool b, U limb, U mask, const mpl::int_<checked>&)
+inline BOOST_MP_CXX14_CONSTEXPR void verify_limb_mask(bool b, U limb, U mask, const std::integral_constant<int, checked>&)
{
// 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."));
+ if (b && (limb & ~mask))
+ BOOST_MP_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 <class U>
-inline void verify_limb_mask(bool /*b*/, U /*limb*/, U /*mask*/, const mpl::int_<unchecked>&){}
+inline BOOST_MP_CXX14_CONSTEXPR void verify_limb_mask(bool /*b*/, U /*limb*/, U /*mask*/, const std::integral_constant<int, unchecked>&) {}
-}
+} // namespace detail
//
// 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 <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-struct cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false> : private Allocator::template rebind<limb_type>::other
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+struct cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>
+ : private boost::multiprecision::detail::empty_value<typename detail::rebind<limb_type, Allocator>::type>
{
- typedef typename Allocator::template rebind<limb_type>::other allocator_type;
-#ifdef BOOST_NO_CXX11_ALLOCATOR
- typedef typename allocator_type::pointer limb_pointer;
- typedef typename allocator_type::const_pointer const_limb_pointer;
-#else
- typedef typename std::allocator_traits<allocator_type>::pointer limb_pointer;
- typedef typename std::allocator_traits<allocator_type>::const_pointer const_limb_pointer;
-#endif
- typedef mpl::int_<Checked> checked_type;
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, bool trivial2>
+ friend struct cpp_int_base;
+
+ using allocator_type = typename detail::rebind<limb_type, Allocator>::type;
+ using limb_pointer = typename std::allocator_traits<allocator_type>::pointer ;
+ using const_limb_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
+ using checked_type = std::integral_constant<int, Checked>;
//
// Interface invariants:
//
- BOOST_STATIC_ASSERT(!is_void<Allocator>::value);
+ static_assert(!std::is_void<Allocator>::value, "Allocator must not be void here");
+
+ using base_type = boost::multiprecision::detail::empty_value<allocator_type>;
private:
struct limb_data
{
- unsigned capacity;
- limb_pointer data;
+ std::size_t 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<limb_type>(0u));
- BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast<limb_type>(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:
+ public:
+ static constexpr std::size_t limb_bits = sizeof(limb_type) * CHAR_BIT;
+ static constexpr limb_type max_limb_value = ~static_cast<limb_type>(0u);
+ static constexpr limb_type sign_bit_mask = static_cast<limb_type>(1u) << (limb_bits - 1);
+ static constexpr std::size_t internal_limb_count =
+ MinBits
+ ? (MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0))
+ : (sizeof(limb_data) / sizeof(limb_type)) > 1 ? (sizeof(limb_data) / sizeof(limb_type)) : 2;
+ private:
union data_type
{
- limb_data ld;
- limb_type la[internal_limb_count];
- limb_type first;
+ 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<limb_type>(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<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i) {}
+ constexpr data_type() noexcept : first(0) {}
+ constexpr data_type(limb_type i) noexcept : first(i) {}
+ constexpr data_type(signed_limb_type i) noexcept : first(static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(i))) {}
+#if BOOST_MP_ENDIAN_LITTLE_BYTE
+ constexpr data_type(double_limb_type i) noexcept : double_first(i)
+ {}
+ constexpr data_type(signed_double_limb_type i) noexcept : double_first(static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i))) {}
+#endif
+#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !(defined(BOOST_MSVC) && (BOOST_MSVC < 1900))
+ constexpr data_type(limb_type* limbs, std::size_t len) noexcept : ld{ len, limbs }
+ {}
+#else
+ constexpr data_type(limb_type* limbs, std::size_t len) noexcept
+ {
+ ld.capacity = len;
+ ld.data = limbs;
+ }
#endif
};
- data_type m_data;
- unsigned m_limbs;
- bool m_sign, m_internal;
+ data_type m_data;
+ std::size_t m_limbs;
+ bool m_sign, m_internal, m_alias;
-public:
+ public:
//
// Direct construction:
//
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT
- : m_data(i), m_limbs(1), m_sign(false), m_internal(true) { }
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_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 cpp_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 cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT
- : m_data(i), m_limbs(i < 0 ? (static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) > static_cast<double_limb_type>(max_limb_value) ? 2 : 1) : (i > max_limb_value ? 2 : 1)),
- m_sign(i < 0), m_internal(true) { }
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(limb_type i) noexcept
+ : m_data(i),
+ m_limbs(1),
+ m_sign(false),
+ m_internal(true),
+ m_alias(false) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(signed_limb_type i) noexcept
+ : m_data(i),
+ m_limbs(1),
+ m_sign(i < 0),
+ m_internal(true),
+ m_alias(false) {}
+#if BOOST_MP_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(double_limb_type i) noexcept
+ : m_data(i),
+ m_limbs(i > max_limb_value ? 2 : 1),
+ m_sign(false),
+ m_internal(true),
+ m_alias(false)
+ {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(signed_double_limb_type i) noexcept
+ : m_data(i),
+ m_limbs(i < 0 ? (static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) > static_cast<double_limb_type>(max_limb_value) ? 2 : 1) : (i > max_limb_value ? 2 : 1)),
+ m_sign(i < 0),
+ m_internal(true),
+ m_alias(false) {}
#endif
//
+ // Aliasing constructor aliases data:
+ //
+ struct scoped_shared_storage : private boost::multiprecision::detail::empty_value<allocator_type>
+ {
+ private:
+ limb_type* data;
+ std::size_t capacity;
+ std::size_t allocated;
+ bool is_alias;
+ allocator_type& allocator() noexcept { return boost::multiprecision::detail::empty_value<allocator_type>::get(); }
+
+ public:
+ scoped_shared_storage(const allocator_type& a, std::size_t len)
+ : boost::multiprecision::detail::empty_value<allocator_type>(boost::multiprecision::detail::empty_init_t(), a), capacity(len), allocated(0), is_alias(false)
+ {
+ data = allocator().allocate(len);
+ }
+ scoped_shared_storage(const cpp_int_base& i, std::size_t len)
+ : boost::multiprecision::detail::empty_value<allocator_type>(boost::multiprecision::detail::empty_init_t(), i.allocator()), capacity(len), allocated(0), is_alias(false)
+ {
+ data = allocator().allocate(len);
+ }
+ scoped_shared_storage(limb_type* limbs, std::size_t n) : data(limbs), capacity(n), allocated(0), is_alias(true) {}
+ ~scoped_shared_storage()
+ {
+ if(!is_alias)
+ allocator().deallocate(data, capacity);
+ }
+ limb_type* allocate(std::size_t n) noexcept
+ {
+ limb_type* result = data + allocated;
+ allocated += n;
+ BOOST_MP_ASSERT(allocated <= capacity);
+ return result;
+ }
+ void deallocate(std::size_t n)
+ {
+ BOOST_MP_ASSERT(n <= allocated);
+ allocated -= n;
+ }
+ };
+ explicit constexpr cpp_int_base(limb_type* data, std::size_t offset, std::size_t len) noexcept
+ : m_data(data + offset, len),
+ m_limbs(len),
+ m_sign(false),
+ m_internal(false),
+ m_alias(true) {}
+ // This next constructor is for constructing const objects from const limb_type*'s only.
+ // Unfortunately we appear to have no way to assert that within the language, and the const_cast
+ // is a side effect of that :(
+ explicit constexpr cpp_int_base(const limb_type* data, std::size_t offset, std::size_t len) noexcept
+ : m_data(const_cast<limb_type*>(data) + offset, len),
+ m_limbs(len),
+ m_sign(false),
+ m_internal(false),
+ m_alias(true) {}
+ explicit cpp_int_base(scoped_shared_storage& data, std::size_t len) noexcept
+ : m_data(data.allocate(len), len),
+ m_limbs(len),
+ m_sign(false),
+ m_internal(false),
+ m_alias(true) {}
+ //
// 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
+ BOOST_MP_FORCEINLINE allocator_type& allocator() noexcept { return base_type::get(); }
+ BOOST_MP_FORCEINLINE const allocator_type& allocator() const noexcept { return base_type::get(); }
+ BOOST_MP_FORCEINLINE std::size_t size() const noexcept { return m_limbs; }
+ BOOST_MP_FORCEINLINE limb_pointer limbs() noexcept { return m_internal ? m_data.la : m_data.ld.data; }
+ BOOST_MP_FORCEINLINE const_limb_pointer limbs() const noexcept { return m_internal ? m_data.la : m_data.ld.data; }
+ BOOST_MP_FORCEINLINE std::size_t capacity() const noexcept { return m_internal ? internal_limb_count : m_data.ld.capacity; }
+ BOOST_MP_FORCEINLINE bool sign() const noexcept { return m_sign; }
+ void sign(bool b) noexcept
{
m_sign = b;
// Check for zero value:
- if(m_sign && (m_limbs == 1))
+ if (m_sign && (m_limbs == 1))
{
- if(limbs()[0] == 0)
+ if (limbs()[0] == 0)
m_sign = false;
}
}
- void resize(unsigned new_size, unsigned min_size)
+ void resize(std::size_t new_size, std::size_t min_size)
{
- static const unsigned max_limbs = MaxBits / (CHAR_BIT * sizeof(limb_type)) + ((MaxBits % (CHAR_BIT * sizeof(limb_type))) ? 1 : 0);
+ constexpr std::size_t 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)
+ 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)
+ std::size_t cap = capacity();
+ if (new_size > cap)
{
+ // We must not be an alias, memory allocation here defeats the whole point of aliasing:
+ BOOST_MP_ASSERT(!m_alias);
// Allocate a new buffer and copy everything over:
- cap = (std::min)((std::max)(cap * 4, new_size), max_limbs);
+ 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)
+ if (!m_internal && !m_alias)
allocator().deallocate(limbs(), capacity());
else
m_internal = false;
- m_limbs = new_size;
+ m_limbs = new_size;
m_data.ld.capacity = cap;
- m_data.ld.data = pl;
+ m_data.ld.data = pl;
}
else
{
m_limbs = new_size;
}
}
- BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE void normalize() noexcept
{
limb_pointer p = limbs();
- while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
+ while ((m_limbs - 1) && !p[m_limbs - 1])
+ --m_limbs;
}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(), m_limbs(1), m_sign(false), m_internal(true) {}
- BOOST_MP_FORCEINLINE cpp_int_base(const cpp_int_base& o) : allocator_type(o), m_limbs(0), m_internal(true)
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base() noexcept : m_data(), m_limbs(1), m_sign(false), m_internal(true), m_alias(false){}
+ BOOST_MP_FORCEINLINE cpp_int_base(const cpp_int_base& o) : base_type(o), m_limbs(o.m_alias ? o.m_limbs : 0), m_sign(o.m_sign), m_internal(o.m_alias ? false : true), m_alias(o.m_alias)
{
- resize(o.size(), o.size());
- std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
- m_sign = o.m_sign;
+ if (m_alias)
+ {
+ m_data.ld = o.m_data.ld;
+ }
+ else
+ {
+ resize(o.size(), o.size());
+ std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
+ }
}
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // rvalue copy:
cpp_int_base(cpp_int_base&& o)
- : allocator_type(static_cast<allocator_type&&>(o)), m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal)
+ : base_type(static_cast<base_type&&>(o)), m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal), m_alias(o.m_alias)
{
- if(m_internal)
+ if (m_internal)
{
std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
}
@@ -314,15 +433,16 @@ public:
o.m_internal = true;
}
}
- cpp_int_base& operator = (cpp_int_base&& o) BOOST_NOEXCEPT
+ cpp_int_base& operator=(cpp_int_base&& o) noexcept
{
- if(!m_internal)
+ if (!m_internal && !m_alias)
allocator().deallocate(m_data.ld.data, m_data.ld.capacity);
- *static_cast<allocator_type*>(this) = static_cast<allocator_type&&>(o);
+ *static_cast<base_type*>(this) = static_cast<base_type&&>(o);
m_limbs = o.m_limbs;
m_sign = o.m_sign;
m_internal = o.m_internal;
- if(m_internal)
+ m_alias = o.m_alias;
+ if (m_internal)
{
std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
}
@@ -334,707 +454,853 @@ public:
}
return *this;
}
-#endif
- BOOST_MP_FORCEINLINE ~cpp_int_base() BOOST_NOEXCEPT
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_int_check_type Checked2>
+ cpp_int_base& operator=(cpp_int_base<MinBits2, MaxBits2, signed_magnitude, Checked2, Allocator>&& o) noexcept
+ {
+ if(o.m_internal)
+ {
+ m_sign = o.m_sign;
+ this->resize(o.size(), o.size());
+ std::memcpy(this->limbs(), o.limbs(), o.size() * sizeof(*(o.limbs())));
+ return *this;
+ }
+ if (!m_internal && !m_alias)
+ allocator().deallocate(m_data.ld.data, m_data.ld.capacity);
+ *static_cast<base_type*>(this) = static_cast<typename cpp_int_base<MinBits2, MaxBits2, signed_magnitude, Checked2, Allocator>::base_type&&>(o);
+ m_limbs = o.m_limbs;
+ m_sign = o.m_sign;
+ m_internal = o.m_internal;
+ m_alias = o.m_alias;
+ m_data.ld.capacity = o.m_data.ld.capacity;
+ m_data.ld.data = o.limbs();
+ o.m_limbs = 0;
+ o.m_internal = true;
+ return *this;
+ }
+ BOOST_MP_FORCEINLINE ~cpp_int_base() noexcept
{
- if(!m_internal)
+ if (!m_internal && !m_alias)
allocator().deallocate(limbs(), capacity());
}
void assign(const cpp_int_base& o)
{
- if(this != &o)
+ if (this != &o)
{
- static_cast<allocator_type&>(*this) = static_cast<const allocator_type&>(o);
- m_limbs = 0;
+ static_cast<base_type&>(*this) = static_cast<const base_type&>(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
+ BOOST_MP_FORCEINLINE void negate() noexcept
{
m_sign = !m_sign;
// Check for zero value:
- if(m_sign && (m_limbs == 1))
+ if (m_sign && (m_limbs == 1))
{
- if(limbs()[0] == 0)
+ if (limbs()[0] == 0)
m_sign = false;
}
}
- BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE bool isneg() const noexcept
{
return m_sign;
}
- BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) 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);
+ std::swap(m_alias, o.m_alias);
}
-protected:
+
+ protected:
template <class A>
- void check_in_range(const A&) BOOST_NOEXCEPT {}
+ void check_in_range(const A&) noexcept {}
};
-#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
-
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::limb_bits;
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::max_limb_value;
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::sign_bit_mask;
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::internal_limb_count;
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-const bool cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::variable;
-
-#endif
-
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-struct cpp_int_base<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator, false> : private Allocator::template rebind<limb_type>::other
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+constexpr std::size_t cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::limb_bits;
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+constexpr limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::max_limb_value;
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+constexpr limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::sign_bit_mask;
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+constexpr std::size_t cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::internal_limb_count;
+
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+struct cpp_int_base<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator, false>
+ : private boost::multiprecision::detail::empty_value<typename detail::rebind<limb_type, Allocator>::type>
{
//
// 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<Allocator>::value), "There is curently no support for unsigned arbitrary precision integers.");
+ static_assert(((sizeof(Allocator) == 0) && !std::is_void<Allocator>::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 <unsigned MinBits, cpp_int_check_type Checked>
+template <std::size_t MinBits, cpp_int_check_type Checked>
struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>
{
- typedef limb_type* limb_pointer;
- typedef const limb_type* const_limb_pointer;
- typedef mpl::int_<Checked> checked_type;
+ using limb_pointer = limb_type* ;
+ using const_limb_pointer = const limb_type* ;
+ using checked_type = std::integral_constant<int, Checked>;
+
+ struct scoped_shared_storage
+ {
+ BOOST_MP_CXX14_CONSTEXPR scoped_shared_storage(const cpp_int_base&, std::size_t) {}
+ BOOST_MP_CXX14_CONSTEXPR void deallocate(std::size_t) {}
+ };
//
// 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?");
+ static_assert(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<limb_type>(0u));
- BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast<limb_type>(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");
+ public:
+ static constexpr std::size_t limb_bits = sizeof(limb_type) * CHAR_BIT;
+ static constexpr limb_type max_limb_value = ~static_cast<limb_type>(0u);
+ static constexpr limb_type sign_bit_mask = static_cast<limb_type>(1u) << (limb_bits - 1);
+ static constexpr std::size_t internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0);
+ static constexpr limb_type upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) - 1 : (~limb_type(0));
+ static_assert(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 <limb_type...VALUES>
- BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{ VALUES... } {}
+ private:
+ union data_type
+ {
+ limb_type m_data[internal_limb_count];
+ limb_type m_first_limb;
+ double_limb_type m_double_first_limb;
+
+ constexpr data_type()
+ : m_data{0}
+ {}
+ constexpr data_type(limb_type i)
+ : m_data{i}
+ {}
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ constexpr data_type(limb_type i, limb_type j) : m_data{i, j}
+ {}
+#endif
+ constexpr data_type(double_limb_type i) : m_double_first_limb(i)
+ {
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(m_double_first_limb))
+ {
+ data_type t(static_cast<limb_type>(i & max_limb_value), static_cast<limb_type>(i >> limb_bits));
+ *this = t;
+ }
#endif
+ }
+ template <limb_type... VALUES>
+ constexpr data_type(literals::detail::value_pack<VALUES...>) : m_data{VALUES...}
+ {}
} m_wrapper;
- boost::uint16_t m_limbs;
- bool m_sign;
+ std::uint16_t m_limbs;
+ bool m_sign;
-public:
+ public:
//
// Direct construction:
//
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT
- : m_wrapper(i), m_limbs(1), m_sign(false) {}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT
- : m_wrapper(limb_type(i < 0 ? static_cast<limb_type>(-static_cast<signed_double_limb_type>(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 cpp_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 cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT
- : m_wrapper(double_limb_type(i < 0 ? static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i)),
- m_limbs(i < 0 ? (static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)),
- m_sign(i < 0) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(limb_type i) noexcept
+ : m_wrapper(i),
+ m_limbs(1),
+ m_sign(false) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(signed_limb_type i) noexcept
+ : m_wrapper(limb_type(i < 0 ? static_cast<limb_type>(-static_cast<signed_double_limb_type>(i)) : i)),
+ m_limbs(1),
+ m_sign(i < 0) {}
+#if BOOST_MP_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(double_limb_type i) noexcept
+ : m_wrapper(i),
+ m_limbs(i > max_limb_value ? 2 : 1),
+ m_sign(false)
+ {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(signed_double_limb_type i) noexcept
+ : m_wrapper(double_limb_type(i < 0 ? static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i)),
+ m_limbs(i < 0 ? (static_cast<double_limb_type>(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 <limb_type...VALUES>
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i)
- : m_wrapper(i), m_limbs(sizeof...(VALUES)), m_sign(false) {}
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<> i)
- : m_wrapper(i), m_limbs(1), m_sign(false) {}
- BOOST_CONSTEXPR cpp_int_base(const cpp_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
-#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ template <limb_type... VALUES>
+ constexpr cpp_int_base(literals::detail::value_pack<VALUES...> i)
+ : m_wrapper(i), m_limbs(sizeof...(VALUES)), m_sign(false)
+ {}
+ constexpr cpp_int_base(literals::detail::value_pack<> i)
+ : m_wrapper(i), m_limbs(1), m_sign(false) {}
+ constexpr cpp_int_base(const cpp_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) {}
+ explicit constexpr cpp_int_base(scoped_shared_storage&, std::size_t) noexcept : m_wrapper(), m_limbs(0), m_sign(false)
+ {}
//
// These are deprecated in C++20 unless we make them explicit:
//
- constexpr cpp_int_base& operator=(const cpp_int_base&) = default;
-#endif
+ BOOST_MP_CXX14_CONSTEXPR cpp_int_base& operator=(const cpp_int_base&) = default;
//
// 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
+ BOOST_MP_FORCEINLINE constexpr std::size_t size() const noexcept { return m_limbs; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_pointer limbs() noexcept { return m_wrapper.m_data; }
+ BOOST_MP_FORCEINLINE constexpr const_limb_pointer limbs() const noexcept { return m_wrapper.m_data; }
+ BOOST_MP_FORCEINLINE constexpr bool sign() const noexcept { return m_sign; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void sign(bool b) noexcept
{
m_sign = b;
// Check for zero value:
- if(m_sign && (m_limbs == 1))
+ if (m_sign && (m_limbs == 1))
{
- if(limbs()[0] == 0)
+ if (limbs()[0] == 0)
m_sign = false;
}
}
- BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void resize(std::size_t new_size, std::size_t min_size) noexcept((Checked == unchecked))
{
- m_limbs = static_cast<boost::uint16_t>((std::min)(new_size, internal_limb_count));
+ m_limbs = static_cast<std::uint16_t>((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))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void normalize() noexcept((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
+ detail::verify_limb_mask(m_limbs == internal_limb_count, p[m_limbs - 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 cpp_int_base()BOOST_NOEXCEPT : m_wrapper(limb_type(0u)), m_limbs(1), m_sign(false) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base() 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 cpp_int_base(const cpp_int_base& o)BOOST_NOEXCEPT
- : m_wrapper(o.m_wrapper), m_limbs(o.m_limbs), m_sign(o.m_sign) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(const cpp_int_base& o) noexcept
+ : m_wrapper(o.m_wrapper),
+ m_limbs(o.m_limbs),
+ m_sign(o.m_sign) {}
// Defaulted functions:
- //~cpp_int_base() BOOST_NOEXCEPT {}
+ //~cpp_int_base() noexcept {}
- void assign(const cpp_int_base& o) BOOST_NOEXCEPT
+ void BOOST_MP_CXX14_CONSTEXPR assign(const cpp_int_base& o) noexcept
{
- if(this != &o)
+ if (this != &o)
{
m_limbs = o.m_limbs;
- std::memcpy(limbs(), o.limbs(), o.size() * sizeof(o.limbs()[0]));
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(m_limbs))
+ {
+ for (std::size_t i = 0; i < m_limbs; ++i)
+ limbs()[i] = o.limbs()[i];
+ }
+ else
+#endif
+ std::memcpy(limbs(), o.limbs(), o.size() * sizeof(o.limbs()[0]));
m_sign = o.m_sign;
}
}
- BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void negate() noexcept
{
m_sign = !m_sign;
// Check for zero value:
- if(m_sign && (m_limbs == 1))
+ if (m_sign && (m_limbs == 1))
{
- if(limbs()[0] == 0)
+ if (limbs()[0] == 0)
m_sign = false;
}
}
- BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool isneg() const noexcept
{
return m_sign;
}
- BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_swap(cpp_int_base& o) 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);
+ for (std::size_t i = 0; i < (std::max)(size(), o.size()); ++i)
+ std_constexpr::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]);
+ std_constexpr::swap(m_sign, o.m_sign);
+ std_constexpr::swap(m_limbs, o.m_limbs);
}
-protected:
+
+ protected:
template <class A>
- void check_in_range(const A&) BOOST_NOEXCEPT {}
+ BOOST_MP_CXX14_CONSTEXPR void check_in_range(const A&) noexcept {}
};
-#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
-
-template <unsigned MinBits, cpp_int_check_type Checked>
-const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::limb_bits;
-template <unsigned MinBits, cpp_int_check_type Checked>
-const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::max_limb_value;
-template <unsigned MinBits, cpp_int_check_type Checked>
-const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::sign_bit_mask;
-template <unsigned MinBits, cpp_int_check_type Checked>
-const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::internal_limb_count;
-template <unsigned MinBits, cpp_int_check_type Checked>
-const bool cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::variable;
-#endif
+template <std::size_t MinBits, cpp_int_check_type Checked>
+constexpr std::size_t cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::limb_bits;
+template <std::size_t MinBits, cpp_int_check_type Checked>
+constexpr limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::max_limb_value;
+template <std::size_t MinBits, cpp_int_check_type Checked>
+constexpr limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::sign_bit_mask;
+template <std::size_t MinBits, cpp_int_check_type Checked>
+constexpr std::size_t cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::internal_limb_count;
//
// Fixed precision (i.e. no allocator), unsigned type with limb-usage count:
//
-template <unsigned MinBits, cpp_int_check_type Checked>
+template <std::size_t MinBits, cpp_int_check_type Checked>
struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>
{
- typedef limb_type* limb_pointer;
- typedef const limb_type* const_limb_pointer;
- typedef mpl::int_<Checked> checked_type;
+ using limb_pointer = limb_type* ;
+ using const_limb_pointer = const limb_type* ;
+ using checked_type = std::integral_constant<int, Checked>;
+ struct scoped_shared_storage
+ {
+ BOOST_MP_CXX14_CONSTEXPR scoped_shared_storage(const cpp_int_base&, std::size_t) {}
+ BOOST_MP_CXX14_CONSTEXPR void deallocate(std::size_t) {}
+ };
//
// 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?");
+ static_assert(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<limb_type>(0u));
- BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast<limb_type>(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");
+ public:
+ static constexpr std::size_t limb_bits = sizeof(limb_type) * CHAR_BIT;
+ static constexpr limb_type max_limb_value = ~static_cast<limb_type>(0u);
+ static constexpr limb_type sign_bit_mask = static_cast<limb_type>(1u) << (limb_bits - 1);
+ static constexpr std::size_t internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0);
+ static constexpr limb_type upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) - 1 : (~limb_type(0));
+ static_assert(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 <limb_type...VALUES>
- BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{ VALUES... } {}
+ private:
+ union data_type
+ {
+ limb_type m_data[internal_limb_count];
+ limb_type m_first_limb;
+ double_limb_type m_double_first_limb;
+
+ constexpr data_type()
+ : m_data{0}
+ {}
+ constexpr data_type(limb_type i)
+ : m_data{i}
+ {}
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ constexpr data_type(limb_type i, limb_type j) : m_data{i, j}
+ {}
+#endif
+ constexpr data_type(double_limb_type i) : m_double_first_limb(i)
+ {
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(m_double_first_limb))
+ {
+ data_type t(static_cast<limb_type>(i & max_limb_value), static_cast<limb_type>(i >> limb_bits));
+ *this = t;
+ }
#endif
+ }
+ template <limb_type... VALUES>
+ constexpr data_type(literals::detail::value_pack<VALUES...>) : m_data{VALUES...}
+ {}
} m_wrapper;
- limb_type m_limbs;
+ std::size_t m_limbs;
-public:
+ public:
//
// Direct construction:
//
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT
- : m_wrapper(i), m_limbs(1) {}
- BOOST_MP_FORCEINLINE cpp_int_base(signed_limb_type i)BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
- : m_wrapper(limb_type(i < 0 ? static_cast<limb_type>(-static_cast<signed_double_limb_type>(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 cpp_int_base(double_limb_type i)BOOST_NOEXCEPT
- : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1) {}
- BOOST_MP_FORCEINLINE cpp_int_base(signed_double_limb_type i)BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
- : m_wrapper(double_limb_type(i < 0 ? static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i)),
- m_limbs(i < 0 ? (static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1))
- {
- if (i < 0) negate();
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(limb_type i) noexcept
+ : m_wrapper(i),
+ m_limbs(1) {}
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(signed_limb_type i) noexcept((Checked == unchecked))
+ : m_wrapper(static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(i))),
+ m_limbs(1)
+ {
+ if (i < 0)
+ negate();
+ }
+#if BOOST_MP_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(double_limb_type i) noexcept
+ : m_wrapper(i),
+ m_limbs(i > max_limb_value ? 2 : 1)
+ {}
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(signed_double_limb_type i) noexcept((Checked == unchecked))
+ : m_wrapper(double_limb_type(i < 0 ? static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i)),
+ m_limbs(i < 0 ? (static_cast<double_limb_type>(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 <limb_type...VALUES>
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i)
- : m_wrapper(i), m_limbs(sizeof...(VALUES)) {}
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>)
- : m_wrapper(static_cast<limb_type>(0u)), m_limbs(1) {}
-#endif
- //
+ template <limb_type... VALUES>
+ constexpr cpp_int_base(literals::detail::value_pack<VALUES...> i)
+ : m_wrapper(i), m_limbs(sizeof...(VALUES))
+ {}
+ constexpr cpp_int_base(literals::detail::value_pack<>)
+ : m_wrapper(static_cast<limb_type>(0u)), m_limbs(1) {}
+ explicit constexpr cpp_int_base(scoped_shared_storage&, std::size_t) noexcept : m_wrapper(), m_limbs(1)
+ {}
+ //
// 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))
+ BOOST_MP_FORCEINLINE constexpr std::size_t size() const noexcept { return m_limbs; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_pointer limbs() noexcept { return m_wrapper.m_data; }
+ BOOST_MP_FORCEINLINE constexpr const_limb_pointer limbs() const noexcept { return m_wrapper.m_data; }
+ BOOST_MP_FORCEINLINE constexpr bool sign() const noexcept { return false; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void sign(bool b) noexcept((Checked == unchecked))
+ {
+ if (b)
+ negate();
+ }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void resize(std::size_t new_size, std::size_t min_size) noexcept((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))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void normalize() noexcept((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 cpp_int_base() BOOST_NOEXCEPT
- : m_wrapper(limb_type(0u)), m_limbs(1) {}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
- : m_wrapper(o.m_wrapper), m_limbs(o.m_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 constexpr cpp_int_base() noexcept
+ : m_wrapper(limb_type(0u)),
+ m_limbs(1) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(const cpp_int_base& o) noexcept
+ : m_wrapper(o.m_wrapper),
+ m_limbs(o.m_limbs) {}
// Defaulted functions:
- //~cpp_int_base() BOOST_NOEXCEPT {}
-#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ //~cpp_int_base() noexcept {}
//
// These are deprecated in C++20 unless we make them explicit:
//
- constexpr cpp_int_base& operator=(const cpp_int_base&) = default;
-#endif
+ BOOST_MP_CXX14_CONSTEXPR cpp_int_base& operator=(const cpp_int_base&) = default;
- BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void assign(const cpp_int_base& o) noexcept
{
- if(this != &o)
+ if (this != &o)
{
m_limbs = o.m_limbs;
- std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(m_limbs))
+ {
+ for (std::size_t i = 0; i < m_limbs; ++i)
+ limbs()[i] = o.limbs()[i];
+ }
+ else
+#endif
+ std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
}
}
-private:
- void check_negate(const mpl::int_<checked>&)
+
+ private:
+ void check_negate(const std::integral_constant<int, checked>&)
{
- BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned number."));
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned number."));
}
- void check_negate(const mpl::int_<unchecked>&){}
-public:
- void negate() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
+ BOOST_MP_CXX14_CONSTEXPR void check_negate(const std::integral_constant<int, unchecked>&) {}
+
+ public:
+ BOOST_MP_CXX14_CONSTEXPR void negate() noexcept((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))
+ 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)
+ std::size_t i = m_limbs;
+ for (; i < internal_limb_count; ++i)
m_wrapper.m_data[i] = 0;
m_limbs = internal_limb_count;
- for(i = 0; i < internal_limb_count; ++i)
+ for (i = 0; i < internal_limb_count; ++i)
m_wrapper.m_data[i] = ~m_wrapper.m_data[i];
normalize();
- eval_increment(static_cast<cpp_int_backend<MinBits, MinBits, unsigned_magnitude, Checked, void>& >(*this));
+ eval_increment(static_cast<cpp_int_backend<MinBits, MinBits, unsigned_magnitude, Checked, void>&>(*this));
}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg()const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE constexpr bool isneg() const noexcept
{
return false;
}
- BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_swap(cpp_int_base& o) 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);
+ for (std::size_t i = 0; i < (std::max)(size(), o.size()); ++i)
+ std_constexpr::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]);
+ std_constexpr::swap(m_limbs, o.m_limbs);
}
-protected:
+
+ protected:
template <class A>
- void check_in_range(const A&) BOOST_NOEXCEPT {}
+ BOOST_MP_CXX14_CONSTEXPR void check_in_range(const A&) noexcept {}
};
-#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
-
-template <unsigned MinBits, cpp_int_check_type Checked>
-const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::limb_bits;
-template <unsigned MinBits, cpp_int_check_type Checked>
-const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::max_limb_value;
-template <unsigned MinBits, cpp_int_check_type Checked>
-const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::sign_bit_mask;
-template <unsigned MinBits, cpp_int_check_type Checked>
-const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::internal_limb_count;
-template <unsigned MinBits, cpp_int_check_type Checked>
-const bool cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::variable;
-#endif
+template <std::size_t MinBits, cpp_int_check_type Checked>
+constexpr std::size_t cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::limb_bits;
+template <std::size_t MinBits, cpp_int_check_type Checked>
+constexpr limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::max_limb_value;
+template <std::size_t MinBits, cpp_int_check_type Checked>
+constexpr limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::sign_bit_mask;
+template <std::size_t MinBits, cpp_int_check_type Checked>
+constexpr std::size_t cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::internal_limb_count;
//
// Traits classes to figure out a native type with N bits, these vary from boost::uint_t<N> only
-// because some platforms have native integer types longer than boost::long_long_type, "really boost::long_long_type" anyone??
+// because some platforms have native integer types longer than long long, "really long long" anyone??
//
template <unsigned N, bool s>
struct trivial_limb_type_imp
{
- typedef double_limb_type type;
+ using type = double_limb_type;
};
template <unsigned N>
struct trivial_limb_type_imp<N, true>
{
- typedef typename boost::uint_t<N>::least type;
+ using type = typename boost::multiprecision::detail::uint_t<N>::least;
};
template <unsigned N>
-struct trivial_limb_type : public trivial_limb_type_imp<N, N <= sizeof(boost::long_long_type) * CHAR_BIT> {};
+struct trivial_limb_type : public trivial_limb_type_imp<N, N <= sizeof(long long) * CHAR_BIT>
+{};
//
// Backend for fixed precision signed-magnitude type which will fit entirely inside a "double_limb_type":
//
-template <unsigned MinBits, cpp_int_check_type Checked>
+template <std::size_t MinBits, cpp_int_check_type Checked>
struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, true>
{
- typedef typename trivial_limb_type<MinBits>::type local_limb_type;
- typedef local_limb_type* limb_pointer;
- typedef const local_limb_type* const_limb_pointer;
- typedef mpl::int_<Checked> 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;
+ using local_limb_type = typename trivial_limb_type<static_cast<unsigned>(MinBits)>::type;
+ using limb_pointer = local_limb_type*;
+ using const_limb_pointer = const local_limb_type*;
+ using checked_type = std::integral_constant<int, Checked>;
+
+ struct scoped_shared_storage
+ {
+ BOOST_MP_CXX14_CONSTEXPR scoped_shared_storage(const cpp_int_base&, std::size_t) {}
+ BOOST_MP_CXX14_CONSTEXPR void deallocate(std::size_t) {}
+ };
+
+ protected:
+ static constexpr std::size_t limb_bits = sizeof(local_limb_type) * CHAR_BIT;
+ static constexpr 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:
+ static_assert(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 <class T>
- typename boost::disable_if_c<!boost::is_integral<T>::value || (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits))>::type
- check_in_range(T val, const mpl::int_<checked>&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!boost::multiprecision::detail::is_integral<T>::value || (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= static_cast<int>(MinBits))))>::type
+ check_in_range(T val, const std::integral_constant<int, checked>&)
{
- typedef typename common_type<typename make_unsigned<T>::type, local_limb_type>::type common_type;
+ using common_type = typename std::common_type<typename boost::multiprecision::detail::make_unsigned<T>::type, local_limb_type>::type;
- if(static_cast<common_type>(boost::multiprecision::detail::unsigned_abs(val)) > static_cast<common_type>(limb_mask))
- BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
+ if (static_cast<common_type>(boost::multiprecision::detail::unsigned_abs(val)) > static_cast<common_type>(limb_mask))
+ BOOST_MP_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
}
template <class T>
- typename boost::disable_if_c<boost::is_integral<T>::value || (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits))>::type
- check_in_range(T val, const mpl::int_<checked>&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::detail::is_integral<T>::value || (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= static_cast<int>(MinBits))))>::type
+ check_in_range(T val, const std::integral_constant<int, checked>&)
{
- using std::abs;
- typedef typename common_type<T, local_limb_type>::type common_type;
+ using std::abs;
+ using common_type = typename std::common_type<T, local_limb_type>::type;
- if (static_cast<common_type>(abs(val)) > static_cast<common_type>(limb_mask))
- BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
+ if (static_cast<common_type>(abs(val)) > static_cast<common_type>(limb_mask))
+ BOOST_MP_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
}
template <class T, int C>
- void check_in_range(T, const mpl::int_<C>&) BOOST_NOEXCEPT {}
+ BOOST_MP_CXX14_CONSTEXPR void check_in_range(T, const std::integral_constant<int, C>&) noexcept {}
template <class T>
- void check_in_range(T val) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<T>(), checked_type())))
+ BOOST_MP_CXX14_CONSTEXPR void check_in_range(T val) noexcept(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<T>(), checked_type())))
{
check_in_range(val, checked_type());
}
-public:
+ public:
//
// Direct construction:
//
template <class SI>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
- : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask) : static_cast<local_limb_type>(i & limb_mask)), m_sign(i < 0) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(SI i, typename std::enable_if<boost::multiprecision::detail::is_signed<SI>::value && boost::multiprecision::detail::is_integral<SI>::value && (Checked == unchecked)>::type const* = nullptr) noexcept(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
+ : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename boost::multiprecision::detail::make_unsigned<SI>::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask) : static_cast<local_limb_type>(i & limb_mask)), m_sign(i < 0) {}
template <class SI>
- BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
- : m_data(i < 0 ? (static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask)) : static_cast<local_limb_type>(i & limb_mask)), m_sign(i < 0)
- { check_in_range(i); }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(SI i, typename std::enable_if<boost::multiprecision::detail::is_signed<SI>::value && boost::multiprecision::detail::is_integral<SI>::value && (Checked == checked)>::type const* = nullptr) noexcept(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
+ : m_data(i < 0 ? (static_cast<local_limb_type>(static_cast<typename boost::multiprecision::detail::make_unsigned<SI>::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask)) : static_cast<local_limb_type>(i & limb_mask)), m_sign(i < 0)
+ {
+ check_in_range(i);
+ }
template <class UI>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(UI i, typename std::enable_if<boost::multiprecision::detail::is_unsigned<UI>::value && (Checked == unchecked)>::type const* = nullptr) noexcept
+ : m_data(static_cast<local_limb_type>(i) & limb_mask),
+ m_sign(false) {}
template <class UI>
- BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == checked)>::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<UI>())))
- : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) { check_in_range(i); }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(UI i, typename std::enable_if<boost::multiprecision::detail::is_unsigned<UI>::value && (Checked == checked)>::type const* = nullptr) noexcept(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<UI>())))
+ : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) { check_in_range(i); }
+#if !(defined(__clang__) && defined(__MINGW32__))
template <class F>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(F i, typename boost::enable_if_c<is_floating_point<F>::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(F i, typename std::enable_if<std::is_floating_point<F>::value && (Checked == unchecked)>::type const* = nullptr) noexcept
+ : m_data(static_cast<local_limb_type>(i < 0 ? -i : i) & limb_mask),
+ m_sign(i < 0) {}
template <class F>
- BOOST_MP_FORCEINLINE cpp_int_base(F i, typename boost::enable_if_c<is_floating_point<F>::value && (Checked == checked)>::type const* = 0)
- : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) { check_in_range(i); }
-#if defined(BOOST_MP_USER_DEFINED_LITERALS)
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(0u)), m_sign(false) {}
- template <limb_type a>
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>)BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(a)), m_sign(false) {}
- template <limb_type a, limb_type b>
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>)BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)), m_sign(false) {}
- BOOST_CONSTEXPR cpp_int_base(const cpp_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
-#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(F i, typename std::enable_if<std::is_floating_point<F>::value && (Checked == checked)>::type const* = nullptr)
+ : m_data(static_cast<local_limb_type>(i < 0 ? -i : i) & limb_mask), m_sign(i < 0) { check_in_range(i); }
+#else
//
- // These are deprecated in C++20 unless we make them explicit:
+ // conversion from float to __int128 is broken on clang/mingw,
+ // see: https://bugs.llvm.org/show_bug.cgi?id=48940
+ // Since no floating point type has more than 64 bits of
+ // precision, we can simply cast to an intermediate type to
+ // solve the issue:
//
- constexpr cpp_int_base& operator=(const cpp_int_base&) = default;
+ template <class F>
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(F i, typename std::enable_if<std::is_floating_point<F>::value && (Checked == unchecked)>::type const* = nullptr) noexcept
+ : m_data(static_cast<local_limb_type>(static_cast<std::uint64_t>(i < 0 ? -i : i)) & limb_mask),
+ m_sign(i < 0) {}
+ template <class F>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(F i, typename std::enable_if<std::is_floating_point<F>::value && (Checked == checked)>::type const* = nullptr)
+ : m_data(static_cast<local_limb_type>(static_cast<std::uint64_t>(i < 0 ? -i : i)) & limb_mask), m_sign(i < 0) { check_in_range(i); }
#endif
+
+ constexpr cpp_int_base(literals::detail::value_pack<>) noexcept
+ : m_data(static_cast<local_limb_type>(0u)),
+ m_sign(false)
+ {}
+ template <limb_type a>
+ constexpr cpp_int_base(literals::detail::value_pack<a>) noexcept
+ : m_data(static_cast<local_limb_type>(a)),
+ m_sign(false) {}
+ template <limb_type a, limb_type b>
+ constexpr cpp_int_base(literals::detail::value_pack<a, b>) noexcept
+ : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)),
+ m_sign(false) {}
+ constexpr cpp_int_base(const cpp_int_base& a, const literals::detail::negate_tag&) noexcept
+ : m_data(a.m_data),
+ m_sign(a.m_data ? !a.m_sign : false) {}
//
+ // These are deprecated in C++20 unless we make them explicit:
+ //
+ BOOST_MP_CXX14_CONSTEXPR cpp_int_base& operator=(const cpp_int_base&) = default;
+
+ explicit constexpr cpp_int_base(scoped_shared_storage&, std::size_t) noexcept : m_data(0), m_sign(false)
+ {}
+ //
// 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
+ BOOST_MP_FORCEINLINE constexpr std::size_t size() const noexcept { return 1; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_pointer limbs() noexcept { return &m_data; }
+ BOOST_MP_FORCEINLINE constexpr const_limb_pointer limbs() const noexcept { return &m_data; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool sign() const noexcept { return m_sign; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void sign(bool b) noexcept
{
m_sign = b;
// Check for zero value:
- if(m_sign && !m_data)
+ if (m_sign && !m_data)
{
m_sign = false;
}
}
- BOOST_MP_FORCEINLINE void resize(unsigned /* new_size */, unsigned min_size)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void resize(std::size_t /* new_size */, std::size_t min_size)
{
detail::verify_new_size(2, min_size, checked_type());
}
- BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void normalize() noexcept((Checked == unchecked))
{
- if(!m_data)
+ 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 cpp_int_base() BOOST_NOEXCEPT : m_data(0), m_sign(false) {}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
- : m_data(o.m_data), m_sign(o.m_sign) {}
- //~cpp_int_base() BOOST_NOEXCEPT {}
- BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base() noexcept : m_data(0), m_sign(false) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(const cpp_int_base& o) noexcept
+ : m_data(o.m_data),
+ m_sign(o.m_sign) {}
+ //~cpp_int_base() noexcept {}
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void assign(const cpp_int_base& o) noexcept
{
m_data = o.m_data;
m_sign = o.m_sign;
}
- BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void negate() noexcept
{
m_sign = !m_sign;
// Check for zero value:
- if(m_data == 0)
+ if (m_data == 0)
{
m_sign = false;
}
}
- BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool isneg() const noexcept
{
return m_sign;
}
- BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_swap(cpp_int_base& o) noexcept
{
- std::swap(m_sign, o.m_sign);
- std::swap(m_data, o.m_data);
+ std_constexpr::swap(m_sign, o.m_sign);
+ std_constexpr::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 <unsigned MinBits, cpp_int_check_type Checked>
+template <std::size_t MinBits, cpp_int_check_type Checked>
struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, true>
{
- typedef typename trivial_limb_type<MinBits>::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<local_limb_type>(static_cast<local_limb_type>(~local_limb_type(0)) >> (limb_bits - MinBits))
- : static_cast<local_limb_type>(~local_limb_type(0)));
+ using local_limb_type = typename trivial_limb_type<static_cast<unsigned>(MinBits)>::type;
+ using limb_pointer = local_limb_type* ;
+ using const_limb_pointer = const local_limb_type* ;
+
+ struct scoped_shared_storage
+ {
+ BOOST_MP_CXX14_CONSTEXPR scoped_shared_storage(const cpp_int_base&, std::size_t) {}
+ BOOST_MP_CXX14_CONSTEXPR void deallocate(std::size_t) {}
+ };
+
+ private:
+ static constexpr std::size_t limb_bits = sizeof(local_limb_type) * CHAR_BIT;
+ static constexpr local_limb_type limb_mask = limb_bits != MinBits ? static_cast<local_limb_type>(static_cast<local_limb_type>(~local_limb_type(0)) >> (limb_bits - MinBits))
+ : static_cast<local_limb_type>(~local_limb_type(0));
- local_limb_type m_data;
+ local_limb_type m_data;
- typedef mpl::int_<Checked> checked_type;
+ using checked_type = std::integral_constant<int, Checked>;
//
// 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:
+ static_assert(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 <class T>
- typename boost::disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits)>::type
- check_in_range(T val, const mpl::int_<checked>&, const boost::false_type&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !(std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= static_cast<int>(MinBits)))>::type
+ check_in_range(T val, const std::integral_constant<int, checked>&, const std::integral_constant<bool, false>&)
{
- typedef typename common_type<T, local_limb_type>::type common_type;
+ using common_type = typename std::common_type<T, local_limb_type>::type;
- if(static_cast<common_type>(val) > limb_mask)
- BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
+ if (static_cast<common_type>(val) > limb_mask)
+ BOOST_MP_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
}
template <class T>
- void check_in_range(T val, const mpl::int_<checked>&, const boost::true_type&)
+ BOOST_MP_CXX14_CONSTEXPR void check_in_range(T val, const std::integral_constant<int, checked>&, const std::integral_constant<bool, true>&)
{
- typedef typename common_type<T, local_limb_type>::type common_type;
+ using common_type = typename std::common_type<T, local_limb_type>::type;
- if(static_cast<common_type>(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."));
+ if (static_cast<common_type>(val) > static_cast<common_type>(limb_mask))
+ BOOST_MP_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
+ if (val < 0)
+ BOOST_MP_THROW_EXCEPTION(std::range_error("The argument to an unsigned cpp_int constructor was negative."));
}
template <class T, int C, bool B>
- BOOST_MP_FORCEINLINE void check_in_range(T, const mpl::int_<C>&, const boost::integral_constant<bool, B>&) BOOST_NOEXCEPT {}
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void check_in_range(T, const std::integral_constant<int, C>&, const std::integral_constant<bool, B>&) noexcept {}
template <class T>
- BOOST_MP_FORCEINLINE void check_in_range(T val) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<T>(), checked_type(), is_signed<T>())))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void check_in_range(T val) noexcept(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<T>(), checked_type(), boost::multiprecision::detail::is_signed<T>())))
{
- check_in_range(val, checked_type(), is_signed<T>());
+ check_in_range(val, checked_type(), boost::multiprecision::detail::is_signed<T>());
}
-public:
+ public:
//
// Direct construction:
//
#ifdef __MSVC_RUNTIME_CHECKS
template <class SI>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT
- : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i & limb_mask)) & limb_mask : static_cast<local_limb_type>(i & limb_mask)) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(SI i, typename std::enable_if<boost::multiprecision::detail::is_signed<SI>::value && boost::multiprecision::detail::is_integral<SI>::value && (Checked == unchecked)>::type const* = nullptr) noexcept
+ : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i & limb_mask)) & limb_mask : static_cast<local_limb_type>(i & limb_mask))
+ {}
template <class SI>
- BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
- : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i & limb_mask) : static_cast<local_limb_type>(i & limb_mask)) { check_in_range(i); }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(SI i, typename std::enable_if<boost::multiprecision::detail::is_signed<SI>::value && boost::multiprecision::detail::is_integral<SI>::value && (Checked == checked)>::type const* = nullptr) noexcept(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
+ : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i & limb_mask) : static_cast<local_limb_type>(i & limb_mask)) { check_in_range(i); }
template <class UI>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(i & limb_mask)) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(UI i, typename std::enable_if<boost::multiprecision::detail::is_unsigned<UI>::value && (Checked == unchecked)>::type const* = nullptr) noexcept
+ : m_data(static_cast<local_limb_type>(i& limb_mask)) {}
template <class UI>
- BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<UI>())))
- : m_data(static_cast<local_limb_type>(i & limb_mask)) { check_in_range(i); }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(UI i, typename std::enable_if<boost::multiprecision::detail::is_unsigned<UI>::value && (Checked == checked)>::type const* = nullptr) noexcept(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<UI>())))
+ : m_data(static_cast<local_limb_type>(i & limb_mask)) { check_in_range(i); }
#else
template <class SI>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT
- : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(SI i, typename std::enable_if<boost::multiprecision::detail::is_signed<SI>::value && boost::multiprecision::detail::is_integral<SI>::value && (Checked == unchecked)>::type const* = nullptr) noexcept
+ : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask)
+ {}
template <class SI>
- BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
- : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)) { check_in_range(i); }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(SI i, typename std::enable_if<boost::multiprecision::detail::is_signed<SI>::value && boost::multiprecision::detail::is_integral<SI>::value && (Checked == checked)>::type const* = nullptr) noexcept(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
+ : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)) { check_in_range(i); }
template <class UI>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(i) & limb_mask) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(UI i, typename std::enable_if<boost::multiprecision::detail::is_unsigned<UI>::value && (Checked == unchecked)>::type const* = nullptr) noexcept
+ : m_data(static_cast<local_limb_type>(i) & limb_mask) {}
template <class UI>
- BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<UI>())))
- : m_data(static_cast<local_limb_type>(i)) { check_in_range(i); }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(UI i, typename std::enable_if<boost::multiprecision::detail::is_unsigned<UI>::value && (Checked == checked)>::type const* = nullptr) noexcept(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<UI>())))
+ : m_data(static_cast<local_limb_type>(i)) { check_in_range(i); }
#endif
template <class F>
- BOOST_MP_FORCEINLINE cpp_int_base(F i, typename boost::enable_if<is_floating_point<F> >::type const* = 0) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
- : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(F i, typename std::enable_if<std::is_floating_point<F>::value >::type const* = nullptr) noexcept((Checked == unchecked))
+ : m_data(static_cast<local_limb_type>(i < 0 ? -i : i) & limb_mask)
{
check_in_range(i);
- if(i < 0)
+ if (i < 0)
negate();
}
-#if defined(BOOST_MP_USER_DEFINED_LITERALS)
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(0u)) {}
- template <limb_type a>
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>) BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(a)) {}
- template <limb_type a, limb_type b>
- BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>) BOOST_NOEXCEPT
- : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)) {}
-#endif
-#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ constexpr cpp_int_base(literals::detail::value_pack<>) noexcept
+ : m_data(static_cast<local_limb_type>(0u))
+ {}
+ template <limb_type a>
+ constexpr cpp_int_base(literals::detail::value_pack<a>) noexcept
+ : m_data(static_cast<local_limb_type>(a)) {}
+ template <limb_type a, limb_type b>
+ constexpr cpp_int_base(literals::detail::value_pack<a, b>) noexcept
+ : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)) {}
//
// These are deprecated in C++20 unless we make them explicit:
//
- constexpr cpp_int_base& operator=(const cpp_int_base&) = default;
-#endif
- //
+ BOOST_MP_CXX14_CONSTEXPR cpp_int_base& operator=(const cpp_int_base&) = default;
+
+ explicit constexpr cpp_int_base(scoped_shared_storage&, std::size_t) noexcept : m_data(0)
+ {}
+ //
// 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))
+ BOOST_MP_FORCEINLINE constexpr std::size_t size() const noexcept { return 1; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_pointer limbs() noexcept { return &m_data; }
+ BOOST_MP_FORCEINLINE constexpr const_limb_pointer limbs() const noexcept { return &m_data; }
+ BOOST_MP_FORCEINLINE constexpr bool sign() const noexcept { return false; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void sign(bool b) noexcept((Checked == unchecked))
{
- if(b)
+ if (b)
negate();
}
- BOOST_MP_FORCEINLINE void resize(unsigned, unsigned min_size)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void resize(unsigned, std::size_t min_size)
{
detail::verify_new_size(2, min_size, checked_type());
}
- BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void normalize() noexcept((Checked == unchecked))
{
detail::verify_limb_mask(true, m_data, limb_mask, checked_type());
m_data &= limb_mask;
}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(0) {}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
- : m_data(o.m_data) {}
- //~cpp_int_base() BOOST_NOEXCEPT {}
- BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base() noexcept : m_data(0) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_base(const cpp_int_base& o) noexcept
+ : m_data(o.m_data) {}
+ //~cpp_int_base() noexcept {}
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void assign(const cpp_int_base& o) noexcept
{
m_data = o.m_data;
}
- BOOST_MP_FORCEINLINE void negate() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void negate()
+ #if !defined(BOOST_NO_CXX17_IF_CONSTEXPR)
+ noexcept((Checked == unchecked))
+ #endif
{
- if(Checked == checked)
+ BOOST_IF_CONSTEXPR(Checked == checked)
{
- BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned type."));
+ BOOST_MP_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
+ BOOST_MP_FORCEINLINE constexpr bool isneg() const noexcept
{
return false;
}
- BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_swap(cpp_int_base& o) noexcept
{
- std::swap(m_data, o.m_data);
+ std_constexpr::swap(m_data, o.m_data);
}
};
//
@@ -1042,78 +1308,87 @@ public:
// used to enable/disable constructors etc:
//
template <class Arg, class Base>
-struct is_allowed_cpp_int_base_conversion : public mpl::if_c<
- is_same<Arg, limb_type>::value || is_same<Arg, signed_limb_type>::value
-#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE)
- || is_same<Arg, double_limb_type>::value || is_same<Arg, signed_double_limb_type>::value
-#endif
-#if defined(BOOST_MP_USER_DEFINED_LITERALS)
- || literals::detail::is_value_pack<Arg>::value
+struct is_allowed_cpp_int_base_conversion : public std::conditional<
+ std::is_same<Arg, limb_type>::value || std::is_same<Arg, signed_limb_type>::value
+#if BOOST_MP_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
+ || std::is_same<Arg, double_limb_type>::value || std::is_same<Arg, signed_double_limb_type>::value
#endif
- || (is_trivial_cpp_int<Base>::value && is_arithmetic<Arg>::value),
- mpl::true_,
- mpl::false_
- >::type
+ || literals::detail::is_value_pack<Arg>::value || (is_trivial_cpp_int<Base>::value && boost::multiprecision::detail::is_arithmetic<Arg>::value),
+ std::integral_constant<bool, true>,
+ std::integral_constant<bool, false>>::type
{};
//
// Now the actual backend, normalising parameters passed to the base class:
//
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
struct cpp_int_backend
- : public cpp_int_base<
- min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
- max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
- SignType,
- Checked,
- Allocator,
- is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value>
+ : public cpp_int_base<
+ min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
+ max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
+ SignType,
+ Checked,
+ Allocator,
+ is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value>
{
- typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> self_type;
- typedef cpp_int_base<
- min_precision<self_type>::value,
- max_precision<self_type>::value,
- SignType,
- Checked,
- Allocator,
- is_trivial_cpp_int<self_type>::value> base_type;
- typedef mpl::bool_<is_trivial_cpp_int<self_type>::value> trivial_tag;
-public:
- typedef typename mpl::if_<
- trivial_tag,
- mpl::list<
- signed char, short, int, long,
- boost::long_long_type, signed_double_limb_type>,
- mpl::list<signed_limb_type, signed_double_limb_type>
- >::type signed_types;
- typedef typename mpl::if_<
- trivial_tag,
- mpl::list<unsigned char, unsigned short, unsigned,
- unsigned long, boost::ulong_long_type, double_limb_type>,
- mpl::list<limb_type, double_limb_type>
- >::type unsigned_types;
- typedef typename mpl::if_<
- trivial_tag,
- mpl::list<float, double, long double>,
- mpl::list<long double>
- >::type float_types;
- typedef mpl::int_<Checked> checked_type;
-
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend() BOOST_NOEXCEPT{}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF(boost::is_void<Allocator>::value) : base_type(o) {}
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(cpp_int_backend&& o) BOOST_NOEXCEPT
- : base_type(static_cast<base_type&&>(o)) {}
-#endif
+ using self_type = cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>;
+ using base_type = cpp_int_base<
+ min_precision<self_type>::value,
+ max_precision<self_type>::value,
+ SignType,
+ Checked,
+ Allocator,
+ is_trivial_cpp_int<self_type>::value>;
+ using trivial_tag = std::integral_constant<bool, is_trivial_cpp_int<self_type>::value>;
+
+ public:
+ using signed_types = typename std::conditional<
+ is_trivial_cpp_int<self_type>::value,
+ std::tuple<
+ signed char, short, int, long,
+ long long, signed_double_limb_type>,
+ std::tuple<signed_limb_type, signed_double_limb_type> >::type;
+ using unsigned_types = typename std::conditional<
+ is_trivial_cpp_int<self_type>::value,
+ std::tuple<unsigned char, unsigned short, unsigned,
+ unsigned long, unsigned long long, double_limb_type>,
+ std::tuple<limb_type, double_limb_type> >::type;
+ using float_types = typename std::conditional<
+ is_trivial_cpp_int<self_type>::value,
+ std::tuple<float, double, long double>,
+ std::tuple<long double> >::type;
+ using checked_type = std::integral_constant<int, Checked> ;
+
+ BOOST_MP_FORCEINLINE constexpr cpp_int_backend() noexcept {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_backend(const cpp_int_backend& o) noexcept(std::is_void<Allocator>::value) : base_type(o) {}
+ // rvalue copy:
+ BOOST_MP_FORCEINLINE constexpr cpp_int_backend(cpp_int_backend&& o) noexcept
+ : base_type(static_cast<base_type&&>(o))
+ {}
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2>
+ BOOST_MP_FORCEINLINE BOOST_CXX14_CONSTEXPR cpp_int_backend(cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2>&& o, typename std::enable_if<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2>, self_type>::value>::type* = nullptr) noexcept
+ {
+ *this = static_cast<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2>&&>(o);
+ }
//
// Direct construction from arithmetic type:
//
template <class Arg>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(Arg i, typename boost::enable_if_c<is_allowed_cpp_int_base_conversion<Arg, base_type>::value >::type const* = 0)BOOST_MP_NOEXCEPT_IF(noexcept(base_type(std::declval<Arg>())))
- : base_type(i) {}
+ BOOST_MP_FORCEINLINE constexpr cpp_int_backend(Arg i, typename std::enable_if<is_allowed_cpp_int_base_conversion<Arg, base_type>::value>::type const* = nullptr) noexcept(noexcept(base_type(std::declval<Arg>())))
+ : base_type(i) {}
+ //
+ // Aliasing constructor: the result will alias the memory referenced, unless
+ // we have fixed precision and storage, in which case we copy the memory:
+ //
+ explicit constexpr cpp_int_backend(limb_type* data, std::size_t offset, std::size_t len) noexcept
+ : base_type(data, offset, len) {}
+ explicit cpp_int_backend(const limb_type* data, std::size_t offset, std::size_t len) noexcept
+ : base_type(data, offset, len) { this->normalize(); }
+ explicit constexpr cpp_int_backend(typename base_type::scoped_shared_storage& data, std::size_t len) noexcept
+ : base_type(data, len) {}
-private:
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::true_ const &)
+ private:
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, std::true_type const&, std::true_type const&)
{
// Assigning trivial type to trivial type:
this->check_in_range(*other.limbs());
@@ -1121,245 +1396,320 @@ private:
this->sign(other.sign());
this->normalize();
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::false_ const &)
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, std::true_type const&, std::false_type const&)
{
// non-trivial to trivial narrowing conversion:
double_limb_type v = *other.limbs();
- if(other.size() > 1)
+ if (other.size() > 1)
{
v |= static_cast<double_limb_type>(other.limbs()[1]) << bits_per_limb;
- if((Checked == checked) && (other.size() > 2))
+ BOOST_IF_CONSTEXPR(Checked == checked)
{
- BOOST_THROW_EXCEPTION(std::range_error("Assignment of a cpp_int that is out of range for the target type."));
+ if (other.size() > 2)
+ {
+ BOOST_MP_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 <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::true_ const &)
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, std::false_type const&, std::true_type 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 cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type,
- cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>
- >::type
- >(*other.limbs());
- this->sign(other.sign());
+ *this = static_cast<
+ typename boost::multiprecision::detail::canonical<
+ typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type,
+ cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::type>(*other.limbs());
+ this->sign(other.sign());
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::false_ const &)
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, std::false_type const&, std::false_type 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]));
+
+#if !defined(BOOST_MP_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
+ std::size_t count = (std::min)(other.size(), this->size());
+ for (std::size_t i = 0; i < count; ++i)
+ this->limbs()[i] = other.limbs()[i];
+#else
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(other.size()))
+ {
+ std::size_t count = (std::min)(other.size(), this->size());
+ for (std::size_t i = 0; i < count; ++i)
+ this->limbs()[i] = other.limbs()[i];
+ }
+ else
+#endif
+ {
+ static_assert(sizeof(other.limbs()[0]) == sizeof(this->limbs()[0]), "This method requires equal limb sizes");
+ std::memcpy(this->limbs(), other.limbs(), (std::min)(other.size() * sizeof(other.limbs()[0]), this->size() * sizeof(this->limbs()[0])));
+ }
+#endif
this->sign(other.sign());
this->normalize();
}
-public:
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- cpp_int_backend(
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
- typename boost::enable_if_c<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value>::type* = 0)
- : base_type()
+
+ public:
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR cpp_int_backend(
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
+ typename std::enable_if<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value>::type* = nullptr)
+ : base_type()
{
do_assign(
- other,
- mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
- mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
+ other,
+ std::integral_constant<bool, is_trivial_cpp_int<self_type>::value>(),
+ std::integral_constant<bool, is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- explicit cpp_int_backend(
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
- typename boost::disable_if_c<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value>::type* = 0)
- : base_type()
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ explicit BOOST_MP_CXX14_CONSTEXPR cpp_int_backend(
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
+ typename std::enable_if< !(is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value)>::type* = nullptr)
+ : base_type()
{
do_assign(
- other,
- mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
- mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
+ other,
+ std::integral_constant<bool, is_trivial_cpp_int<self_type>::value>(),
+ std::integral_constant<bool, is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- cpp_int_backend& operator=(
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other)
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR cpp_int_backend& operator=(
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other)
{
do_assign(
- other,
- mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
- mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
+ other,
+ std::integral_constant<bool, is_trivial_cpp_int<self_type>::value>(),
+ std::integral_constant<bool, is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
return *this;
}
-#ifdef BOOST_MP_USER_DEFINED_LITERALS
- BOOST_CONSTEXPR cpp_int_backend(const cpp_int_backend& a, const literals::detail::negate_tag& tag)
- : base_type(static_cast<const base_type&>(a), tag){}
-#endif
+ constexpr cpp_int_backend(const cpp_int_backend& a, const literals::detail::negate_tag& tag)
+ : base_type(static_cast<const base_type&>(a), tag)
+ {}
- BOOST_MP_FORCEINLINE cpp_int_backend& operator = (const cpp_int_backend& o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().assign(std::declval<const cpp_int_backend&>())))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_backend& operator=(const cpp_int_backend& o) noexcept(noexcept(std::declval<cpp_int_backend>().assign(std::declval<const cpp_int_backend&>())))
{
this->assign(o);
return *this;
}
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- BOOST_MP_FORCEINLINE cpp_int_backend& operator = (cpp_int_backend&& o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<base_type&>() = std::declval<base_type>()))
+ // rvalue copy:
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_backend& operator=(cpp_int_backend&& o) noexcept(noexcept(std::declval<base_type&>() = std::declval<base_type>()))
{
*static_cast<base_type*>(this) = static_cast<base_type&&>(o);
return *this;
}
-#endif
-private:
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<((MaxBits2 <= MaxBits) || (MaxBits == 0)) && !std::is_void<Allocator>::value, cpp_int_backend&>::type operator=(cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator>&& o) noexcept
+ {
+ *static_cast<base_type*>(this) = static_cast<typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2>::base_type&&>(o);
+ return *this;
+ }
+
template <class A>
- typename boost::enable_if<is_unsigned<A> >::type do_assign_arithmetic(A val, const mpl::true_&)
- BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().check_in_range(std::declval<A>())))
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_unsigned<A>::value
+ && trivial_tag::value, cpp_int_backend&>::type
+ operator=(const A& val)
+ noexcept(noexcept(std::declval<cpp_int_backend>().check_in_range(std::declval<A>())))
{
this->check_in_range(val);
*this->limbs() = static_cast<typename self_type::local_limb_type>(val);
this->sign(false);
this->normalize();
+ return *this;
}
template <class A>
- typename boost::disable_if_c<is_unsigned<A>::value || !is_integral<A>::value >::type do_assign_arithmetic(A val, const mpl::true_&)
- BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().check_in_range(std::declval<A>())) && noexcept(std::declval<cpp_int_backend>().sign(true)))
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !(boost::multiprecision::detail::is_unsigned<A>::value || !boost::multiprecision::detail::is_integral<A>::value)
+ && trivial_tag::value, cpp_int_backend&>::type
+ operator=(const A& val)
+ noexcept(noexcept(std::declval<cpp_int_backend>().check_in_range(std::declval<A>())) && noexcept(std::declval<cpp_int_backend>().sign(true)))
{
this->check_in_range(val);
*this->limbs() = (val < 0) ? static_cast<typename self_type::local_limb_type>(boost::multiprecision::detail::unsigned_abs(val)) : static_cast<typename self_type::local_limb_type>(val);
this->sign(val < 0);
this->normalize();
+ return *this;
}
template <class A>
- typename boost::enable_if_c< !is_integral<A>::value>::type do_assign_arithmetic(A val, const mpl::true_&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_convertible<A, limb_type>::value
+ && !boost::multiprecision::detail::is_integral<A>::value
+ && trivial_tag::value, cpp_int_backend&>::type
+ operator=(const A& val)
{
this->check_in_range(val);
*this->limbs() = (val < 0) ? static_cast<typename self_type::local_limb_type>(boost::multiprecision::detail::abs(val)) : static_cast<typename self_type::local_limb_type>(val);
this->sign(val < 0);
this->normalize();
+ return *this;
}
- BOOST_MP_FORCEINLINE void do_assign_arithmetic(limb_type i, const mpl::false_&) BOOST_NOEXCEPT
+ template <class A>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<A, limb_type>::value && !trivial_tag::value, cpp_int_backend&>::type
+ operator=(A i) noexcept
{
this->resize(1, 1);
*this->limbs() = i;
this->sign(false);
+ return *this;
}
- BOOST_MP_FORCEINLINE void do_assign_arithmetic(signed_limb_type i, const mpl::false_&) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().sign(true)))
+ template <class A>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if <
+ std::is_same<A, signed_limb_type>::value && !trivial_tag::value, cpp_int_backend&>::type
+ operator=(A i) noexcept(noexcept(std::declval<cpp_int_backend>().sign(true)))
{
this->resize(1, 1);
*this->limbs() = static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(i));
this->sign(i < 0);
+ return *this;
}
- void do_assign_arithmetic(double_limb_type i, const mpl::false_&) BOOST_NOEXCEPT
+ template <class A>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if <
+ std::is_same<A, double_limb_type>::value && !trivial_tag::value, cpp_int_backend&>::type
+ operator=(A i) noexcept
{
- BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
- BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2);
+ static_assert(sizeof(i) == 2 * sizeof(limb_type), "Failed integer size check");
+ static_assert(base_type::internal_limb_count >= 2, "Failed internal limb count");
typename base_type::limb_pointer p = this->limbs();
#ifdef __MSVC_RUNTIME_CHECKS
*p = static_cast<limb_type>(i & ~static_cast<limb_type>(0));
#else
- *p = static_cast<limb_type>(i);
+ *p = static_cast<limb_type>(i);
#endif
p[1] = static_cast<limb_type>(i >> base_type::limb_bits);
this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1);
this->sign(false);
+ return *this;
}
- void do_assign_arithmetic(signed_double_limb_type i, const mpl::false_&) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().sign(true)))
+ template <class A>
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if <
+ std::is_same<A, signed_double_limb_type>::value && !trivial_tag::value, cpp_int_backend&>::type
+ operator=(A i) noexcept(noexcept(std::declval<cpp_int_backend>().sign(true)))
{
- BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
- BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2);
+ static_assert(sizeof(i) == 2 * sizeof(limb_type), "double limb type size check failed");
+ static_assert(base_type::internal_limb_count >= 2, "Failed internal limb count check");
bool s = false;
- double_limb_type ui;
- if(i < 0)
+ if (i < 0)
s = true;
- ui = static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i));
- typename base_type::limb_pointer p = this->limbs();
+ double_limb_type ui = static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i));
+ typename base_type::limb_pointer p = this->limbs();
#ifdef __MSVC_RUNTIME_CHECKS
*p = static_cast<limb_type>(ui & ~static_cast<limb_type>(0));
#else
- *p = static_cast<limb_type>(ui);
+ *p = static_cast<limb_type>(ui);
#endif
p[1] = static_cast<limb_type>(ui >> base_type::limb_bits);
this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1);
this->sign(s);
+ return *this;
}
-
- void do_assign_arithmetic(long double a, const mpl::false_&)
+private:
+ template <class F>
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_float(F a)
{
using default_ops::eval_add;
using default_ops::eval_subtract;
- using std::frexp;
- using std::ldexp;
- using std::floor;
+ BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp;
- if(a < 0)
+ if (a < 0)
{
- do_assign_arithmetic(-a, mpl::false_());
+ do_assign_float(-a);
this->sign(true);
return;
}
- if (a == 0) {
+ if (a == 0)
+ {
*this = static_cast<limb_type>(0u);
}
- if (a == 1) {
+ if (a == 1)
+ {
*this = static_cast<limb_type>(1u);
}
- BOOST_ASSERT(!(boost::math::isinf)(a));
- BOOST_ASSERT(!(boost::math::isnan)(a));
+ if (!BOOST_MP_ISFINITE(a))
+ {
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Cannot convert a non-finite number to an integer."));
+ }
- int e;
- long double f, term;
+ int e = 0;
+ F f(0), term(0);
*this = static_cast<limb_type>(0u);
f = frexp(a, &e);
- static const limb_type shift = std::numeric_limits<limb_type>::digits;
+#if !(defined(__clang__) && (__clang_major__ <= 7))
+ constexpr limb_type shift = std::numeric_limits<limb_type>::digits;
+#else
+ // clang 7 has an issue converting long double to unsigned long long in
+ // release mode (bits get dropped, conversion appears to go via float)
+ // Never extract more than double bits at a time:
+ constexpr limb_type shift = std::numeric_limits<limb_type>::digits > std::numeric_limits<double>::digits
+ ? std::numeric_limits<double>::digits : std::numeric_limits<limb_type>::digits;
+#endif
- while(f)
+ while (f != static_cast<F>(0.0f))
{
// extract int sized bits from f:
- f = ldexp(f, shift);
+ f = ldexp(f, shift);
term = floor(f);
- e -= shift;
+ e = e - static_cast<int>(shift);
eval_left_shift(*this, shift);
- if(term > 0)
+#if !(defined(__clang__) && (__clang_major__ <= 7))
+ if (term > 0)
eval_add(*this, static_cast<limb_type>(term));
else
eval_subtract(*this, static_cast<limb_type>(-term));
+#else
+ // clang 7 requires extra cast to double to avoid buggy code generation:
+ if (term > 0)
+ eval_add(*this, static_cast<limb_type>(static_cast<double>(term)));
+ else
+ eval_subtract(*this, static_cast<limb_type>(static_cast<double>(-term)));
+#endif
f -= term;
}
- if(e > 0)
- eval_left_shift(*this, e);
- else if(e < 0)
- eval_right_shift(*this, -e);
+ if (e > 0)
+ eval_left_shift(*this, static_cast<unsigned int>(e));
+ else if (e < 0)
+ eval_right_shift(*this, static_cast<unsigned int>(-e));
}
public:
- template <class Arithmetic>
- BOOST_MP_FORCEINLINE typename boost::enable_if_c<!boost::multiprecision::detail::is_byte_container<Arithmetic>::value, cpp_int_backend&>::type operator = (Arithmetic val) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().do_assign_arithmetic(std::declval<Arithmetic>(), trivial_tag())))
+ template <class A>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if <
+ std::is_floating_point<A>::value && !trivial_tag::value, cpp_int_backend&>::type
+ operator=(A a)
{
- do_assign_arithmetic(val, trivial_tag());
+ do_assign_float(a);
return *this;
}
-private:
- void do_assign_string(const char* s, const mpl::true_&)
+
+ private:
+ void do_assign_string(const char* s, const std::integral_constant<bool, true>&)
{
- std::size_t n = s ? std::strlen(s) : 0;
- *this = 0;
+ std::size_t n = s ? std::strlen(s) : 0;
+ *this = 0;
unsigned radix = 10;
- bool isneg = false;
- if(n && (*s == '-'))
+ bool isneg = false;
+ if (n && (*s == '-'))
{
--n;
++s;
isneg = true;
}
- if(n && (*s == '0'))
+ if (n && (*s == '0'))
{
- if((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
+ if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
{
radix = 16;
- s +=2;
+ s += 2;
n -= 2;
}
else
@@ -1368,51 +1718,51 @@ private:
n -= 1;
}
}
- if(n)
+ if (n)
{
unsigned val;
- while(*s)
+ 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';
+ if (*s >= '0' && *s <= '9')
+ val = static_cast<unsigned>(*s - '0');
+ else if (*s >= 'a' && *s <= 'f')
+ val = 10u + static_cast<unsigned>(*s - 'a');
+ else if (*s >= 'A' && *s <= 'F')
+ val = 10u + static_cast<unsigned>(*s - 'A');
else
- val = radix + 1;
- if(val >= radix)
+ val = radix + 1u;
+ if (val >= radix)
{
- BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
}
*this->limbs() = detail::checked_multiply(*this->limbs(), static_cast<typename base_type::local_limb_type>(radix), checked_type());
*this->limbs() = detail::checked_add(*this->limbs(), static_cast<typename base_type::local_limb_type>(val), checked_type());
++s;
}
}
- if(isneg)
+ if (isneg)
this->negate();
}
- void do_assign_string(const char* s, const mpl::false_&)
+ void do_assign_string(const char* s, const std::integral_constant<bool, false>&)
{
- using default_ops::eval_multiply;
using default_ops::eval_add;
- std::size_t n = s ? std::strlen(s) : 0;
- *this = static_cast<limb_type>(0u);
+ using default_ops::eval_multiply;
+ std::size_t n = s ? std::strlen(s) : 0;
+ *this = static_cast<limb_type>(0u);
unsigned radix = 10;
- bool isneg = false;
- if(n && (*s == '-'))
+ bool isneg = false;
+ if (n && (*s == '-'))
{
--n;
++s;
isneg = true;
}
- if(n && (*s == '0'))
+ if (n && (*s == '0'))
{
- if((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
+ if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
{
radix = 16;
- s +=2;
+ s += 2;
n -= 2;
}
else
@@ -1427,37 +1777,38 @@ private:
// be left unchanged.
//
cpp_int_backend result;
- if(n)
+ if (n)
{
- if(radix == 16)
+ if (radix == 16)
{
- while(*s == '0') ++s;
+ while (*s == '0')
+ ++s;
std::size_t bitcount = 4 * std::strlen(s);
- limb_type val;
+ limb_type val;
std::size_t limb, shift;
- if(bitcount > 4)
+ if (bitcount > 4)
bitcount -= 4;
else
bitcount = 0;
std::size_t newsize = bitcount / (sizeof(limb_type) * CHAR_BIT) + 1;
- result.resize(static_cast<unsigned>(newsize), static_cast<unsigned>(newsize)); // will throw if this is a checked integer that cannot be resized
+ result.resize(static_cast<unsigned>(newsize), static_cast<unsigned>(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)
+ 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';
+ if (*s >= '0' && *s <= '9')
+ val = static_cast<unsigned>(*s - '0');
+ else if (*s >= 'a' && *s <= 'f')
+ val = 10u + static_cast<unsigned>(*s - 'a');
+ else if (*s >= 'A' && *s <= 'F')
+ val = 10u + static_cast<unsigned>(*s - 'A');
else
{
- BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
}
- limb = bitcount / (sizeof(limb_type) * CHAR_BIT);
+ limb = bitcount / (sizeof(limb_type) * CHAR_BIT);
shift = bitcount % (sizeof(limb_type) * CHAR_BIT);
val <<= shift;
- if(result.size() > limb)
+ if (result.size() > limb)
{
result.limbs()[limb] |= val;
}
@@ -1466,42 +1817,43 @@ private:
}
result.normalize();
}
- else if(radix == 8)
+ else if (radix == 8)
{
- while(*s == '0') ++s;
+ while (*s == '0')
+ ++s;
std::size_t bitcount = 3 * std::strlen(s);
- limb_type val;
+ limb_type val;
std::size_t limb, shift;
- if(bitcount > 3)
+ if (bitcount > 3)
bitcount -= 3;
else
bitcount = 0;
std::size_t newsize = bitcount / (sizeof(limb_type) * CHAR_BIT) + 1;
- result.resize(static_cast<unsigned>(newsize), static_cast<unsigned>(newsize)); // will throw if this is a checked integer that cannot be resized
+ result.resize(static_cast<unsigned>(newsize), static_cast<unsigned>(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)
+ while (*s)
{
- if(*s >= '0' && *s <= '7')
- val = *s - '0';
+ if (*s >= '0' && *s <= '7')
+ val = static_cast<unsigned>(*s - '0');
else
{
- BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
}
- limb = bitcount / (sizeof(limb_type) * CHAR_BIT);
+ limb = bitcount / (sizeof(limb_type) * CHAR_BIT);
shift = bitcount % (sizeof(limb_type) * CHAR_BIT);
- if(result.size() > limb)
+ if (result.size() > limb)
{
result.limbs()[limb] |= (val << shift);
- if(shift > sizeof(limb_type) * CHAR_BIT - 3)
+ 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 (val)
{
// If this is the most-significant-limb, we may need to allocate an extra one for the overflow:
- if(limb + 1 == newsize)
+ if (limb + 1 == newsize)
result.resize(static_cast<unsigned>(newsize + 1), static_cast<unsigned>(newsize + 1));
- if(result.size() > limb + 1)
+ if (result.size() > limb + 1)
{
result.limbs()[limb + 1] |= val;
}
@@ -1518,19 +1870,19 @@ private:
// 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)
+ while (*s)
{
limb_type block = 0;
- for(unsigned i = 0; i < digits_per_block_10; ++i)
+ for (unsigned i = 0; i < digits_per_block_10; ++i)
{
limb_type val;
- if(*s >= '0' && *s <= '9')
- val = *s - '0';
+ if (*s >= '0' && *s <= '9')
+ val = static_cast<limb_type>(*s - '0');
else
- BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected character encountered in input."));
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unexpected character encountered in input."));
block *= 10;
block += val;
- if(!*++s)
+ if (!*++s)
{
block_mult = block_multiplier(i);
break;
@@ -1541,247 +1893,255 @@ private:
}
}
}
- if(isneg)
+ if (isneg)
result.negate();
result.swap(*this);
}
-public:
- cpp_int_backend& operator = (const char* s)
+
+ public:
+ cpp_int_backend& operator=(const char* s)
{
do_assign_string(s, trivial_tag());
return *this;
}
- BOOST_MP_FORCEINLINE void swap(cpp_int_backend& o) BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(cpp_int_backend& o) noexcept
{
this->do_swap(o);
}
-private:
- std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::false_&)const
+
+ private:
+ std::string do_get_trivial_string(std::ios_base::fmtflags f, const std::integral_constant<bool, false>&) const
{
- typedef typename mpl::if_c<sizeof(typename base_type::local_limb_type) == 1, unsigned, typename base_type::local_limb_type>::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."));
+ using io_type = typename std::conditional<sizeof(typename base_type::local_limb_type) == 1, unsigned, typename base_type::local_limb_type>::type;
+ if (this->sign() && (((f & std::ios_base::hex) == std::ios_base::hex) || ((f & std::ios_base::oct) == std::ios_base::oct)))
+ BOOST_MP_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<io_type>(*this->limbs());
std::string result;
- if(this->sign())
+ if (this->sign())
result += '-';
- else if(f & std::ios_base::showpos)
+ 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
+ std::string do_get_trivial_string(std::ios_base::fmtflags f, const std::integral_constant<bool, 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)
+ if ((f & std::ios_base::oct) == std::ios_base::oct)
base = 8;
- else if((f & std::ios_base::hex) == std::ios_base::hex)
+ 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;
+ std::size_t Bits = sizeof(typename base_type::local_limb_type) * CHAR_BIT;
- if(base == 8 || base == 16)
+ 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<limb_type>((1u << shift) - 1);
- typename base_type::local_limb_type v = *this->limbs();
+ if (this->sign())
+ BOOST_MP_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<limb_type>((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)
+ std::string::difference_type pos = static_cast<std::string::difference_type>(result.size() - 1u);
+ char letter_a = f & std::ios_base::uppercase ? 'A' : 'a';
+ for (std::size_t i = 0; i < Bits / shift; ++i)
{
- char c = '0' + static_cast<char>(v & mask);
- if(c > '9')
- c += 'A' - '9' - 1;
- result[pos--] = c;
+ char c = static_cast<char>('0' + static_cast<char>(v & mask));
+ if (c > '9')
+ c = static_cast<char>(c + letter_a - '9' - 1);
+ result[static_cast<std::size_t>(pos)] = c;
+ --pos;
v >>= shift;
}
- if(Bits % shift)
+ if (Bits % shift)
{
- mask = static_cast<limb_type>((1u << (Bits % shift)) - 1);
- char c = '0' + static_cast<char>(v & mask);
- if(c > '9')
- c += 'A' - '9';
- result[pos] = c;
+ mask = static_cast<limb_type>((1u << (Bits % shift)) - 1);
+ char c = static_cast<char>('0' + static_cast<char>(v & mask));
+ if (c > '9')
+ c = static_cast<char>(c + letter_a - '9');
+ result[static_cast<std::size_t>(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))
+ if (!result.empty() && (n == std::string::npos))
n = result.size() - 1;
result.erase(0, n);
- if(f & std::ios_base::showbase)
+ if (f & std::ios_base::showbase)
{
- const char* pp = base == 8 ? "0" : "0x";
+ const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
result.insert(static_cast<std::string::size_type>(0), pp);
}
}
else
{
result.assign(Bits / 3 + 1, '0');
- std::string::difference_type pos = result.size() - 1;
+ std::string::difference_type pos = static_cast<std::string::difference_type>(result.size() - 1u);
typename base_type::local_limb_type v(*this->limbs());
- bool neg = false;
- if(this->sign())
+ bool neg = false;
+ if (this->sign())
{
neg = true;
}
- while(v)
+ while (v)
{
- result[pos] = (v % 10) + '0';
+ result[static_cast<std::string::size_type>(pos)] = static_cast<char>(static_cast<char>(v % 10) + '0');
--pos;
v /= 10;
}
std::string::size_type n = result.find_first_not_of('0');
result.erase(0, n);
- if(result.empty())
+ if (result.empty())
result = "0";
- if(neg)
+ if (neg)
result.insert(static_cast<std::string::size_type>(0), 1, '-');
- else if(f & std::ios_base::showpos)
+ else if (f & std::ios_base::showpos)
result.insert(static_cast<std::string::size_type>(0), 1, '+');
}
return result;
}
- std::string do_get_string(std::ios_base::fmtflags f, const mpl::true_&)const
+ std::string do_get_string(std::ios_base::fmtflags f, const std::integral_constant<bool, true>&) const
{
#ifdef BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO
- return do_get_trivial_string(f, mpl::bool_<is_same<typename base_type::local_limb_type, double_limb_type>::value>());
+ return do_get_trivial_string(f, std::integral_constant<bool, std::is_same<typename base_type::local_limb_type, double_limb_type>::value>());
#else
- return do_get_trivial_string(f, mpl::bool_<false>());
+ return do_get_trivial_string(f, std::integral_constant<bool, false>());
#endif
}
- std::string do_get_string(std::ios_base::fmtflags f, const mpl::false_&)const
+ std::string do_get_string(std::ios_base::fmtflags f, const std::integral_constant<bool, false>&) const
{
using default_ops::eval_get_sign;
int base = 10;
- if((f & std::ios_base::oct) == std::ios_base::oct)
+ if ((f & std::ios_base::oct) == std::ios_base::oct)
base = 8;
- else if((f & std::ios_base::hex) == std::ios_base::hex)
+ else if ((f & std::ios_base::hex) == std::ios_base::hex)
base = 16;
std::string result;
- unsigned Bits = this->size() * base_type::limb_bits;
+ std::size_t Bits = this->size() * base_type::limb_bits;
- if(base == 8 || base == 16)
+ 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<limb_type>((1u << shift) - 1);
+ if (this->sign())
+ BOOST_MP_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<limb_type>((1u << shift) - 1);
cpp_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)
+ std::string::difference_type pos = static_cast<std::string::difference_type>(result.size() - 1u);
+ char letter_a = f & std::ios_base::uppercase ? 'A' : 'a';
+ for (std::size_t i = 0; i < Bits / shift; ++i)
{
- char c = '0' + static_cast<char>(t.limbs()[0] & mask);
- if(c > '9')
- c += 'A' - '9' - 1;
- result[pos--] = c;
+ char c = static_cast<char>('0' + static_cast<char>(t.limbs()[0] & mask));
+ if (c > '9')
+ c = static_cast<char>(c + letter_a - '9' - 1);
+ result[static_cast<std::size_t>(pos)] = c;
+ --pos;
eval_right_shift(t, shift);
}
- if(Bits % shift)
+ if (Bits % shift)
{
- mask = static_cast<limb_type>((1u << (Bits % shift)) - 1);
- char c = '0' + static_cast<char>(t.limbs()[0] & mask);
- if(c > '9')
- c += 'A' - '9';
- result[pos] = c;
+ mask = static_cast<limb_type>((1u << (Bits % shift)) - 1);
+ char c = static_cast<char>('0' + static_cast<char>(t.limbs()[0] & mask));
+ if (c > '9')
+ c = static_cast<char>(c + letter_a - '9');
+ result[static_cast<std::size_t>(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))
+ if (!result.empty() && (n == std::string::npos))
n = result.size() - 1;
result.erase(0, n);
- if(f & std::ios_base::showbase)
+ if (f & std::ios_base::showbase)
{
- const char* pp = base == 8 ? "0" : "0x";
+ const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
result.insert(static_cast<std::string::size_type>(0), pp);
}
}
else
{
result.assign(Bits / 3 + 1, '0');
- std::string::difference_type pos = result.size() - 1;
- cpp_int_backend t(*this);
- cpp_int_backend r;
- bool neg = false;
- if(t.sign())
+ std::string::difference_type pos = static_cast<std::string::difference_type>(result.size() - 1u);
+ cpp_int_backend t(*this);
+ cpp_int_backend r;
+ bool neg = false;
+ if (t.sign())
{
t.negate();
neg = true;
}
- if(this->size() == 1)
+ if (this->size() == 1)
{
- result = boost::lexical_cast<std::string>(t.limbs()[0]);
+ result = std::to_string(t.limbs()[0]);
}
else
{
cpp_int_backend block10;
block10 = max_block_10;
- while(eval_get_sign(t) != 0)
+ while (eval_get_sign(t) != 0)
{
cpp_int_backend t2;
divide_unsigned_helper(&t2, t, block10, r);
- t = t2;
+ t = t2;
limb_type v = r.limbs()[0];
- for(unsigned i = 0; i < digits_per_block_10; ++i)
+ for (std::size_t i = 0; i < digits_per_block_10; ++i)
{
- char c = '0' + v % 10;
+ char c = static_cast<char>('0' + static_cast<char>(v % 10));
v /= 10;
- result[pos] = c;
- if(pos-- == 0)
+ result[static_cast<std::size_t>(pos)] = c;
+ if (pos-- == 0u)
break;
}
}
}
std::string::size_type n = result.find_first_not_of('0');
result.erase(0, n);
- if(result.empty())
- result = "0";
- if(neg)
+ if (result.empty())
+ result = std::string(static_cast<std::size_t>(1u), '0');
+ if (neg)
result.insert(static_cast<std::string::size_type>(0), 1, '-');
- else if(f & std::ios_base::showpos)
+ else if (f & std::ios_base::showpos)
result.insert(static_cast<std::string::size_type>(0), 1, '+');
}
return result;
}
-public:
- std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f)const
+
+ public:
+ std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f) const
{
return do_get_string(f, trivial_tag());
}
-private:
+
+ private:
template <class Container>
- void construct_from_container(const Container& c, const mpl::false_&)
+ void construct_from_container(const Container& c, const std::integral_constant<bool, false>&)
{
//
// We assume that c is a sequence of (unsigned) bytes with the most significant byte first:
//
- unsigned newsize = static_cast<unsigned>(c.size() / sizeof(limb_type));
- if(c.size() % sizeof(limb_type))
+ std::size_t newsize = static_cast<unsigned>(c.size() / sizeof(limb_type));
+ if (c.size() % sizeof(limb_type))
{
++newsize;
}
- if(newsize)
+ if (newsize)
{
- this->resize(newsize, newsize); // May throw
+ this->resize(newsize, newsize); // May throw
std::memset(this->limbs(), 0, this->size());
typename Container::const_iterator i(c.begin()), j(c.end());
- unsigned byte_location = static_cast<unsigned>(c.size() - 1);
- while(i != j)
+ std::size_t byte_location = static_cast<unsigned>(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)
+ std::size_t limb = byte_location / sizeof(limb_type);
+ std::size_t shift = (byte_location % sizeof(limb_type)) * CHAR_BIT;
+ if (this->size() > limb)
this->limbs()[limb] |= static_cast<limb_type>(static_cast<unsigned char>(*i)) << shift;
++i;
--byte_location;
@@ -1789,68 +2149,69 @@ private:
}
}
template <class Container>
- void construct_from_container(const Container& c, const mpl::true_&)
+ BOOST_MP_CXX14_CONSTEXPR void construct_from_container(const Container& c, const std::integral_constant<bool, 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;
+ using local_limb_type = typename base_type::local_limb_type;
*this->limbs() = 0;
- if(c.size())
+ if (c.size())
{
typename Container::const_iterator i(c.begin()), j(c.end());
- unsigned byte_location = static_cast<unsigned>(c.size() - 1);
- while(i != j)
+ std::size_t byte_location = static_cast<unsigned>(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)
+ std::size_t limb = byte_location / sizeof(local_limb_type);
+ std::size_t shift = (byte_location % sizeof(local_limb_type)) * CHAR_BIT;
+ if (limb == 0)
this->limbs()[0] |= static_cast<limb_type>(static_cast<unsigned char>(*i)) << shift;
++i;
--byte_location;
}
}
}
-public:
+
+ public:
template <class Container>
- cpp_int_backend(const Container& c, typename boost::enable_if_c<boost::multiprecision::detail::is_byte_container<Container>::value>::type const* = 0)
+ BOOST_MP_CXX14_CONSTEXPR cpp_int_backend(const Container& c, typename std::enable_if<boost::multiprecision::detail::is_byte_container<Container>::value>::type const* = nullptr)
{
//
// We assume that c is a sequence of (unsigned) bytes with the most significant byte first:
//
construct_from_container(c, trivial_tag());
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::false_&, const mpl::false_&)const BOOST_NOEXCEPT
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&) const noexcept
{
- if(this->sign() != o.sign())
+ 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())
+ if (this->sign())
result = -result;
return result;
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::true_&, const mpl::false_&)const
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&) const
{
cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> t(*this);
return t.compare(o);
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::false_&, const mpl::true_&)const
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&) const
{
cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> t(o);
return compare(t);
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::true_&, const mpl::true_&)const BOOST_NOEXCEPT
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&) const noexcept
{
- if(this->sign())
+ if (this->sign())
{
- if(o.sign())
+ if (o.sign())
{
return *this->limbs() < *o.limbs() ? 1 : (*this->limbs() > *o.limbs() ? -1 : 0);
}
@@ -1859,36 +2220,36 @@ public:
}
else
{
- if(o.sign())
+ if (o.sign())
return 1;
return *this->limbs() < *o.limbs() ? -1 : (*this->limbs() > *o.limbs() ? 1 : 0);
}
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- int compare(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o)const BOOST_NOEXCEPT
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR int compare(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) const noexcept
{
- typedef mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> t1;
- typedef mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value> t2;
+ using t1 = std::integral_constant<bool, is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> ;
+ using t2 = std::integral_constant<bool, is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>;
return compare_imp(o, t1(), t2());
}
- template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- int compare_unsigned(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o)const BOOST_NOEXCEPT
+ template <std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+ BOOST_MP_CXX14_CONSTEXPR int compare_unsigned(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) const noexcept
{
- if(this->size() != o.size())
+ 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)
+ for (std::ptrdiff_t i = static_cast<std::ptrdiff_t>(static_cast<std::ptrdiff_t>(this->size()) - 1); i >= 0; --i)
{
- if(pa[i] != pb[i])
+ if (pa[i] != pb[i])
return pa[i] > pb[i] ? 1 : -1;
}
return 0;
}
template <class Arithmetic>
- BOOST_MP_FORCEINLINE typename boost::enable_if<is_arithmetic<Arithmetic>, int>::type compare(Arithmetic i)const
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<Arithmetic>::value, int>::type compare(Arithmetic i) const
{
// braindead version:
cpp_int_backend t;
@@ -1899,103 +2260,98 @@ public:
} // namespace backends
-namespace default_ops{
+namespace default_ops {
template <class Backend>
struct double_precision_type;
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
struct double_precision_type<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
{
- typedef typename mpl::if_c<
- backends::is_fixed_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
- backends::cpp_int_backend<
- (is_void<Allocator>::value ?
- 2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value
- : MinBits),
- 2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
- SignType,
- Checked,
- Allocator>,
- backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>
- >::type type;
+ using type = typename std::conditional<
+ backends::is_fixed_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
+ backends::cpp_int_backend<
+ (std::is_void<Allocator>::value ? 2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value
+ : MinBits),
+ 2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
+ SignType,
+ Checked,
+ Allocator>,
+ backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::type;
};
+} // namespace default_ops
-}
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+struct is_equivalent_number_type<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, backends::cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >
+ : public std::integral_constant<bool, std::numeric_limits<number<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, et_on> >::digits == std::numeric_limits<number<backends::cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, et_on> >::digits>{};
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked>
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked>
struct expression_template_default<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, void> >
{
- static const expression_template_option value = et_off;
+ static constexpr expression_template_option value = et_off;
};
using boost::multiprecision::backends::cpp_int_backend;
-template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
-struct number_category<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > : public mpl::int_<number_kind_integer>{};
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+struct number_category<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > : public std::integral_constant<int, number_kind_integer>
+{};
-typedef number<cpp_int_backend<> > cpp_int;
-typedef rational_adaptor<cpp_int_backend<> > cpp_rational_backend;
-typedef number<cpp_rational_backend> cpp_rational;
+using cpp_int = number<cpp_int_backend<> > ;
+using cpp_rational_backend = rational_adaptor<cpp_int_backend<> >;
+using cpp_rational = number<cpp_rational_backend> ;
// Fixed precision unsigned types:
-typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> > uint128_t;
-typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> > uint256_t;
-typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> > uint512_t;
-typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t;
+using uint128_t = number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> > ;
+using uint256_t = number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> > ;
+using uint512_t = number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> > ;
+using uint1024_t = number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> >;
// Fixed precision signed types:
-typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> > int128_t;
-typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> > int256_t;
-typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> > int512_t;
-typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> > int1024_t;
+using int128_t = number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> > ;
+using int256_t = number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> > ;
+using int512_t = number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> > ;
+using int1024_t = number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> >;
// Over again, but with checking enabled this time:
-typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_int;
-typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_rational_backend;
-typedef number<checked_cpp_rational_backend> checked_cpp_rational;
+using checked_cpp_int = number<cpp_int_backend<0, 0, signed_magnitude, checked> > ;
+using checked_cpp_rational_backend = rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> >;
+using checked_cpp_rational = number<checked_cpp_rational_backend> ;
// Fixed precision unsigned types:
-typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> > checked_uint128_t;
-typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> > checked_uint256_t;
-typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> > checked_uint512_t;
-typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> > checked_uint1024_t;
+using checked_uint128_t = number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> > ;
+using checked_uint256_t = number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> > ;
+using checked_uint512_t = number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> > ;
+using checked_uint1024_t = number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> >;
// Fixed precision signed types:
-typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> > checked_int128_t;
-typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> > checked_int256_t;
-typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> > checked_int512_t;
-typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> > checked_int1024_t;
-
-#ifdef BOOST_NO_SFINAE_EXPR
-
-namespace detail{
-
-template<unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-struct is_explicitly_convertible<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > : public mpl::true_ {};
-
-}
+using checked_int128_t = number<cpp_int_backend<128, 128, signed_magnitude, checked, void> > ;
+using checked_int256_t = number<cpp_int_backend<256, 256, signed_magnitude, checked, void> > ;
+using checked_int512_t = number<cpp_int_backend<512, 512, signed_magnitude, checked, void> > ;
+using checked_int1024_t = number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> >;
+
+#if defined(__GNUC__) && !defined(__clang__)
+// see https://github.com/boostorg/multiprecision/issues/413
+// and https://github.com/boostorg/multiprecision/issues/431
+#pragma GCC diagnostic pop
#endif
-
-#ifdef _MSC_VER
+#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
-}} // namespaces
+}} // namespace boost::multiprecision
//
// Last of all we include the implementations of all the eval_* non member functions:
//
+#include <boost/multiprecision/cpp_int/limits.hpp>
#include <boost/multiprecision/cpp_int/comparison.hpp>
#include <boost/multiprecision/cpp_int/add.hpp>
#include <boost/multiprecision/cpp_int/multiply.hpp>
#include <boost/multiprecision/cpp_int/divide.hpp>
#include <boost/multiprecision/cpp_int/bitwise.hpp>
#include <boost/multiprecision/cpp_int/misc.hpp>
-#include <boost/multiprecision/cpp_int/limits.hpp>
-#ifdef BOOST_MP_USER_DEFINED_LITERALS
#include <boost/multiprecision/cpp_int/literals.hpp>
-#endif
#include <boost/multiprecision/cpp_int/serialize.hpp>
#include <boost/multiprecision/cpp_int/import_export.hpp>
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/add.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/add.hpp
index f8ec7bb135..1b0f828534 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/add.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/add.hpp
@@ -1,111 +1,34 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
#ifndef BOOST_MP_CPP_INT_ADD_HPP
#define BOOST_MP_CPP_INT_ADD_HPP
-namespace boost{ namespace multiprecision{ namespace backends{
+#include <boost/multiprecision/detail/constexpr.hpp>
+#include <boost/multiprecision/cpp_int/add_unsigned.hpp>
-#ifdef _MSC_VER
-#pragma warning(push)
-#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 <class CppInt1, class CppInt2, class CppInt3>
-inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::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();
- minmax(as, bs, m, x);
- if(x == 1)
- {
- bool s = a.sign();
- result = static_cast<double_limb_type>(*a.limbs()) + static_cast<double_limb_type>(*b.limbs());
- result.sign(s);
- 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;
+namespace boost { namespace multiprecision { namespace backends {
- if(as < bs)
- swap(pa, pb);
-
- // First where a and b overlap:
- while(pr != pr_end)
- {
- carry += static_cast<double_limb_type>(*pa) + static_cast<double_limb_type>(*pb);
-#ifdef __MSVC_RUNTIME_CHECKS
- *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
-#else
- *pr = static_cast<limb_type>(carry);
-#endif
- carry >>= CppInt1::limb_bits;
- ++pr, ++pa, ++pb;
- }
- pr_end += x - m;
- // Now where only a has digits:
- while(pr != pr_end)
- {
- if(!carry)
- {
- if(pa != pr)
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(_LIBCPP_VERSION)
- std::copy(pa, pa + (pr_end - pr), stdext::checked_array_iterator<limb_type*>(pr, result.size()));
-#else
- std::copy(pa, pa + (pr_end - pr), pr);
-#endif
- break;
- }
- carry += static_cast<double_limb_type>(*pa);
-#ifdef __MSVC_RUNTIME_CHECKS
- *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
-#else
- *pr = static_cast<limb_type>(carry);
-#endif
- carry >>= CppInt1::limb_bits;
- ++pr, ++pa;
- }
- if(carry)
- {
- // We overflowed, need to add one more limb:
- result.resize(x + 1, x + 1);
- if(result.size() > x)
- result.limbs()[x] = static_cast<limb_type>(carry);
- }
- result.normalize();
- result.sign(a.sign());
-}
//
// As above, but for adding a single limb to a non-trivial cpp_int:
//
template <class CppInt1, class CppInt2>
-inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
+inline BOOST_MP_CXX14_CONSTEXPR void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) noexcept(is_non_throwing_cpp_int<CppInt1>::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();
+ std::size_t 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<double_limb_type>(pa[i]);
#ifdef __MSVC_RUNTIME_CHECKS
@@ -116,158 +39,65 @@ 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)
- pr[i] = pa[i];
+ std_constexpr::copy(pa + i, pa + a.size(), pr + i);
}
- if(carry)
+ if (carry)
{
// We overflowed, need to add one more limb:
- unsigned x = result.size();
+ std::size_t x = result.size();
result.resize(x + 1, x + 1);
- if(result.size() > x)
+ if (result.size() > x)
result.limbs()[x] = static_cast<limb_type>(carry);
}
result.normalize();
result.sign(a.sign());
}
//
-// Core subtraction routine for all non-trivial cpp_int's:
-//
-template <class CppInt1, class CppInt2, class CppInt3>
-inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
-{
- using std::swap;
-
- // Nothing fancy, just let uintmax_t take the strain:
- double_limb_type borrow = 0;
- unsigned m, x;
- minmax(a.size(), b.size(), m, x);
- //
- // special cases for small limb counts:
- //
- if(x == 1)
- {
- bool s = a.sign();
- limb_type al = *a.limbs();
- limb_type bl = *b.limbs();
- if(bl > al)
- {
- std::swap(al, bl);
- s = !s;
- }
- result = al - bl;
- result.sign(s);
- return;
- }
- // This isn't used till later, but comparison has to occur before we resize the result,
- // as that may also resize a or b if this is an inplace operation:
- int c = a.compare_unsigned(b);
- // 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)
- {
- swap(pa, pb);
- swapped = true;
- }
- else if(c == 0)
- {
- result = static_cast<limb_type>(0);
- return;
- }
-
- unsigned i = 0;
- // First where a and b overlap:
- while(i < m)
- {
- borrow = static_cast<double_limb_type>(pa[i]) - static_cast<double_limb_type>(pb[i]) - borrow;
- pr[i] = static_cast<limb_type>(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))
- {
- borrow = static_cast<double_limb_type>(pa[i]) - borrow;
- pr[i] = static_cast<limb_type>(borrow);
- borrow = (borrow >> CppInt1::limb_bits) & 1u;
- ++i;
- }
- // Any remaining digits are the same as those in pa:
- if((x != i) && (pa != pr))
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(_LIBCPP_VERSION)
- std::copy(pa + i, pa + x, stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
-#else
- std::copy(pa + i, pa + x, pr + i);
-#endif
- BOOST_ASSERT(0 == borrow);
-
- //
- // We may have lost digits, if so update limb usage count:
- //
- result.normalize();
- result.sign(a.sign());
- if(swapped)
- result.negate();
-}
-//
// And again to subtract a single limb:
//
template <class CppInt1, class CppInt2>
-inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
+inline BOOST_MP_CXX14_CONSTEXPR void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
{
// Subtract one limb.
// Nothing fancy, just let uintmax_t take the strain:
- BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1);
+ constexpr double_limb_type borrow = static_cast<double_limb_type>(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) && !defined(_LIBCPP_VERSION)
- std::copy(pa + 1, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + 1, result.size() - 1));
-#else
- std::copy(pa + 1, pa + a.size(), pr + 1);
-#endif
+ std_constexpr::copy(pa + 1, pa + a.size(), pr + 1);
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<limb_type>((borrow + *pa) - b);
- unsigned i = 1;
- while(!pa[i])
+ *pr = static_cast<limb_type>((borrow + *pa) - b);
+ std::size_t i = 1;
+ 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) && !defined(_LIBCPP_VERSION)
- std::copy(pa + i, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
-#else
- std::copy(pa + i, pa + a.size(), pr + i);
-#endif
+ std_constexpr::copy(pa + i, pa + a.size(), pr + i);
}
result.normalize();
result.sign(a.sign());
@@ -277,99 +107,99 @@ 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 <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_add(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_add(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
eval_add(result, result, o);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, 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>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
- eval_add(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
+eval_add(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(a.sign() != b.sign())
+ if (a.sign() != b.sign())
{
subtract_unsigned(result, a, b);
return;
}
add_unsigned(result, a, b);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(result.sign())
+ if (result.sign())
{
subtract_unsigned(result, result, o);
}
else
add_unsigned(result, result, o);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_add(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_add(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(a.sign())
+ if (a.sign())
{
subtract_unsigned(result, a, o);
}
else
add_unsigned(result, a, o);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_add(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_add(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const signed_limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(o < 0)
+ if (o < 0)
eval_subtract(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
- else if(o > 0)
+ else if (o > 0)
eval_add(result, static_cast<limb_type>(o));
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_add(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_add(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const signed_limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(o < 0)
+ if (o < 0)
eval_subtract(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
- else if(o > 0)
+ else if (o > 0)
eval_add(result, a, static_cast<limb_type>(o));
- else if(&result != &a)
+ else if (&result != &a)
result = a;
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_subtract(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_subtract(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(result.sign())
+ if (result.sign())
{
add_unsigned(result, result, o);
}
else
subtract_unsigned(result, result, o);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_subtract(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_subtract(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(a.sign())
+ if (a.sign())
{
add_unsigned(result, a, o);
}
@@ -378,82 +208,84 @@ BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<Mi
subtract_unsigned(result, a, o);
}
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_subtract(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_subtract(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const signed_limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(o)
+ if (o)
{
- if(o < 0)
+ if (o < 0)
eval_add(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
else
eval_subtract(result, static_cast<limb_type>(o));
}
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_subtract(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_subtract(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const signed_limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(o)
+ if (o)
{
- if(o < 0)
+ if (o < 0)
eval_add(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
else
eval_subtract(result, a, static_cast<limb_type>(o));
}
- else if(&result != &a)
+ else if (&result != &a)
result = a;
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_increment(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_increment(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- static const limb_type one = 1;
- if(!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
+ constexpr limb_type one = 1;
+
+ if (!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
++result.limbs()[0];
else if (result.sign() && result.limbs()[0])
{
--result.limbs()[0];
- if (!result.limbs()[0])
+ if (!result.limbs()[0] && (result.size() == 1))
result.sign(false);
}
else
eval_add(result, one);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_decrement(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_decrement(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- static const limb_type one = 1;
- if(!result.sign() && result.limbs()[0])
+ constexpr limb_type one = 1;
+
+ if (!result.sign() && result.limbs()[0])
--result.limbs()[0];
else if (result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
++result.limbs()[0];
else
eval_subtract(result, one);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_subtract(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_subtract(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
eval_subtract(result, result, o);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, 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<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
- eval_subtract(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
+eval_subtract(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(a.sign() != b.sign())
+ if (a.sign() != b.sign())
{
add_unsigned(result, a, b);
return;
@@ -466,19 +298,16 @@ BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<Mi
//
// One of the arguments is signed:
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
- >::type
- eval_add(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type
+eval_add(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::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<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
result.negate();
@@ -491,36 +320,29 @@ inline typename enable_if_c<
result.normalize();
}
// Simple version for two unsigned arguments:
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- >::type
- eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
result.normalize();
}
// signed subtraction:
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
- >::type
- eval_subtract(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type
+eval_subtract(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(result.sign() != o.sign())
+ if (result.sign() != o.sign())
{
*result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::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<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
result.negate();
@@ -530,25 +352,17 @@ inline typename enable_if_c<
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- >::type
- eval_subtract(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_subtract(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
result.normalize();
}
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-}}} // namespaces
+}}} // namespace boost::multiprecision::backends
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/add_unsigned.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/add_unsigned.hpp
new file mode 100644
index 0000000000..2149767e1e
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/add_unsigned.hpp
@@ -0,0 +1,387 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2020 Madhur Chauhan.
+// Copyright 2020 John Maddock. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_MP_ADD_UNSIGNED_HPP
+#define BOOST_MP_ADD_UNSIGNED_HPP
+
+#include <boost/multiprecision/cpp_int/intel_intrinsics.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+
+namespace boost { namespace multiprecision { namespace backends {
+
+template <class CppInt1, class CppInt2, class CppInt3>
+inline BOOST_MP_CXX14_CONSTEXPR void add_unsigned_constexpr(CppInt1& result, const CppInt2& a, const CppInt3& b) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
+{
+ using ::boost::multiprecision::std_constexpr::swap;
+ //
+ // This is the generic, C++ only version of addition.
+ // It's also used for all constexpr branches, hence the name.
+ // Nothing fancy, just let uintmax_t take the strain:
+ //
+ double_limb_type carry = 0;
+ std::size_t m(0), x(0);
+ std::size_t as = a.size();
+ std::size_t bs = b.size();
+ minmax(as, bs, m, x);
+ if (x == 1)
+ {
+ bool s = a.sign();
+ result = static_cast<double_limb_type>(*a.limbs()) + static_cast<double_limb_type>(*b.limbs());
+ result.sign(s);
+ 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;
+
+ if (as < bs)
+ swap(pa, pb);
+
+ // First where a and b overlap:
+ while (pr != pr_end)
+ {
+ carry += static_cast<double_limb_type>(*pa) + static_cast<double_limb_type>(*pb);
+#ifdef __MSVC_RUNTIME_CHECKS
+ *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
+ *pr = static_cast<limb_type>(carry);
+#endif
+ carry >>= CppInt1::limb_bits;
+ ++pr, ++pa, ++pb;
+ }
+ pr_end += x - m;
+ // Now where only a has digits:
+ while (pr != pr_end)
+ {
+ if (!carry)
+ {
+ if (pa != pr)
+ std_constexpr::copy(pa, pa + (pr_end - pr), pr);
+ break;
+ }
+ carry += static_cast<double_limb_type>(*pa);
+#ifdef __MSVC_RUNTIME_CHECKS
+ *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
+ *pr = static_cast<limb_type>(carry);
+#endif
+ carry >>= CppInt1::limb_bits;
+ ++pr, ++pa;
+ }
+ if (carry)
+ {
+ // We overflowed, need to add one more limb:
+ result.resize(x + 1, x + 1);
+ if (result.size() > x)
+ result.limbs()[x] = static_cast<limb_type>(1u);
+ }
+ result.normalize();
+ result.sign(a.sign());
+}
+//
+// Core subtraction routine for all non-trivial cpp_int's:
+//
+template <class CppInt1, class CppInt2, class CppInt3>
+inline BOOST_MP_CXX14_CONSTEXPR void subtract_unsigned_constexpr(CppInt1& result, const CppInt2& a, const CppInt3& b) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
+{
+ using ::boost::multiprecision::std_constexpr::swap;
+ //
+ // This is the generic, C++ only version of subtraction.
+ // It's also used for all constexpr branches, hence the name.
+ // Nothing fancy, just let uintmax_t take the strain:
+ //
+ double_limb_type borrow = 0;
+ std::size_t m(0), x(0);
+ minmax(a.size(), b.size(), m, x);
+ //
+ // special cases for small limb counts:
+ //
+ if (x == 1)
+ {
+ bool s = a.sign();
+ limb_type al = *a.limbs();
+ limb_type bl = *b.limbs();
+ if (bl > al)
+ {
+ ::boost::multiprecision::std_constexpr::swap(al, bl);
+ s = !s;
+ }
+ result = al - bl;
+ result.sign(s);
+ return;
+ }
+ // This isn't used till later, but comparison has to occur before we resize the result,
+ // as that may also resize a or b if this is an inplace operation:
+ int c = a.compare_unsigned(b);
+ // 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)
+ {
+ swap(pa, pb);
+ swapped = true;
+ }
+ else if (c == 0)
+ {
+ result = static_cast<limb_type>(0);
+ return;
+ }
+
+ std::size_t i = 0;
+ // First where a and b overlap:
+ while (i < m)
+ {
+ borrow = static_cast<double_limb_type>(pa[i]) - static_cast<double_limb_type>(pb[i]) - borrow;
+ pr[i] = static_cast<limb_type>(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))
+ {
+ borrow = static_cast<double_limb_type>(pa[i]) - borrow;
+ pr[i] = static_cast<limb_type>(borrow);
+ borrow = (borrow >> CppInt1::limb_bits) & 1u;
+ ++i;
+ }
+ // Any remaining digits are the same as those in pa:
+ if ((x != i) && (pa != pr))
+ std_constexpr::copy(pa + i, pa + x, pr + i);
+ BOOST_MP_ASSERT(0 == borrow);
+
+ //
+ // We may have lost digits, if so update limb usage count:
+ //
+ result.normalize();
+ result.sign(a.sign());
+ if (swapped)
+ result.negate();
+}
+
+
+#ifdef BOOST_MP_HAS_IMMINTRIN_H
+//
+// This is the key addition routine where all the argument types are non-trivial cpp_int's:
+//
+//
+// This optimization is limited to: GCC, LLVM, ICC (Intel), MSVC for x86_64 and i386.
+// If your architecture and compiler supports ADC intrinsic, please file a bug
+//
+// As of May, 2020 major compilers don't recognize carry chain though adc
+// intrinsics are used to hint compilers to use ADC and still compilers don't
+// unroll the loop efficiently (except LLVM) so manual unrolling is done.
+//
+// Also note that these intrinsics were only introduced by Intel as part of the
+// ADX processor extensions, even though the addc instruction has been available
+// for basically all x86 processors. That means gcc-9, clang-9, msvc-14.2 and up
+// are required to support these intrinsics.
+//
+template <class CppInt1, class CppInt2, class CppInt3>
+inline BOOST_MP_CXX14_CONSTEXPR void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
+{
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(a.size()))
+ {
+ add_unsigned_constexpr(result, a, b);
+ }
+ else
+#endif
+ {
+ using std::swap;
+
+ // Nothing fancy, just let uintmax_t take the strain:
+ std::size_t m(0), x(0);
+ std::size_t as = a.size();
+ std::size_t bs = b.size();
+ minmax(as, bs, m, x);
+ if (x == 1)
+ {
+ bool s = a.sign();
+ result = static_cast<double_limb_type>(*a.limbs()) + static_cast<double_limb_type>(*b.limbs());
+ result.sign(s);
+ 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();
+
+ if (as < bs)
+ swap(pa, pb);
+ // First where a and b overlap:
+ std::size_t i = 0;
+ unsigned char carry = 0;
+#if defined(BOOST_MSVC) && !defined(BOOST_HAS_INT128) && defined(_M_X64)
+ //
+ // Special case for 32-bit limbs on 64-bit architecture - we can process
+ // 2 limbs with each instruction.
+ //
+ for (; i + 8 <= m; i += 8)
+ {
+ carry = _addcarry_u64(carry, *(unsigned long long*)(pa + i + 0), *(unsigned long long*)(pb + i + 0), (unsigned long long*)(pr + i));
+ carry = _addcarry_u64(carry, *(unsigned long long*)(pa + i + 2), *(unsigned long long*)(pb + i + 2), (unsigned long long*)(pr + i + 2));
+ carry = _addcarry_u64(carry, *(unsigned long long*)(pa + i + 4), *(unsigned long long*)(pb + i + 4), (unsigned long long*)(pr + i + 4));
+ carry = _addcarry_u64(carry, *(unsigned long long*)(pa + i + 6), *(unsigned long long*)(pb + i + 6), (unsigned long long*)(pr + i + 6));
+ }
+#else
+ for (; i + 4 <= m; i += 4)
+ {
+ carry = ::boost::multiprecision::detail::addcarry_limb(carry, pa[i + 0], pb[i + 0], pr + i);
+ carry = ::boost::multiprecision::detail::addcarry_limb(carry, pa[i + 1], pb[i + 1], pr + i + 1);
+ carry = ::boost::multiprecision::detail::addcarry_limb(carry, pa[i + 2], pb[i + 2], pr + i + 2);
+ carry = ::boost::multiprecision::detail::addcarry_limb(carry, pa[i + 3], pb[i + 3], pr + i + 3);
+ }
+#endif
+ for (; i < m; ++i)
+ carry = ::boost::multiprecision::detail::addcarry_limb(carry, pa[i], pb[i], pr + i);
+ for (; i < x && carry; ++i)
+ // We know carry is 1, so we just need to increment pa[i] (ie add a literal 1) and capture the carry:
+ carry = ::boost::multiprecision::detail::addcarry_limb(0, pa[i], 1, pr + i);
+ if (i == x && carry)
+ {
+ // We overflowed, need to add one more limb:
+ result.resize(x + 1, x + 1);
+ if (result.size() > x)
+ result.limbs()[x] = static_cast<limb_type>(1u);
+ }
+ else if ((x != i) && (pa != pr))
+ // Copy remaining digits only if we need to:
+ std_constexpr::copy(pa + i, pa + x, pr + i);
+ result.normalize();
+ result.sign(a.sign());
+ }
+}
+
+template <class CppInt1, class CppInt2, class CppInt3>
+inline BOOST_MP_CXX14_CONSTEXPR void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
+{
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(a.size()))
+ {
+ subtract_unsigned_constexpr(result, a, b);
+ }
+ else
+#endif
+ {
+ using std::swap;
+
+ // Nothing fancy, just let uintmax_t take the strain:
+ std::size_t m(0), x(0);
+ minmax(a.size(), b.size(), m, x);
+ //
+ // special cases for small limb counts:
+ //
+ if (x == 1)
+ {
+ bool s = a.sign();
+ limb_type al = *a.limbs();
+ limb_type bl = *b.limbs();
+ if (bl > al)
+ {
+ ::boost::multiprecision::std_constexpr::swap(al, bl);
+ s = !s;
+ }
+ result = al - bl;
+ result.sign(s);
+ return;
+ }
+ // This isn't used till later, but comparison has to occur before we resize the result,
+ // as that may also resize a or b if this is an inplace operation:
+ int c = a.compare_unsigned(b);
+ // 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)
+ {
+ swap(pa, pb);
+ swapped = true;
+ }
+ else if (c == 0)
+ {
+ result = static_cast<limb_type>(0);
+ return;
+ }
+
+ std::size_t i = 0;
+ unsigned char borrow = 0;
+ // First where a and b overlap:
+#if defined(BOOST_MSVC) && !defined(BOOST_HAS_INT128) && defined(_M_X64)
+ //
+ // Special case for 32-bit limbs on 64-bit architecture - we can process
+ // 2 limbs with each instruction.
+ //
+ for (; i + 8 <= m; i += 8)
+ {
+ borrow = _subborrow_u64(borrow, *reinterpret_cast<const unsigned long long*>(pa + i), *reinterpret_cast<const unsigned long long*>(pb + i), reinterpret_cast<unsigned long long*>(pr + i));
+ borrow = _subborrow_u64(borrow, *reinterpret_cast<const unsigned long long*>(pa + i + 2), *reinterpret_cast<const unsigned long long*>(pb + i + 2), reinterpret_cast<unsigned long long*>(pr + i + 2));
+ borrow = _subborrow_u64(borrow, *reinterpret_cast<const unsigned long long*>(pa + i + 4), *reinterpret_cast<const unsigned long long*>(pb + i + 4), reinterpret_cast<unsigned long long*>(pr + i + 4));
+ borrow = _subborrow_u64(borrow, *reinterpret_cast<const unsigned long long*>(pa + i + 6), *reinterpret_cast<const unsigned long long*>(pb + i + 6), reinterpret_cast<unsigned long long*>(pr + i + 6));
+ }
+#else
+ for(; i + 4 <= m; i += 4)
+ {
+ borrow = boost::multiprecision::detail::subborrow_limb(borrow, pa[i], pb[i], pr + i);
+ borrow = boost::multiprecision::detail::subborrow_limb(borrow, pa[i + 1], pb[i + 1], pr + i + 1);
+ borrow = boost::multiprecision::detail::subborrow_limb(borrow, pa[i + 2], pb[i + 2], pr + i + 2);
+ borrow = boost::multiprecision::detail::subborrow_limb(borrow, pa[i + 3], pb[i + 3], pr + i + 3);
+ }
+#endif
+ for (; i < m; ++i)
+ borrow = boost::multiprecision::detail::subborrow_limb(borrow, pa[i], pb[i], pr + i);
+
+ // Now where only a has digits, only as long as we've borrowed:
+ while (borrow && (i < x))
+ {
+ borrow = boost::multiprecision::detail::subborrow_limb(borrow, pa[i], 0, pr + i);
+ ++i;
+ }
+ // Any remaining digits are the same as those in pa:
+ if ((x != i) && (pa != pr))
+ std_constexpr::copy(pa + i, pa + x, pr + i);
+ BOOST_MP_ASSERT(0 == borrow);
+
+ //
+ // We may have lost digits, if so update limb usage count:
+ //
+ result.normalize();
+ result.sign(a.sign());
+ if (swapped)
+ result.negate();
+ } // constepxr.
+}
+
+#else
+
+template <class CppInt1, class CppInt2, class CppInt3>
+inline BOOST_MP_CXX14_CONSTEXPR void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
+{
+ add_unsigned_constexpr(result, a, b);
+}
+
+template <class CppInt1, class CppInt2, class CppInt3>
+inline BOOST_MP_CXX14_CONSTEXPR void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
+{
+ subtract_unsigned_constexpr(result, a, b);
+}
+
+#endif
+
+} } } // namespaces
+
+
+#endif
+
+
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/bitwise.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/bitwise.hpp
index 168544c9bb..de23f52657 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/bitwise.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/bitwise.hpp
@@ -1,55 +1,62 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
-#ifndef BOOST_MP_CPP_INT_BIT_HPP
-#define BOOST_MP_CPP_INT_BIT_HPP
+#ifndef BOOST_MP_CPP_INT_BITWISE_HPP
+#define BOOST_MP_CPP_INT_BITWISE_HPP
-#ifdef _MSC_VER
+#include <stdexcept>
+#include <type_traits>
+#include <boost/multiprecision/detail/endian.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+
+#ifdef BOOST_MSVC
#pragma warning(push)
-#pragma warning(disable:4319)
+#pragma warning(disable : 4319)
#endif
-namespace boost{ namespace multiprecision{ namespace backends{
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-void is_valid_bitwise_op(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::int_<checked>&)
+namespace boost { namespace multiprecision { namespace backends {
+
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const std::integral_constant<int, checked>&)
{
- if(result.sign() || o.sign())
- BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior."));
+ if (result.sign() || o.sign())
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior."));
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-void is_valid_bitwise_op(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& , const mpl::int_<unchecked>&){}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&, const std::integral_constant<int, unchecked>&) {}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
-void is_valid_bitwise_op(
- const cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result, const mpl::int_<checked>&)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
+ const cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result, const std::integral_constant<int, checked>&)
{
- if(result.sign())
- BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior."));
+ if (result.sign())
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior."));
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
-void is_valid_bitwise_op(
- const cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>&, const mpl::int_<checked>&){}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
+ const cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>&, const std::integral_constant<int, checked>&) {}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-void is_valid_bitwise_op(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&, const mpl::int_<unchecked>&){}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&, const std::integral_constant<int, unchecked>&) {}
template <class CppInt1, class CppInt2, class Op>
-void bitwise_op(
- CppInt1& result,
- const CppInt2& o,
- Op op, const mpl::true_&) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<CppInt1>::value))
+BOOST_MP_CXX14_CONSTEXPR void bitwise_op(
+ CppInt1& result,
+ const CppInt2& o,
+ Op op, const std::integral_constant<bool, true>&) noexcept((is_non_throwing_cpp_int<CppInt1>::value))
{
//
// There are 4 cases:
@@ -68,38 +75,38 @@ void bitwise_op(
//
// 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;
+ std::size_t rs = result.size();
+ std::size_t os = o.size();
+ std::size_t m(0), x(0);
minmax(rs, os, m, x);
result.resize(x, x);
- typename CppInt1::limb_pointer pr = result.limbs();
+ typename CppInt1::limb_pointer pr = result.limbs();
typename CppInt2::const_limb_pointer po = o.limbs();
- for(unsigned i = rs; i < x; ++i)
+ for (std::size_t i = rs; i < x; ++i)
pr[i] = 0;
limb_type next_limb = 0;
- if(!result.sign())
+ if (!result.sign())
{
- if(!o.sign())
+ if (!o.sign())
{
- for(unsigned i = 0; i < os; ++i)
+ for (std::size_t i = 0; i < os; ++i)
pr[i] = op(pr[i], po[i]);
- for(unsigned i = os; i < x; ++i)
+ for (std::size_t 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)
+ for (std::size_t i = 0; i < os; ++i)
{
carry += static_cast<double_limb_type>(~po[i]);
pr[i] = op(pr[i], static_cast<limb_type>(carry));
carry >>= CppInt1::limb_bits;
}
- for(unsigned i = os; i < x; ++i)
+ for (std::size_t i = os; i < x; ++i)
{
carry += static_cast<double_limb_type>(~limb_type(0));
pr[i] = op(pr[i], static_cast<limb_type>(carry));
@@ -112,17 +119,17 @@ void bitwise_op(
}
else
{
- if(!o.sign())
+ if (!o.sign())
{
// "result" is negative:
double_limb_type carry = 1;
- for(unsigned i = 0; i < os; ++i)
+ for (std::size_t i = 0; i < os; ++i)
{
carry += static_cast<double_limb_type>(~pr[i]);
pr[i] = op(static_cast<limb_type>(carry), po[i]);
carry >>= CppInt1::limb_bits;
}
- for(unsigned i = os; i < x; ++i)
+ for (std::size_t i = os; i < x; ++i)
{
carry += static_cast<double_limb_type>(~pr[i]);
pr[i] = op(static_cast<limb_type>(carry), limb_type(0));
@@ -137,7 +144,7 @@ void bitwise_op(
// both are negative:
double_limb_type r_carry = 1;
double_limb_type o_carry = 1;
- for(unsigned i = 0; i < os; ++i)
+ for (std::size_t i = 0; i < os; ++i)
{
r_carry += static_cast<double_limb_type>(~pr[i]);
o_carry += static_cast<double_limb_type>(~po[i]);
@@ -145,7 +152,7 @@ void bitwise_op(
r_carry >>= CppInt1::limb_bits;
o_carry >>= CppInt1::limb_bits;
}
- for(unsigned i = os; i < x; ++i)
+ for (std::size_t i = os; i < x; ++i)
{
r_carry += static_cast<double_limb_type>(~pr[i]);
o_carry += static_cast<double_limb_type>(~limb_type(0));
@@ -162,19 +169,19 @@ void bitwise_op(
//
// See if the result is negative or not:
//
- if(static_cast<signed_limb_type>(next_limb) < 0)
+ if (static_cast<signed_limb_type>(next_limb) < 0)
{
double_limb_type carry = 1;
- for(unsigned i = 0; i < x; ++i)
+ for (std::size_t i = 0; i < x; ++i)
{
carry += static_cast<double_limb_type>(~pr[i]);
pr[i] = static_cast<limb_type>(carry);
carry >>= CppInt1::limb_bits;
}
- if(carry)
+ if (carry)
{
result.resize(x + 1, x);
- if(result.size() > x)
+ if (result.size() > x)
result.limbs()[x] = static_cast<limb_type>(carry);
}
result.sign(true);
@@ -186,122 +193,131 @@ void bitwise_op(
}
template <class CppInt1, class CppInt2, class Op>
-void bitwise_op(
- CppInt1& result,
- const CppInt2& o,
- Op op, const mpl::false_&) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<CppInt1>::value))
+BOOST_MP_CXX14_CONSTEXPR void bitwise_op(
+ CppInt1& result,
+ const CppInt2& o,
+ Op op, const std::integral_constant<bool, false>&) noexcept((is_non_throwing_cpp_int<CppInt1>::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;
+ std::size_t rs = result.size();
+ std::size_t os = o.size();
+ std::size_t m(0), x(0);
minmax(rs, os, m, x);
result.resize(x, x);
- typename CppInt1::limb_pointer pr = result.limbs();
+ typename CppInt1::limb_pointer pr = result.limbs();
typename CppInt2::const_limb_pointer po = o.limbs();
- for(unsigned i = rs; i < x; ++i)
+ for (std::size_t i = rs; i < x; ++i)
pr[i] = 0;
- for(unsigned i = 0; i < os; ++i)
+ for (std::size_t i = 0; i < os; ++i)
pr[i] = op(pr[i], po[i]);
- for(unsigned i = os; i < x; ++i)
+ for (std::size_t 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 <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_bitwise_and(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+struct bit_and
+{
+ BOOST_MP_CXX14_CONSTEXPR limb_type operator()(limb_type a, limb_type b) const noexcept { return a & b; }
+};
+struct bit_or
+{
+ BOOST_MP_CXX14_CONSTEXPR limb_type operator()(limb_type a, limb_type b) const noexcept { return a | b; }
+};
+struct bit_xor
+{
+ BOOST_MP_CXX14_CONSTEXPR limb_type operator()(limb_type a, limb_type b) const noexcept { return a ^ b; }
+};
+
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_bitwise_and(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- bitwise_op(result, o, bit_and(),
- mpl::bool_<std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed>());
+ bitwise_op(result, o, bit_and(),
+ std::integral_constant<bool, std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed > ());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_bitwise_or(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_bitwise_or(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
bitwise_op(result, o, bit_or(),
- mpl::bool_<std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed>());
+ std::integral_constant<bool, std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed > ());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_bitwise_xor(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_bitwise_xor(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
bitwise_op(result, o, bit_xor(),
- mpl::bool_<std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed>());
+ std::integral_constant<bool, std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed > ());
}
//
// Again for operands which are single limbs:
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
- eval_bitwise_and(
- cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
- limb_type l) BOOST_NOEXCEPT
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
+eval_bitwise_and(
+ cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
+ limb_type l) noexcept
{
result.limbs()[0] &= l;
result.resize(1, 1);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
- eval_bitwise_or(
- cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
- limb_type l) BOOST_NOEXCEPT
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
+eval_bitwise_or(
+ cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
+ limb_type l) noexcept
{
result.limbs()[0] |= l;
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
- eval_bitwise_xor(
- cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
- limb_type l) BOOST_NOEXCEPT
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
+eval_bitwise_xor(
+ cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
+ limb_type l) noexcept
{
result.limbs()[0] ^= l;
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_complement(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_complement(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
+ static_assert(((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 <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value >::type
- eval_complement(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_complement(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- unsigned os = o.size();
- result.resize(UINT_MAX, os);
- for(unsigned i = 0; i < os; ++i)
+ std::size_t os = o.size();
+ result.resize(SIZE_MAX, os);
+ for (std::size_t i = 0; i < os; ++i)
result.limbs()[i] = ~o.limbs()[i];
- for(unsigned i = os; i < result.size(); ++i)
+ for (std::size_t i = os; i < result.size(); ++i)
result.limbs()[i] = ~static_cast<limb_type>(0);
result.normalize();
}
@@ -310,12 +326,12 @@ template <class Int>
inline void left_shift_byte(Int& result, double_limb_type s)
{
limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
- limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
- unsigned ors = result.size();
- if((ors == 1) && (!*result.limbs()))
+ limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
+ std::size_t 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)))
+ std::size_t 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);
@@ -323,11 +339,11 @@ inline void left_shift_byte(Int& result, double_limb_type s)
typename Int::limb_pointer pr = result.limbs();
- if(rs != ors)
+ if (rs != ors)
pr[rs - 1] = 0u;
std::size_t bytes = static_cast<std::size_t>(s / CHAR_BIT);
- std::size_t len = (std::min)(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes);
- if(bytes >= rs * sizeof(limb_type))
+ std::size_t len = (std::min)(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes);
+ if (bytes >= rs * sizeof(limb_type))
result = static_cast<limb_type>(0u);
else
{
@@ -338,47 +354,56 @@ inline void left_shift_byte(Int& result, double_limb_type s)
}
template <class Int>
-inline void left_shift_limb(Int& result, double_limb_type s)
+inline BOOST_MP_CXX14_CONSTEXPR void left_shift_limb(Int& result, double_limb_type s)
{
limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
- limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
+ limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
- unsigned ors = result.size();
- if((ors == 1) && (!*result.limbs()))
+ std::size_t 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)))
+ std::size_t 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)
+ if (offset > rs)
{
// The result is shifted past the end of the result:
result = static_cast<limb_type>(0);
return;
}
- unsigned i = rs - result.size();
- for(; i < ors; ++i)
+ std::size_t 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;
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(s))
+ {
+ for (; i < rs; ++i)
+ pr[rs - 1 - i] = 0;
+ }
+ else
+#endif
+ {
+ std::memset(pr, 0, (rs - i) * sizeof(*pr));
+ }
}
template <class Int>
-inline void left_shift_generic(Int& result, double_limb_type s)
+inline BOOST_MP_CXX14_CONSTEXPR void left_shift_generic(Int& result, double_limb_type s)
{
limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
- limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
+ limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
- unsigned ors = result.size();
- if((ors == 1) && (!*result.limbs()))
+ std::size_t 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)))
+ std::size_t 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);
@@ -386,19 +411,19 @@ inline void left_shift_generic(Int& result, double_limb_type s)
typename Int::limb_pointer pr = result.limbs();
- if(offset > rs)
+ if (offset > rs)
{
// The result is shifted past the end of the result:
result = static_cast<limb_type>(0);
return;
}
- unsigned i = rs - result.size();
+ std::size_t i = rs - result.size();
// This code only works when shift is non-zero, otherwise we invoke undefined behaviour!
- BOOST_ASSERT(shift);
- if(!truncated)
+ BOOST_MP_ASSERT(shift);
+ if (!truncated)
{
- if(rs > ors + offset)
+ if (rs > ors + offset)
{
pr[rs - 1 - i] = pr[ors - 1 - i] >> (Int::limb_bits - shift);
--rs;
@@ -406,55 +431,78 @@ inline void left_shift_generic(Int& result, double_limb_type s)
else
{
pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
- if(ors > 1)
+ if (ors > 1)
pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift);
++i;
}
}
- for(; rs - i >= 2 + offset; ++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)
+ 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;
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(s))
+ {
+ for (; i < rs; ++i)
+ pr[rs - 1 - i] = 0;
+ }
+ else
+#endif
+ {
+ std::memset(pr, 0, (rs - i) * sizeof(*pr));
+ }
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_left_shift(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_left_shift(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ double_limb_type s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
- if(!s)
+ if (!s)
return;
-#if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT)
- static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
- static const limb_type byte_shift_mask = CHAR_BIT - 1;
- if((s & limb_shift_mask) == 0)
+#if BOOST_MP_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
+ constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
+ constexpr 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)
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ else if ((s & byte_shift_mask) == 0)
+#else
+ else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
+#endif
{
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)
+#elif BOOST_MP_ENDIAN_LITTLE_BYTE
+ constexpr limb_type byte_shift_mask = CHAR_BIT - 1;
+
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if ((s & byte_shift_mask) == 0)
+#else
+ constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
+ if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
+ left_shift_limb(result, s);
+ else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
+#endif
{
left_shift_byte(result, s);
}
#else
- static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
- if((s & limb_shift_mask) == 0)
+ constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
+
+ if ((s & limb_shift_mask) == 0)
{
left_shift_limb(result, s);
}
@@ -473,77 +521,76 @@ template <class Int>
inline void right_shift_byte(Int& result, double_limb_type s)
{
limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
- limb_type shift;
- BOOST_ASSERT((s % CHAR_BIT) == 0);
- unsigned ors = result.size();
- unsigned rs = ors;
- if(offset >= rs)
+ BOOST_MP_ASSERT((s % CHAR_BIT) == 0);
+ std::size_t ors = result.size();
+ std::size_t rs = ors;
+ if (offset >= rs)
{
result = limb_type(0);
return;
}
rs -= offset;
typename Int::limb_pointer pr = result.limbs();
- unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
- shift = static_cast<limb_type>(s / CHAR_BIT);
+ unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
+ limb_type shift = static_cast<limb_type>(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)
+ if (shift < Int::limb_bits)
{
pr[ors - offset - 1] &= (static_cast<limb_type>(1u) << shift) - 1;
- if(!pr[ors - offset - 1] && (rs > 1))
+ if (!pr[ors - offset - 1] && (rs > 1))
--rs;
}
result.resize(rs, rs);
}
template <class Int>
-inline void right_shift_limb(Int& result, double_limb_type s)
+inline BOOST_MP_CXX14_CONSTEXPR void right_shift_limb(Int& result, double_limb_type s)
{
limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
- BOOST_ASSERT((s % Int::limb_bits) == 0);
- unsigned ors = result.size();
- unsigned rs = ors;
- if(offset >= rs)
+ BOOST_MP_ASSERT((s % Int::limb_bits) == 0);
+ std::size_t ors = result.size();
+ std::size_t 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)
+ std::size_t i = 0;
+ for (; i < rs; ++i)
pr[i] = pr[i + offset];
result.resize(rs, rs);
}
template <class Int>
-inline void right_shift_generic(Int& result, double_limb_type s)
+inline BOOST_MP_CXX14_CONSTEXPR void right_shift_generic(Int& result, double_limb_type s)
{
limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
- limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
- unsigned ors = result.size();
- unsigned rs = ors;
- if(offset >= rs)
+ limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
+ std::size_t ors = result.size();
+ std::size_t 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 ((pr[ors - 1] >> shift) == 0)
{
- if(--rs == 0)
+ if (--rs == 0)
{
result = limb_type(0);
return;
}
}
- unsigned i = 0;
+ std::size_t i = 0;
// This code only works for non-zero shift, otherwise we invoke undefined behaviour!
- BOOST_ASSERT(shift);
- for(; i + offset + 1 < ors; ++i)
+ BOOST_MP_ASSERT(shift);
+ for (; i + offset + 1 < ors; ++i)
{
pr[i] = pr[i + offset] >> shift;
pr[i] |= pr[i + offset + 1] << (Int::limb_bits - shift);
@@ -552,109 +599,134 @@ inline void right_shift_generic(Int& result, double_limb_type s)
result.resize(rs, rs);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
- eval_right_shift(
- cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
- double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
+eval_right_shift(
+ cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
+ double_limb_type s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value))
{
is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>::checked_type());
- if(!s)
+ if (!s)
return;
-#if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT)
- static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
- static const limb_type byte_shift_mask = CHAR_BIT - 1;
- if((s & limb_shift_mask) == 0)
+#if BOOST_MP_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
+ constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+ constexpr 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)
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ else if ((s & byte_shift_mask) == 0)
+#else
+ else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
+#endif
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)
+#elif BOOST_MP_ENDIAN_LITTLE_BYTE
+ constexpr limb_type byte_shift_mask = CHAR_BIT - 1;
+
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if ((s & byte_shift_mask) == 0)
+#else
+ constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+ if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
+ right_shift_limb(result, s);
+ else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
+#endif
right_shift_byte(result, s);
#else
- static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
- if((s & limb_shift_mask) == 0)
+ constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+
+ if ((s & limb_shift_mask) == 0)
right_shift_limb(result, s);
#endif
else
right_shift_generic(result, s);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value>::type
- eval_right_shift(
- cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result,
- double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value>::type
+eval_right_shift(
+ cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result,
+ double_limb_type s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value))
{
is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::checked_type());
- if(!s)
+ if (!s)
return;
bool is_neg = result.sign();
- if(is_neg)
+ if (is_neg)
eval_increment(result);
-#if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT)
- static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
- static const limb_type byte_shift_mask = CHAR_BIT - 1;
- if((s & limb_shift_mask) == 0)
+#if BOOST_MP_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
+ constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+ constexpr 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)
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ else if ((s & byte_shift_mask) == 0)
+#else
+ else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
+#endif
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)
+#elif BOOST_MP_ENDIAN_LITTLE_BYTE
+ constexpr limb_type byte_shift_mask = CHAR_BIT - 1;
+
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if ((s & byte_shift_mask) == 0)
+#else
+ constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+ if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
+ right_shift_limb(result, s);
+ else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
+#endif
right_shift_byte(result, s);
#else
- static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
- if((s & limb_shift_mask) == 0)
+ constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+
+ if ((s & limb_shift_mask) == 0)
right_shift_limb(result, s);
#endif
else
right_shift_generic(result, s);
- if(is_neg)
+ if (is_neg)
eval_decrement(result);
}
//
// Over again for trivial cpp_int's:
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
-BOOST_MP_FORCEINLINE typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type
- eval_left_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value >::type
+eval_left_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
*result.limbs() = detail::checked_left_shift(*result.limbs(), s, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
-BOOST_MP_FORCEINLINE typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type
- eval_right_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value >::type
+eval_right_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
// Nothing to check here... just make sure we don't invoke undefined behavior:
is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
*result.limbs() = (static_cast<unsigned>(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign() ? ((--*result.limbs()) >> s) + 1 : *result.limbs() >> s);
- if(result.sign() && (*result.limbs() == 0))
+ if (result.sign() && (*result.limbs() == 0))
result = static_cast<signed_limb_type>(-1);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
- >::type
- eval_complement(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
-{
- BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)>::type
+eval_complement(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+{
+ static_assert(((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())
+ if (o.sign())
{
*result.limbs() = *o.limbs() - 1;
result.sign(false);
@@ -667,58 +739,47 @@ inline typename enable_if_c<
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- >::type
- eval_complement(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_complement(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() = ~*o.limbs();
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- >::type
- eval_bitwise_and(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_bitwise_and(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() &= *o.limbs();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
- >::type
- eval_bitwise_and(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)>::type
+eval_bitwise_and(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
using default_ops::eval_bit_test;
using default_ops::eval_increment;
- if(result.sign() || o.sign())
+ if (result.sign() || o.sign())
{
- static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
+ constexpr std::size_t m = detail::static_unsigned_max<detail::static_unsigned_max<MinBits1, MinBits2>::value, detail::static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
eval_bitwise_and(t1, t2);
bool s = eval_bit_test(t1, m + 1);
- if(s)
+ if (s)
{
eval_complement(t1, t1);
eval_increment(t1);
@@ -732,43 +793,36 @@ inline typename enable_if_c<
}
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- >::type
- eval_bitwise_or(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_bitwise_or(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() |= *o.limbs();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
- >::type
- eval_bitwise_or(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)>::type
+eval_bitwise_or(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
using default_ops::eval_bit_test;
using default_ops::eval_increment;
- if(result.sign() || o.sign())
+ if (result.sign() || o.sign())
{
- static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
+ constexpr std::size_t m = detail::static_unsigned_max<detail::static_unsigned_max<MinBits1, MinBits2>::value, detail::static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
eval_bitwise_or(t1, t2);
bool s = eval_bit_test(t1, m + 1);
- if(s)
+ if (s)
{
eval_complement(t1, t1);
eval_increment(t1);
@@ -783,43 +837,36 @@ inline typename enable_if_c<
}
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- >::type
- eval_bitwise_xor(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_bitwise_xor(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() ^= *o.limbs();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
- >::type
- eval_bitwise_xor(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)>::type
+eval_bitwise_xor(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
using default_ops::eval_bit_test;
using default_ops::eval_increment;
- if(result.sign() || o.sign())
+ if (result.sign() || o.sign())
{
- static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
+ constexpr std::size_t m = detail::static_unsigned_max<detail::static_unsigned_max<MinBits1, MinBits2>::value, detail::static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
eval_bitwise_xor(t1, t2);
bool s = eval_bit_test(t1, m + 1);
- if(s)
+ if (s)
{
eval_complement(t1, t1);
eval_increment(t1);
@@ -833,9 +880,9 @@ inline typename enable_if_c<
}
}
-}}} // namespaces
+}}} // namespace boost::multiprecision::backends
-#ifdef _MSC_VER
+#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/checked.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/checked.hpp
index cafe50ea49..5d621403d0 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/checked.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/checked.hpp
@@ -1,21 +1,51 @@
// Copyright 2012 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_CHECKED_HPP
#define BOOST_MP_CPP_INT_CHECKED_HPP
-namespace boost{ namespace multiprecision{ namespace backends{ namespace detail{
+#include <climits>
+#include <limits>
+#include <type_traits>
+#include <stdexcept>
+#include <string>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+
+namespace boost { namespace multiprecision { namespace backends { namespace detail {
//
// Simple routines for performing checked arithmetic with a builtin arithmetic type.
// Note that this is not a complete header, it must be included as part of boost/multiprecision/cpp_int.hpp.
//
+template <typename T>
+inline constexpr T type_max() noexcept
+{
+ return
+ #ifdef BOOST_HAS_INT128
+ std::is_same<T, boost::multiprecision::int128_type>::value ? INT128_MAX :
+ std::is_same<T, boost::multiprecision::uint128_type>::value ? UINT128_MAX :
+ #endif
+ (std::numeric_limits<T>::max)();
+}
+
+template <typename T>
+inline constexpr T type_min() noexcept
+{
+ return
+ #ifdef BOOST_HAS_INT128
+ std::is_same<T, boost::multiprecision::int128_type>::value ? INT128_MIN :
+ std::is_same<T, boost::multiprecision::uint128_type>::value ? T(0) :
+ #endif
+ (std::numeric_limits<T>::min)();
+}
+
inline void raise_overflow(std::string op)
{
- BOOST_THROW_EXCEPTION(std::overflow_error("overflow in " + op));
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("overflow in " + op));
}
inline void raise_add_overflow()
{
@@ -23,7 +53,7 @@ inline void raise_add_overflow()
}
inline void raise_subtract_overflow()
{
- BOOST_THROW_EXCEPTION(std::range_error("Subtraction resulted in a negative value, but the type is unsigned"));
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Subtraction resulted in a negative value, but the type is unsigned"));
}
inline void raise_mul_overflow()
{
@@ -35,115 +65,114 @@ inline void raise_div_overflow()
}
template <class A>
-inline A checked_add_imp(A a, A b, const mpl::true_&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_add_imp(A a, A b, const std::integral_constant<bool, true>&)
{
- if(a > 0)
+ if (a > 0)
{
- if((b > 0) && ((integer_traits<A>::const_max - b) < a))
+ if ((b > 0) && ((type_max<A>() - b) < a))
raise_add_overflow();
}
else
{
- if((b < 0) && ((integer_traits<A>::const_min - b) > a))
+ if ((b < 0) && ((type_min<A>() - b) > a))
raise_add_overflow();
}
return a + b;
}
template <class A>
-inline A checked_add_imp(A a, A b, const mpl::false_&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_add_imp(A a, A b, const std::integral_constant<bool, false>&)
{
- if((integer_traits<A>::const_max - b) < a)
+ if ((type_max<A>() - b) < a)
raise_add_overflow();
return a + b;
}
template <class A>
-inline A checked_add(A a, A b, const mpl::int_<checked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_add(A a, A b, const std::integral_constant<int, checked>&)
{
- return checked_add_imp(a, b, boost::is_signed<A>());
+ return checked_add_imp(a, b, std::integral_constant<bool, boost::multiprecision::detail::is_signed<A>::value && boost::multiprecision::detail::is_integral<A>::value > ());
}
template <class A>
-inline A checked_add(A a, A b, const mpl::int_<unchecked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_add(A a, A b, const std::integral_constant<int, unchecked>&)
{
return a + b;
}
template <class A>
-inline A checked_subtract_imp(A a, A b, const mpl::true_&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_subtract_imp(A a, A b, const std::integral_constant<bool, true>&)
{
- if(a > 0)
+ if (a > 0)
{
- if((b < 0) && ((integer_traits<A>::const_max + b) < a))
+ if ((b < 0) && ((type_max<A>() + b) < a))
raise_subtract_overflow();
}
else
{
- if((b > 0) && ((integer_traits<A>::const_min + b) > a))
+ if ((b > 0) && ((type_min<A>() + b) > a))
raise_subtract_overflow();
}
return a - b;
}
template <class A>
-inline A checked_subtract_imp(A a, A b, const mpl::false_&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_subtract_imp(A a, A b, const std::integral_constant<bool, false>&)
{
- if(a < b)
+ if (a < b)
raise_subtract_overflow();
return a - b;
}
template <class A>
-inline A checked_subtract(A a, A b, const mpl::int_<checked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_subtract(A a, A b, const std::integral_constant<int, checked>&)
{
- return checked_subtract_imp(a, b, boost::is_signed<A>());
+ return checked_subtract_imp(a, b, std::integral_constant<bool, boost::multiprecision::detail::is_signed<A>::value && boost::multiprecision::detail::is_integral<A>::value>());
}
template <class A>
-inline A checked_subtract(A a, A b, const mpl::int_<unchecked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_subtract(A a, A b, const std::integral_constant<int, unchecked>&)
{
return a - b;
}
template <class A>
-inline A checked_multiply(A a, A b, const mpl::int_<checked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_multiply(A a, A b, const std::integral_constant<int, checked>&)
{
BOOST_MP_USING_ABS
- if(a && (integer_traits<A>::const_max / abs(a) < abs(b)))
+ if (a && (type_max<A>() / abs(a) < abs(b)))
raise_mul_overflow();
return a * b;
}
template <class A>
-inline A checked_multiply(A a, A b, const mpl::int_<unchecked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_multiply(A a, A b, const std::integral_constant<int, unchecked>&)
{
return a * b;
}
template <class A>
-inline A checked_divide(A a, A b, const mpl::int_<checked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_divide(A a, A b, const std::integral_constant<int, checked>&)
{
- if(b == 0)
+ if (b == 0)
raise_div_overflow();
return a / b;
}
template <class A>
-inline A checked_divide(A a, A b, const mpl::int_<unchecked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_divide(A a, A b, const std::integral_constant<int, unchecked>&)
{
return a / b;
}
template <class A>
-inline A checked_left_shift(A a, boost::ulong_long_type shift, const mpl::int_<checked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_left_shift(A a, unsigned long long shift, const std::integral_constant<int, checked>&)
{
- if(a && shift)
+ if (a && shift)
{
- if((shift > sizeof(A) * CHAR_BIT) || (a >> (sizeof(A) * CHAR_BIT - shift)))
- BOOST_THROW_EXCEPTION(std::overflow_error("Shift out of range"));
+ if ((shift > sizeof(A) * CHAR_BIT) || (a >> (sizeof(A) * CHAR_BIT - shift)))
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Shift out of range"));
}
return a << shift;
}
template <class A>
-inline A checked_left_shift(A a, boost::ulong_long_type shift, const mpl::int_<unchecked>&)
+inline BOOST_MP_CXX14_CONSTEXPR A checked_left_shift(A a, unsigned long long shift, const std::integral_constant<int, unchecked>&)
{
return (shift >= sizeof(A) * CHAR_BIT) ? 0 : a << shift;
}
-}}}} // namespaces
+}}}} // namespace boost::multiprecision::backends::detail
#endif
-
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/comparison.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/comparison.hpp
index 8d8e7aacb8..9808889ff1 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/comparison.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/comparison.hpp
@@ -1,257 +1,232 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
#ifndef BOOST_MP_CPP_INT_COMPARISON_HPP
#define BOOST_MP_CPP_INT_COMPARISON_HPP
-#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/multiprecision/detail/constexpr.hpp>
-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 <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
- bool
- >::type
- eval_eq(const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& a, const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& b) BOOST_NOEXCEPT
-{
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(_LIBCPP_VERSION)
- return (a.sign() == b.sign())
- && (a.size() == b.size())
- && std::equal(a.limbs(), a.limbs() + a.size(),
- stdext::checked_array_iterator<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::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 <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& a, const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& b) noexcept
+{
+ return (a.sign() == b.sign()) && (a.size() == b.size()) && std_constexpr::equal(a.limbs(), a.limbs() + a.size(), b.limbs());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value,
- bool
- >::type
- eval_eq(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b) BOOST_NOEXCEPT
-{
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(_LIBCPP_VERSION)
- return (a.sign() == b.sign())
- && (a.size() == b.size())
- && std::equal(a.limbs(), a.limbs() + a.size(), stdext::checked_array_iterator<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b) noexcept
+{
+ return (a.sign() == b.sign()) && (a.size() == b.size()) && std_constexpr::equal(a.limbs(), a.limbs() + a.size(), b.limbs());
+}
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, limb_type b) noexcept
+{
+ return (a.sign() == false) && (a.size() == 1) && (*a.limbs() == b);
+}
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, signed_limb_type b) noexcept
+{
+ return (a.sign() == (b < 0)) && (a.size() == 1) && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b));
+}
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, limb_type b) noexcept
+{
+ return (a.size() == 1) && (*a.limbs() == b);
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
-{
- return (a.sign() == false)
- && (a.size() == 1)
- && (*a.limbs() == b);
-}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
-{
- return (a.sign() == (b < 0))
- && (a.size() == 1)
- && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b));
-}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
-{
- return (a.size() == 1)
- && (*a.limbs() == b);
-}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, signed_limb_type b) noexcept
{
return (b < 0) ? eval_eq(a, cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>(b)) : eval_eq(a, static_cast<limb_type>(b)); // Use bit pattern of b for comparison
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, limb_type b) noexcept
{
- if(a.sign())
+ if (a.sign())
return true;
- if(a.size() > 1)
+ if (a.size() > 1)
return false;
return *a.limbs() < b;
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-inline typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, signed_limb_type b) noexcept
{
- if((b == 0) || (a.sign() != (b < 0)))
+ if ((b == 0) || (a.sign() != (b < 0)))
return a.sign();
- if(a.sign())
+ if (a.sign())
{
- if(a.size() > 1)
+ if (a.size() > 1)
return true;
return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b);
}
else
{
- if(a.size() > 1)
+ if (a.size() > 1)
return false;
return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b);
}
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, limb_type b) noexcept
{
- if(a.size() > 1)
+ if (a.size() > 1)
return false;
return *a.limbs() < b;
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, signed_limb_type b) noexcept
{
return (b < 0) ? a.compare(b) < 0 : eval_lt(a, static_cast<limb_type>(b)); // Use bit pattern of b for comparison
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, limb_type b) noexcept
{
- if(a.sign())
+ if (a.sign())
return false;
- if(a.size() > 1)
+ if (a.size() > 1)
return true;
return *a.limbs() > b;
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-inline typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, signed_limb_type b) noexcept
{
- if(b == 0)
+ if (b == 0)
return !a.sign() && ((a.size() > 1) || *a.limbs());
- if(a.sign() != (b < 0))
+ if (a.sign() != (b < 0))
return !a.sign();
- if(a.sign())
+ if (a.sign())
{
- if(a.size() > 1)
+ if (a.size() > 1)
return false;
return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b);
}
else
{
- if(a.size() > 1)
+ if (a.size() > 1)
return true;
return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b);
}
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, limb_type b) noexcept
{
- if(a.size() > 1)
+ if (a.size() > 1)
return true;
return *a.limbs() > b;
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, signed_limb_type b) noexcept
{
return (b < 0) ? a.compare(b) > 0 : eval_gt(a, static_cast<limb_type>(b)); // Use bit pattern of b for comparison.
}
//
// And again for trivial cpp_ints:
//
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
- bool
- >::value eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
+ bool>::value
+eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& b) noexcept
{
return (a.sign() == b.sign()) && (*a.limbs() == *b.limbs());
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
- bool
- >::value eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
+ bool>::value
+eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) noexcept
{
return *a.limbs() == *b.limbs();
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
- bool
- >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class U>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, U b) noexcept
{
return !a.sign() && (*a.limbs() == b);
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
- bool
- >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class S>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, S b) noexcept
{
return (a.sign() == (b < 0)) && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b));
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
- bool
- >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class U>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, U b) noexcept
{
return *a.limbs() == b;
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
- bool
- >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class S>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
+ bool>::type
+eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, S b) noexcept
{
- typedef typename make_unsigned<S>::type ui_type;
- if(b < 0)
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<S>::type;
+ if (b < 0)
{
cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> t(b);
return *a.limbs() == *t.limbs();
@@ -262,60 +237,60 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
}
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) noexcept
{
- if(a.sign() != b.sign())
+ if (a.sign() != b.sign())
return a.sign();
return a.sign() ? *a.limbs() > *b.limbs() : *a.limbs() < *b.limbs();
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) noexcept
{
return *a.limbs() < *b.limbs();
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class U>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, U b) noexcept
{
- if(a.sign())
+ if (a.sign())
return true;
return *a.limbs() < b;
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class S>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, S b) noexcept
{
- if(a.sign() != (b < 0))
+ 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 <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class U>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, U b) noexcept
{
return *a.limbs() < b;
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
- bool
- >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class S>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
+ bool>::type
+eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, S b) noexcept
{
- typedef typename make_unsigned<S>::type ui_type;
- if(b < 0)
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<S>::type;
+ if (b < 0)
{
cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> t(b);
return *a.limbs() < *t.limbs();
@@ -326,60 +301,60 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
}
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& b) noexcept
{
- if(a.sign() != b.sign())
+ if (a.sign() != b.sign())
return !a.sign();
return a.sign() ? *a.limbs() < *b.limbs() : *a.limbs() > *b.limbs();
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) noexcept
{
return *a.limbs() > *b.limbs();
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class U>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, U b) noexcept
{
- if(a.sign())
+ if (a.sign())
return false;
return *a.limbs() > b;
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class S>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, S b) noexcept
{
- if(a.sign() != (b < 0))
+ 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 <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class U>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, U b) noexcept
{
return *a.limbs() > b;
}
-template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
- bool
- >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class S>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
+ bool>::type
+eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, S b) noexcept
{
- typedef typename make_unsigned<S>::type ui_type;
- if(b < 0)
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<S>::type;
+ if (b < 0)
{
cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> t(b);
return *a.limbs() > *t.limbs();
@@ -394,6 +369,6 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
#pragma warning(pop)
#endif
-}}} // namespaces
+}}} // namespace boost::multiprecision::backends
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/cpp_int_config.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/cpp_int_config.hpp
index eb88f3da80..1b7df4f1a9 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/cpp_int_config.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/cpp_int_config.hpp
@@ -1,129 +1,150 @@
///////////////////////////////////////////////////////////////
-// Copyright 2012 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_
+// Copyright 2012 - 2021 John Maddock.
+// Copyright 2021 Matt Borland.
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
-#ifndef BOOST_MP_CPP_INT_CORE_HPP
-#define BOOST_MP_CPP_INT_CORE_HPP
+#ifndef BOOST_MP_CPP_INT_CONFIG_HPP
+#define BOOST_MP_CPP_INT_CONFIG_HPP
-#include <boost/integer.hpp>
-#include <boost/integer_traits.hpp>
-#include <boost/mpl/if.hpp>
-#include <boost/mpl/int.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/assert.hpp>
+#include <cstdint>
+#include <type_traits>
+#include <limits>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/number_base.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
-namespace boost{ namespace multiprecision{
+namespace boost {
+namespace multiprecision {
-namespace detail{
+namespace detail {
//
// These traits calculate the largest type in the list
-// [unsigned] boost::long_long_type, long, int, which has the specified number
-// of bits. Note that intN_t and boost::int_t<N> find the first
+// [unsigned] long long, long, int, which has the specified number
+// of bits. Note that int_t and uint_t find the first
// member of the above list, not the last. We want the last in the
// list to ensure that mixed arithmetic operations are as efficient
// as possible.
//
-template <unsigned N>
+
+template <std::size_t Bits>
+struct int_t
+{
+ using exact = typename std::conditional<Bits <= sizeof(signed char) * CHAR_BIT, signed char,
+ typename std::conditional<Bits <= sizeof(short) * CHAR_BIT, short,
+ typename std::conditional<Bits <= sizeof(int) * CHAR_BIT, int,
+ typename std::conditional<Bits <= sizeof(long) * CHAR_BIT, long,
+ typename std::conditional<Bits <= sizeof(long long) * CHAR_BIT, long long, void
+ >::type>::type>::type>::type>::type;
+
+ using least = typename std::conditional<Bits-1 <= std::numeric_limits<signed char>::digits, signed char,
+ typename std::conditional<Bits-1 <= std::numeric_limits<short>::digits, short,
+ typename std::conditional<Bits-1 <= std::numeric_limits<int>::digits, int,
+ typename std::conditional<Bits-1 <= std::numeric_limits<long>::digits, long,
+ typename std::conditional<Bits-1 <= std::numeric_limits<long long>::digits, long long, void
+ >::type>::type>::type>::type>::type;
+
+ static_assert(!std::is_same<void, exact>::value && !std::is_same<void, least>::value, "Number of bits does not match any standard data type. \
+ Please file an issue at https://github.com/boostorg/multiprecision/ referencing this error from cpp_int_config.hpp");
+};
+
+template <std::size_t Bits>
+struct uint_t
+{
+ using exact = typename std::conditional<Bits <= sizeof(unsigned char) * CHAR_BIT, unsigned char,
+ typename std::conditional<Bits <= sizeof(unsigned short) * CHAR_BIT, unsigned short,
+ typename std::conditional<Bits <= sizeof(unsigned int) * CHAR_BIT, unsigned int,
+ typename std::conditional<Bits <= sizeof(unsigned long) * CHAR_BIT, unsigned long,
+ typename std::conditional<Bits <= sizeof(unsigned long long) * CHAR_BIT, unsigned long long, void
+ >::type>::type>::type>::type>::type;
+
+ using least = typename std::conditional<Bits <= std::numeric_limits<unsigned char>::digits, unsigned char,
+ typename std::conditional<Bits <= std::numeric_limits<unsigned short>::digits, unsigned short,
+ typename std::conditional<Bits <= std::numeric_limits<unsigned int>::digits, unsigned int,
+ typename std::conditional<Bits <= std::numeric_limits<unsigned long>::digits, unsigned long,
+ typename std::conditional<Bits <= std::numeric_limits<unsigned long long>::digits, unsigned long long, void
+ >::type>::type>::type>::type>::type;
+
+ static_assert(!std::is_same<void, exact>::value && !std::is_same<void, least>::value, "Number of bits does not match any standard data type. \
+ Please file an issue at https://github.com/boostorg/multiprecision/ referencing this error from cpp_int_config.hpp");
+};
+
+template <std::size_t N>
struct largest_signed_type
{
- typedef typename mpl::if_c<
- 1 + std::numeric_limits<boost::long_long_type>::digits == N,
- boost::long_long_type,
- typename mpl::if_c<
- 1 + std::numeric_limits<long>::digits == N,
- long,
- typename mpl::if_c<
- 1 + std::numeric_limits<int>::digits == N,
- int,
- typename boost::int_t<N>::exact
- >::type
- >::type
- >::type type;
+ using type = typename std::conditional<
+ 1 + std::numeric_limits<long long>::digits == N,
+ long long,
+ typename std::conditional<
+ 1 + std::numeric_limits<long>::digits == N,
+ long,
+ typename std::conditional<
+ 1 + std::numeric_limits<int>::digits == N,
+ int,
+ typename int_t<N>::exact>::type>::type>::type;
};
-template <unsigned N>
+template <std::size_t N>
struct largest_unsigned_type
{
- typedef typename mpl::if_c<
- std::numeric_limits<boost::ulong_long_type>::digits == N,
- boost::ulong_long_type,
- typename mpl::if_c<
- std::numeric_limits<unsigned long>::digits == N,
- unsigned long,
- typename mpl::if_c<
- std::numeric_limits<unsigned int>::digits == N,
- unsigned int,
- typename boost::uint_t<N>::exact
- >::type
- >::type
- >::type type;
+ using type = typename std::conditional<
+ std::numeric_limits<unsigned long long>::digits == N,
+ unsigned long long,
+ typename std::conditional<
+ std::numeric_limits<unsigned long>::digits == N,
+ unsigned long,
+ typename std::conditional<
+ std::numeric_limits<unsigned int>::digits == N,
+ unsigned int,
+ typename uint_t<N>::exact>::type>::type>::type;
};
} // namespace detail
#if defined(BOOST_HAS_INT128)
-typedef detail::largest_unsigned_type<64>::type limb_type;
-typedef detail::largest_signed_type<64>::type signed_limb_type;
-typedef boost::uint128_type double_limb_type;
-typedef boost::int128_type signed_double_limb_type;
-static const limb_type max_block_10 = 1000000000000000000uLL;
-static const limb_type digits_per_block_10 = 18;
+using limb_type = detail::largest_unsigned_type<64>::type;
+using signed_limb_type = detail::largest_signed_type<64>::type;
+using double_limb_type = boost::multiprecision::uint128_type;
+using signed_double_limb_type = boost::multiprecision::int128_type;
+constexpr limb_type max_block_10 = 1000000000000000000uLL;
+constexpr limb_type digits_per_block_10 = 18;
-inline limb_type block_multiplier(unsigned count)
+inline BOOST_MP_CXX14_CONSTEXPR limb_type block_multiplier(std::size_t count)
{
- static const limb_type values[digits_per_block_10]
- = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000 };
- BOOST_ASSERT(count < digits_per_block_10);
+ constexpr limb_type values[digits_per_block_10] = {10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000};
+ BOOST_MP_ASSERT(count < digits_per_block_10);
return values[count];
}
// Can't do formatted IO on an __int128
#define BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO
-// Need to specialise integer_traits for __int128 as it's not a normal native type:
-} // namespace multiprecision
-
-template<>
-class integer_traits<multiprecision::double_limb_type>
- : public std::numeric_limits<multiprecision::double_limb_type>,
- public detail::integer_traits_base<multiprecision::double_limb_type, 0, ~static_cast<multiprecision::double_limb_type>(0)>
-{ };
-template<>
-class integer_traits<multiprecision::signed_double_limb_type>
- : public std::numeric_limits<multiprecision::signed_double_limb_type>,
- public detail::integer_traits_base<multiprecision::signed_double_limb_type, static_cast<multiprecision::signed_double_limb_type>((static_cast<multiprecision::double_limb_type>(1) << 127)), static_cast<multiprecision::signed_double_limb_type>(((~static_cast<multiprecision::double_limb_type>(0)) >> 1))>
-{ };
-
-namespace multiprecision{
-
#else
-typedef detail::largest_unsigned_type<32>::type limb_type;
-typedef detail::largest_signed_type<32>::type signed_limb_type;
-typedef detail::largest_unsigned_type<64>::type double_limb_type;
-typedef detail::largest_signed_type<64>::type signed_double_limb_type;
-static const limb_type max_block_10 = 1000000000;
-static const limb_type digits_per_block_10 = 9;
+using limb_type = detail::largest_unsigned_type<32>::type;
+using signed_limb_type = detail::largest_signed_type<32>::type ;
+using double_limb_type = detail::largest_unsigned_type<64>::type;
+using signed_double_limb_type = detail::largest_signed_type<64>::type ;
+constexpr limb_type max_block_10 = 1000000000;
+constexpr limb_type digits_per_block_10 = 9;
-inline limb_type block_multiplier(unsigned count)
+inline limb_type block_multiplier(std::size_t count)
{
- static const limb_type values[digits_per_block_10]
- = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
- BOOST_ASSERT(count < digits_per_block_10);
+ constexpr limb_type values[digits_per_block_10] = {10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
+ BOOST_MP_ASSERT(count < digits_per_block_10);
return values[count];
}
#endif
-static const unsigned bits_per_limb = sizeof(limb_type) * CHAR_BIT;
+constexpr std::size_t bits_per_limb = sizeof(limb_type) * CHAR_BIT;
template <class T>
-inline void minmax(const T& a, const T& b, T& aa, T& bb)
+inline BOOST_MP_CXX14_CONSTEXPR void minmax(const T& a, const T& b, T& aa, T& bb)
{
- if(a < b)
+ if (a < b)
{
aa = a;
bb = b;
@@ -137,27 +158,19 @@ inline void minmax(const T& a, const T& b, T& aa, T& bb)
enum cpp_integer_type
{
- signed_magnitude = 1,
+ signed_magnitude = 1,
unsigned_magnitude = 0,
- signed_packed = 3,
- unsigned_packed = 2
+ signed_packed = 3,
+ unsigned_packed = 2
};
enum cpp_int_check_type
{
- checked = 1,
+ checked = 1,
unchecked = 0
};
-}}
-
-//
-// Figure out whether to support user-defined-literals or not:
-//
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_USER_DEFINED_LITERALS) \
- && !defined(BOOST_NO_CXX11_CONSTEXPR)
-# define BOOST_MP_USER_DEFINED_LITERALS
-#endif
-
-#endif // BOOST_MP_CPP_INT_CORE_HPP
+} // namespace multiprecision
+} // namespace boost
+#endif // BOOST_MP_CPP_INT_CONFIG_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/divide.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/divide.hpp
index 81583ec384..b1253fc368 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/divide.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/divide.hpp
@@ -1,29 +1,32 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
-#ifndef BOOST_MP_CPP_INT_DIV_HPP
-#define BOOST_MP_CPP_INT_DIV_HPP
+#ifndef BOOST_MP_CPP_INT_DIVIDE_HPP
+#define BOOST_MP_CPP_INT_DIVIDE_HPP
-namespace boost{ namespace multiprecision{ namespace backends{
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+
+namespace boost { namespace multiprecision { namespace backends {
template <class CppInt1, class CppInt2, class CppInt3>
-void divide_unsigned_helper(
- CppInt1* result,
- const CppInt2& x,
- const CppInt3& y,
- CppInt1& r)
+BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
+ CppInt1* result,
+ const CppInt2& x,
+ const CppInt3& y,
+ CppInt1& r)
{
- if(((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
+ if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
{
CppInt2 t(x);
divide_unsigned_helper(result, t, y, r);
return;
}
- if(((void*)result == (void*)&y) || ((void*)&r == (void*)&y))
+ if (((void*)result == (void*)&y) || ((void*)&r == (void*)&y))
{
CppInt3 t(y);
divide_unsigned_helper(result, x, t, r);
@@ -48,10 +51,9 @@ void divide_unsigned_helper(
and avoids the normalisation step which would require extra storage.
*/
-
using default_ops::eval_subtract;
- if(result == &r)
+ if (result == &r)
{
CppInt1 rem;
divide_unsigned_helper(result, x, y, rem);
@@ -62,9 +64,9 @@ void divide_unsigned_helper(
//
// Find the most significant words of numerator and denominator.
//
- limb_type y_order = y.size() - 1;
+ std::size_t y_order = y.size() - 1;
- if(y_order == 0)
+ if (y_order == 0)
{
//
// Only a single non-zero limb in the denominator, in this case
@@ -78,56 +80,54 @@ void divide_unsigned_helper(
typename CppInt2::const_limb_pointer px = x.limbs();
typename CppInt3::const_limb_pointer py = y.limbs();
- limb_type r_order = x.size() - 1;
- if((r_order == 0) && (*px == 0))
+ std::size_t r_order = x.size() - 1;
+ if ((r_order == 0) && (*px == 0))
{
// x is zero, so is the result:
r = x;
- if(result)
+ if (result)
*result = x;
return;
}
r = x;
r.sign(false);
- if(result)
+ if (result)
*result = static_cast<limb_type>(0u);
//
// Check if the remainder is already less than the divisor, if so
// we already have the result. Note we try and avoid a full compare
// if we can:
//
- if(r_order <= y_order)
+ if (r_order <= y_order)
{
- if((r_order < y_order) || (r.compare_unsigned(y) < 0))
+ if ((r_order < y_order) || (r.compare_unsigned(y) < 0))
{
return;
}
}
CppInt1 t;
- bool r_neg = false;
+ bool r_neg = false;
//
// See if we can short-circuit long division, and use basic arithmetic instead:
//
- if(r_order == 0)
+ if (r_order == 0)
{
- if(result)
+ if (result)
{
*result = px[0] / py[0];
}
r = px[0] % py[0];
return;
}
- else if(r_order == 1)
+ else if (r_order == 1)
{
- double_limb_type a, b;
- a = (static_cast<double_limb_type>(px[1]) << CppInt1::limb_bits) | px[0];
- b = y_order ?
- (static_cast<double_limb_type>(py[1]) << CppInt1::limb_bits) | py[0]
- : py[0];
- if(result)
+ double_limb_type a = (static_cast<double_limb_type>(px[1]) << CppInt1::limb_bits) | px[0];
+ double_limb_type b = y_order ? (static_cast<double_limb_type>(py[1]) << CppInt1::limb_bits) | py[0]
+ : py[0];
+ if (result)
{
*result = a / b;
}
@@ -137,16 +137,15 @@ void divide_unsigned_helper(
//
// prepare result:
//
- if(result)
+ if (result)
result->resize(1 + r_order - y_order, 1 + r_order - y_order);
typename CppInt1::const_limb_pointer prem = r.limbs();
// This is initialised just to keep the compiler from emitting useless warnings later on:
- typename CppInt1::limb_pointer pr
- = typename CppInt1::limb_pointer();
- if(result)
+ typename CppInt1::limb_pointer pr = typename CppInt1::limb_pointer();
+ if (result)
{
pr = result->limbs();
- for(unsigned i = 1; i < 1 + r_order - y_order; ++i)
+ for (std::size_t i = 1; i < 1 + r_order - y_order; ++i)
pr[i] = 0;
}
bool first_pass = true;
@@ -156,60 +155,57 @@ void divide_unsigned_helper(
//
// Calculate our best guess for how many times y divides into r:
//
- limb_type guess;
- if((prem[r_order] <= py[y_order]) && (r_order > 0))
+ limb_type guess = 1;
+ if ((prem[r_order] <= py[y_order]) && (r_order > 0))
{
- double_limb_type a, b, v;
- a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
- b = py[y_order];
- v = a / b;
- if(v > CppInt1::max_limb_value)
- guess = 1;
- else
+ double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
+ double_limb_type b = py[y_order];
+ double_limb_type v = a / b;
+ if (v <= CppInt1::max_limb_value)
{
guess = static_cast<limb_type>(v);
--r_order;
}
}
- else if(r_order == 0)
+ else if (r_order == 0)
{
guess = prem[0] / py[y_order];
}
else
{
- double_limb_type a, b, v;
- a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
- b = (y_order > 0) ? (static_cast<double_limb_type>(py[y_order]) << CppInt1::limb_bits) | py[y_order - 1] : (static_cast<double_limb_type>(py[y_order]) << CppInt1::limb_bits);
- v = a / b;
- guess = static_cast<limb_type>(v);
+ double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
+ double_limb_type b = (y_order > 0) ? (static_cast<double_limb_type>(py[y_order]) << CppInt1::limb_bits) | py[y_order - 1] : (static_cast<double_limb_type>(py[y_order]) << CppInt1::limb_bits);
+ BOOST_MP_ASSERT(b);
+ double_limb_type v = a / b;
+ guess = static_cast<limb_type>(v);
}
- BOOST_ASSERT(guess); // If the guess ever gets to zero we go on forever....
+ BOOST_MP_ASSERT(guess); // If the guess ever gets to zero we go on forever....
//
// Update result:
//
- limb_type shift = r_order - y_order;
- if(result)
+ std::size_t shift = r_order - y_order;
+ if (result)
{
- if(r_neg)
+ if (r_neg)
{
- if(pr[shift] > guess)
+ if (pr[shift] > guess)
pr[shift] -= guess;
else
{
t.resize(shift + 1, shift + 1);
t.limbs()[shift] = guess;
- for(unsigned i = 0; i < shift; ++i)
+ for (std::size_t i = 0; i < shift; ++i)
t.limbs()[i] = 0;
eval_subtract(*result, t);
}
}
- else if(CppInt1::max_limb_value - pr[shift] > guess)
+ else if (CppInt1::max_limb_value - pr[shift] > guess)
pr[shift] += guess;
else
{
t.resize(shift + 1, shift + 1);
t.limbs()[shift] = guess;
- for(unsigned i = 0; i < shift; ++i)
+ for (std::size_t i = 0; i < shift; ++i)
t.limbs()[i] = 0;
eval_add(*result, t);
}
@@ -220,21 +216,21 @@ void divide_unsigned_helper(
//
double_limb_type carry = 0;
t.resize(y.size() + shift + 1, y.size() + shift);
- bool truncated_t = (t.size() != y.size() + shift + 1);
- typename CppInt1::limb_pointer pt = t.limbs();
- for(unsigned i = 0; i < shift; ++i)
+ bool truncated_t = (t.size() != y.size() + shift + 1);
+ typename CppInt1::limb_pointer pt = t.limbs();
+ for (std::size_t i = 0; i < shift; ++i)
pt[i] = 0;
- for(unsigned i = 0; i < y.size(); ++i)
+ for (std::size_t i = 0; i < y.size(); ++i)
{
carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
#ifdef __MSVC_RUNTIME_CHECKS
pt[i + shift] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
#else
- pt[i + shift] = static_cast<limb_type>(carry);
+ pt[i + shift] = static_cast<limb_type>(carry);
#endif
carry >>= CppInt1::limb_bits;
}
- if(carry && !truncated_t)
+ if (carry && !truncated_t)
{
#ifdef __MSVC_RUNTIME_CHECKS
pt[t.size() - 1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
@@ -242,7 +238,7 @@ void divide_unsigned_helper(
pt[t.size() - 1] = static_cast<limb_type>(carry);
#endif
}
- else if(!truncated_t)
+ else if (!truncated_t)
{
t.resize(t.size() - 1, t.size() - 1);
}
@@ -250,21 +246,21 @@ void divide_unsigned_helper(
// Update r in a way that won't actually produce a negative result
// in case the argument types are unsigned:
//
- if(truncated_t && carry)
+ if (truncated_t && carry)
{
// We need to calculate 2^n + t - r
// where n is the number of bits in this type.
// Simplest way is to get 2^n - r by complementing
// r, then add t to it. Note that we can't call eval_complement
// in case this is a signed checked type:
- for(unsigned i = 0; i <= r_order; ++i)
+ for (std::size_t i = 0; i <= r_order; ++i)
r.limbs()[i] = ~prem[i];
r.normalize();
eval_increment(r);
eval_add(r, t);
r_neg = !r_neg;
}
- else if(r.compare(t) > 0)
+ else if (r.compare(t) > 0)
{
eval_subtract(r, t);
}
@@ -272,39 +268,39 @@ void divide_unsigned_helper(
{
r.swap(t);
eval_subtract(r, t);
- prem = r.limbs();
+ prem = r.limbs();
r_neg = !r_neg;
}
//
// First time through we need to strip any leading zero, otherwise
// the termination condition goes belly-up:
//
- if(result && first_pass)
+ if (result && first_pass)
{
first_pass = false;
- while(pr[result->size() - 1] == 0)
+ while (pr[result->size() - 1] == 0)
result->resize(result->size() - 1, result->size() - 1);
}
//
// Update r_order:
//
r_order = r.size() - 1;
- if(r_order < y_order)
+ if (r_order < y_order)
break;
}
// Termination condition is really just a check that r > y, but with a common
// short-circuit case handled first:
- while((r_order > y_order) || (r.compare_unsigned(y) >= 0));
+ while ((r_order > y_order) || (r.compare_unsigned(y) >= 0));
//
// We now just have to normalise the result:
//
- if(r_neg && eval_get_sign(r))
+ if (r_neg && eval_get_sign(r))
{
// We have one too many in the result:
- if(result)
+ if (result)
eval_decrement(*result);
- if(y.sign())
+ if (y.sign())
{
r.negate();
eval_subtract(r, y);
@@ -313,24 +309,24 @@ void divide_unsigned_helper(
eval_subtract(r, y, r);
}
- BOOST_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed
+ BOOST_MP_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed
}
template <class CppInt1, class CppInt2>
-void divide_unsigned_helper(
- CppInt1* result,
- const CppInt2& x,
- limb_type y,
- CppInt1& r)
+BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
+ CppInt1* result,
+ const CppInt2& x,
+ limb_type y,
+ CppInt1& r)
{
- if(((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
+ if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
{
CppInt2 t(x);
divide_unsigned_helper(result, t, y, r);
return;
}
- if(result == &r)
+ if (result == &r)
{
CppInt1 rem;
divide_unsigned_helper(result, x, y, rem);
@@ -342,14 +338,14 @@ void divide_unsigned_helper(
using default_ops::eval_subtract;
- if(y == 0)
+ if (y == 0)
{
- BOOST_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
}
//
// Find the most significant word of numerator.
//
- limb_type r_order = x.size() - 1;
+ std::size_t r_order = x.size() - 1;
//
// Set remainder and result to their initial values:
@@ -359,12 +355,12 @@ void divide_unsigned_helper(
typename CppInt1::limb_pointer pr = r.limbs();
//
- // check for x < y, try to do this without actually having to
+ // check for x < y, try to do this without actually having to
// do a full comparison:
//
- if((r_order == 0) && (*pr < y))
+ if ((r_order == 0) && (*pr < y))
{
- if(result)
+ if (result)
*result = static_cast<limb_type>(0u);
return;
}
@@ -372,9 +368,9 @@ void divide_unsigned_helper(
//
// See if we can short-circuit long division, and use basic arithmetic instead:
//
- if(r_order == 0)
+ if (r_order == 0)
{
- if(result)
+ if (result)
{
*result = *pr / y;
result->sign(x.sign());
@@ -383,11 +379,10 @@ void divide_unsigned_helper(
r.sign(x.sign());
return;
}
- else if(r_order == 1)
+ else if (r_order == 1)
{
- double_limb_type a;
- a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[0];
- if(result)
+ double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[0];
+ if (result)
{
*result = a / y;
result->sign(x.sign());
@@ -399,12 +394,12 @@ void divide_unsigned_helper(
// This is initialised just to keep the compiler from emitting useless warnings later on:
typename CppInt1::limb_pointer pres = typename CppInt1::limb_pointer();
- if(result)
+ if (result)
{
result->resize(r_order + 1, r_order + 1);
pres = result->limbs();
- if(result->size() > r_order)
- pres[r_order] = 0; // just in case we don't set the most significant limb below.
+ if (result->size() > r_order)
+ pres[r_order] = 0; // just in case we don't set the most significant limb below.
}
do
@@ -412,43 +407,42 @@ void divide_unsigned_helper(
//
// Calculate our best guess for how many times y divides into r:
//
- if((pr[r_order] < y) && r_order)
+ if ((pr[r_order] < y) && r_order)
{
- double_limb_type a, b;
- a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1];
- b = a % y;
+ double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1];
+ double_limb_type b = a % y;
r.resize(r.size() - 1, r.size() - 1);
--r_order;
pr[r_order] = static_cast<limb_type>(b);
- if(result)
+ if (result)
pres[r_order] = static_cast<limb_type>(a / y);
- if(r_order && pr[r_order] == 0)
+ if (r_order && pr[r_order] == 0)
{
- --r_order; // No remainder, division was exact.
+ --r_order; // No remainder, division was exact.
r.resize(r.size() - 1, r.size() - 1);
- if(result)
+ if (result)
pres[r_order] = static_cast<limb_type>(0u);
}
}
else
{
- if(result)
+ if (result)
pres[r_order] = pr[r_order] / y;
pr[r_order] %= y;
- if(r_order && pr[r_order] == 0)
+ if (r_order && pr[r_order] == 0)
{
- --r_order; // No remainder, division was exact.
+ --r_order; // No remainder, division was exact.
r.resize(r.size() - 1, r.size() - 1);
- if(result)
+ if (result)
pres[r_order] = static_cast<limb_type>(0u);
}
}
}
// Termination condition is really just a check that r >= y, but with two common
// short-circuit cases handled first:
- while(r_order || (pr[r_order] >= y));
+ while (r_order || (pr[r_order] >= y));
- if(result)
+ if (result)
{
result->normalize();
result->sign(x.sign());
@@ -456,200 +450,206 @@ void divide_unsigned_helper(
r.normalize();
r.sign(x.sign());
- BOOST_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
+ BOOST_MP_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, 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<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
- eval_divide(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
+eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
{
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
- bool s = a.sign() != b.sign();
+ bool s = a.sign() != b.sign();
divide_unsigned_helper(&result, a, b, r);
result.sign(s);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_divide(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- limb_type& b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ limb_type& b)
{
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
- bool s = a.sign();
+ bool s = a.sign();
divide_unsigned_helper(&result, a, b, r);
result.sign(s);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_divide(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- signed_limb_type& b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ signed_limb_type& b)
{
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
- bool s = a.sign() != (b < 0);
+ bool s = a.sign() != (b < 0);
divide_unsigned_helper(&result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(b)), r);
result.sign(s);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_divide(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
{
// There is no in place divide:
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
eval_divide(result, a, b);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_divide(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- limb_type b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ limb_type b)
{
// There is no in place divide:
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
eval_divide(result, a, b);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_divide(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- signed_limb_type b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ signed_limb_type b)
{
// There is no in place divide:
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
eval_divide(result, a, b);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, 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<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
+eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
{
bool s = a.sign();
- divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, b, result);
+ if (b.size() == 1)
+ eval_modulus(result, a, *b.limbs());
+ else
+ {
+ using cpp_int_backend1_type = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>;
+
+ divide_unsigned_helper(static_cast<cpp_int_backend1_type*>(nullptr), a, b, result);
+ }
result.sign(s);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, limb_type b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const limb_type mod)
{
- bool s = a.sign();
- divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, b, result);
- result.sign(s);
+ const std::ptrdiff_t n = static_cast<std::ptrdiff_t>(a.size());
+ const double_limb_type two_n_mod = static_cast<limb_type>(1u) + (~static_cast<limb_type>(0u) - mod) % mod;
+ limb_type res = a.limbs()[n - 1] % mod;
+
+ for (std::ptrdiff_t i = n - 2; i >= 0; --i)
+ res = static_cast<limb_type>(static_cast<double_limb_type>(static_cast<double_limb_type>(res * two_n_mod) + a.limbs()[i]) % mod);
+ //
+ // We must not modify result until here in case
+ // result and a are the same object:
+ //
+ result.resize(1, 1);
+ *result.limbs() = res;
+ result.sign(a.sign());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- signed_limb_type b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ signed_limb_type b)
{
- bool s = a.sign();
- divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(b)), result);
- result.sign(s);
+ const limb_type t = b < 0 ? static_cast<limb_type>(-b) : static_cast<limb_type>(b);
+ eval_modulus(result, a, t);
+ result.sign(a.sign());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
{
// There is no in place divide:
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
eval_modulus(result, a, b);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- limb_type b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ limb_type b)
{
- // There is no in place divide:
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
- eval_modulus(result, a, b);
+ // Single limb modulus is in place:
+ eval_modulus(result, result, b);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- signed_limb_type b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ signed_limb_type b)
{
- // There is no in place divide:
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
- eval_modulus(result, a, b);
+ // Single limb modulus is in place:
+ eval_modulus(result, result, b);
}
//
// Over again for trivial cpp_int's:
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
- >::type
- eval_divide(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type
+eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
{
- if(!*o.limbs())
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
+ if (!*o.limbs())
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
*result.limbs() /= *o.limbs();
result.sign(result.sign() != o.sign());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- >::type
- eval_divide(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
{
- if(!*o.limbs())
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
+ if (!*o.limbs())
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
*result.limbs() /= *o.limbs();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- >::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
{
- if(!*o.limbs())
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
+ if (!*o.limbs())
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
*result.limbs() %= *o.limbs();
result.sign(result.sign());
}
-}}} // namespaces
+}}} // namespace boost::multiprecision::backends
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/import_export.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/import_export.hpp
index b975a79663..e0c122213f 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/import_export.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/import_export.hpp
@@ -1,251 +1,248 @@
///////////////////////////////////////////////////////////////
// Copyright 2015 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP
#define BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP
+#include <climits>
+#include <cstring>
+#include <boost/multiprecision/detail/endian.hpp>
namespace boost {
- namespace multiprecision {
-
- namespace detail {
-
- template <class Backend, class Unsigned>
- 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<limb_type>(0u) : (static_cast<limb_type>(1u) << chunk_bits) - 1;
-
- limb_type value = static_cast<limb_type>(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 <class Backend, class Unsigned>
- 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<local_limb_type>(0u) : (static_cast<local_limb_type>(1u) << chunk_bits) - 1;
- local_limb_type value = (static_cast<local_limb_type>(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 <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
- inline void resize_to_bit_size(cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& newval, unsigned bits, const mpl::false_&)
- {
- unsigned limb_count = static_cast<unsigned>(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<unsigned>::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 <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
- inline void resize_to_bit_size(cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& newval, unsigned, const mpl::true_&)
- {
- *newval.limbs() = 0;
- }
-
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
- import_bits_generic(
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
- {
- typename number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>::backend_type newval;
-
- typedef typename std::iterator_traits<Iterator>::value_type value_type;
- typedef typename boost::make_unsigned<value_type>::type unsigned_value_type;
- typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
- typedef typename boost::make_unsigned<difference_type>::type size_type;
- typedef typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::trivial_tag tag_type;
-
- if(!chunk_size)
- chunk_size = std::numeric_limits<value_type>::digits;
-
- size_type limbs = std::distance(i, j);
- size_type bits = limbs * chunk_size;
-
- detail::resize_to_bit_size(newval, static_cast<unsigned>(bits), tag_type());
-
- difference_type bit_location = msv_first ? bits - chunk_size : 0;
- difference_type bit_location_change = msv_first ? -static_cast<difference_type>(chunk_size) : chunk_size;
-
- while(i != j)
- {
- detail::assign_bits(newval, static_cast<unsigned_value_type>(*i), static_cast<unsigned>(bit_location), chunk_size, tag_type());
- ++i;
- bit_location += bit_location_change;
- }
-
- newval.normalize();
-
- val.backend().swap(newval);
- return val;
- }
-
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
- inline typename boost::disable_if_c<boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
- import_bits_fast(
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, 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<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
- result.resize(static_cast<unsigned>(limb_len), static_cast<unsigned>(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 <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
- inline typename boost::enable_if_c<boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
- import_bits_fast(
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0)
- {
- cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& 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<unsigned>(limb_len), static_cast<unsigned>(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 multiprecision {
+
+namespace detail {
+
+template <class Backend, class Unsigned>
+void assign_bits(Backend& val, Unsigned bits, std::size_t bit_location, std::size_t chunk_bits, const std::integral_constant<bool, false>& tag)
+{
+ std::size_t limb = bit_location / (sizeof(limb_type) * CHAR_BIT);
+ std::size_t shift = bit_location % (sizeof(limb_type) * CHAR_BIT);
+ limb_type mask = chunk_bits >= sizeof(limb_type) * CHAR_BIT ? ~static_cast<limb_type>(0u) : (static_cast<limb_type>(1u) << chunk_bits) - 1;
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
- inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
- import_bits(
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
+ limb_type value = static_cast<limb_type>(bits & mask) << shift;
+ if (value)
+ {
+ if (val.size() == limb)
{
- return detail::import_bits_generic(val, i, j, chunk_size, msv_first);
+ 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 <class Backend, class Unsigned>
+void assign_bits(Backend& val, Unsigned bits, std::size_t bit_location, std::size_t chunk_bits, const std::integral_constant<bool, true>&)
+{
+ using local_limb_type = typename Backend::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<local_limb_type>(0u) : (static_cast<local_limb_type>(1u) << chunk_bits) - 1;
+ local_limb_type value = (static_cast<local_limb_type>(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 <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
- inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
- import_bits(
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, 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);
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+inline void resize_to_bit_size(cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& newval, std::size_t bits, const std::integral_constant<bool, false>&)
+{
+ std::size_t limb_count = static_cast<unsigned>(bits / (sizeof(limb_type) * CHAR_BIT));
+ if (bits % (sizeof(limb_type) * CHAR_BIT))
+ ++limb_count;
+ constexpr std::size_t max_limbs = MaxBits ? MaxBits / (CHAR_BIT * sizeof(limb_type)) + ((MaxBits % (CHAR_BIT * sizeof(limb_type))) ? 1 : 0) : (std::numeric_limits<unsigned>::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 <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+inline void resize_to_bit_size(cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& newval, unsigned, const std::integral_constant<bool, true>&)
+{
+ *newval.limbs() = 0;
+}
+
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
+number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
+import_bits_generic(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, std::size_t chunk_size = 0, bool msv_first = true)
+{
+ typename number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>::backend_type newval;
+
+ using value_type = typename std::iterator_traits<Iterator>::value_type ;
+ using unsigned_value_type = typename boost::multiprecision::detail::make_unsigned<value_type>::type ;
+ using difference_type = typename std::iterator_traits<Iterator>::difference_type ;
+ using size_type = typename boost::multiprecision::detail::make_unsigned<difference_type>::type ;
+ using tag_type = typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::trivial_tag;
+
+ if (!chunk_size)
+ chunk_size = std::numeric_limits<value_type>::digits;
+
+ size_type limbs = std::distance(i, j);
+ size_type bits = limbs * chunk_size;
+
+ detail::resize_to_bit_size(newval, static_cast<unsigned>(bits), tag_type());
+
+ difference_type bit_location = msv_first ? bits - chunk_size : 0;
+ difference_type bit_location_change = msv_first ? -static_cast<difference_type>(chunk_size) : chunk_size;
+
+ while (i != j)
+ {
+ detail::assign_bits(newval, static_cast<unsigned_value_type>(*i), static_cast<std::size_t>(bit_location), chunk_size, tag_type());
+ ++i;
+ bit_location += bit_location_change;
+ }
+
+ newval.normalize();
+
+ val.backend().swap(newval);
+ return val;
+}
+
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
+inline typename std::enable_if< !boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
+import_bits_fast(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, std::size_t 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<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
+ result.resize(static_cast<unsigned>(limb_len), static_cast<unsigned>(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 <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
+inline typename std::enable_if<boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
+import_bits_fast(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, std::size_t chunk_size = 0)
+{
+ cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& 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<unsigned>(limb_len), static_cast<unsigned>(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 <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
+inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
+import_bits(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, std::size_t chunk_size = 0, bool msv_first = true)
+{
+ return detail::import_bits_generic(val, i, j, chunk_size, msv_first);
+}
+
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
+inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
+import_bits(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, std::size_t chunk_size = 0, bool msv_first = true)
+{
+#if BOOST_MP_ENDIAN_LITTLE_BYTE
+ 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);
- }
+ return detail::import_bits_generic(val, i, j, chunk_size, msv_first);
+}
- namespace detail {
-
- template <class Backend>
- 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<boost::uintmax_t>::digits ? ~static_cast<boost::uintmax_t>(0) : (static_cast<boost::uintmax_t>(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 <class Backend>
- 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<typename Backend::local_limb_type>::digits ? ~static_cast<typename Backend::local_limb_type>(0) : (static_cast<typename Backend::local_limb_type>(1u) << count) - 1;
- return (result >> location) & mask;
- }
+namespace detail {
+
+template <class Backend>
+std::uintmax_t extract_bits(const Backend& val, std::size_t location, std::size_t count, const std::integral_constant<bool, false>& tag)
+{
+ std::size_t limb = location / (sizeof(limb_type) * CHAR_BIT);
+ std::size_t shift = location % (sizeof(limb_type) * CHAR_BIT);
+ std::uintmax_t result = 0;
+ std::uintmax_t mask = count == std::numeric_limits<std::uintmax_t>::digits ? ~static_cast<std::uintmax_t>(0) : (static_cast<std::uintmax_t>(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 <class Backend>
+inline std::uintmax_t extract_bits(const Backend& val, std::size_t location, std::size_t count, const std::integral_constant<bool, true>&)
+{
+ typename Backend::local_limb_type result = *val.limbs();
+ typename Backend::local_limb_type mask = count >= std::numeric_limits<typename Backend::local_limb_type>::digits ? ~static_cast<typename Backend::local_limb_type>(0) : (static_cast<typename Backend::local_limb_type>(1u) << count) - 1;
+ return (result >> location) & mask;
+}
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class OutputIterator>
- OutputIterator export_bits(
- const number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, OutputIterator out, unsigned chunk_size, bool msv_first = true)
- {
-#ifdef _MSC_VER
+} // namespace detail
+
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class OutputIterator>
+OutputIterator export_bits(
+ const number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, OutputIterator out, std::size_t chunk_size, bool msv_first = true)
+{
+#ifdef BOOST_MSVC
#pragma warning(push)
-#pragma warning(disable:4244)
+#pragma warning(disable : 4244)
#endif
- typedef typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::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<int>(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
+ using tag_type = typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::trivial_tag;
+ if (!val)
+ {
+ *out = 0;
+ ++out;
+ return out;
+ }
+ std::size_t bitcount = boost::multiprecision::backends::eval_msb_imp(val.backend()) + 1;
+
+ std::ptrdiff_t bit_location = msv_first ? static_cast<std::ptrdiff_t>(bitcount - chunk_size) : 0;
+ const std::ptrdiff_t bit_step = msv_first ? static_cast<std::ptrdiff_t>(-static_cast<std::ptrdiff_t>(chunk_size)) : static_cast<std::ptrdiff_t>(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 < static_cast<int>(bitcount)));
+
+ return out;
+#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
- }
-
- }
}
-
+}
+} // namespace boost::multiprecision
#endif // BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP
-
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/intel_intrinsics.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/intel_intrinsics.hpp
new file mode 100644
index 0000000000..1dfe181dee
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/intel_intrinsics.hpp
@@ -0,0 +1,138 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2020 Madhur Chauhan.
+// Copyright 2020 John Maddock.
+// Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_MP_INTEL_INTRINSICS_HPP
+#define BOOST_MP_INTEL_INTRINSICS_HPP
+//
+// Select which actual implementation header to use:
+//
+#ifdef __has_include
+#if __has_include(<immintrin.h>)
+#define BOOST_MP_HAS_IMMINTRIN_H
+#endif
+#endif
+//
+// If this is GCC/clang, then check that the actual intrinsic exists:
+//
+#if defined(__has_builtin) && defined(__GNUC__)
+#if !__has_builtin(__builtin_ia32_addcarryx_u64) && defined(BOOST_MP_HAS_IMMINTRIN_H) \
+ && !(defined(BOOST_GCC) && (__GNUC__ >= 9) \
+ && (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)\
+ || defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_AMD64) \
+ || defined(_M_X64) || defined(__amd64__) || defined(_M_X64)))
+#undef BOOST_MP_HAS_IMMINTRIN_H
+#endif
+#elif defined(BOOST_MP_HAS_IMMINTRIN_H) && defined(__GNUC__) && !(defined(BOOST_GCC) && (__GNUC__ >= 9))
+#undef BOOST_MP_HAS_IMMINTRIN_H
+#endif
+
+#if defined(__clang_major__) && (__clang_major__ < 9)
+// We appear to crash the compiler if we try to use these intrinsics?
+#undef BOOST_MP_HAS_IMMINTRIN_H
+#endif
+
+#if defined(_WIN32) && (defined(_M_ARM64) || defined(_M_ARM))
+//
+// When targeting platforms such as ARM, msvc (and also clang when emulating msvc) still has the
+// Intel headers in its include path even though they're not usable.
+// See https://github.com/boostorg/multiprecision/issues/321
+// Also https://github.com/boostorg/multiprecision/issues/475
+//
+#undef BOOST_MP_HAS_IMMINTRIN_H
+#endif
+
+#if defined(__APPLE_CC__) && defined(__clang_major__) && (__clang_major__ < 11) && defined(BOOST_MP_HAS_IMMINTRIN_H)
+// Apple clang has it's own version numbers.
+#undef BOOST_MP_HAS_IMMINTRIN_H
+#endif
+
+
+//
+// If the compiler supports the intrinsics used by GCC internally
+// inside <immintrin.h> then we'll use them directly.
+// This is a bit of defensive programming, mostly for a modern clang
+// sitting on top of an older GCC header install.
+//
+#if defined(__has_builtin) && !defined(BOOST_INTEL)
+
+# if __has_builtin(__builtin_ia32_addcarryx_u64)
+# define BOOST_MP_ADDC __builtin_ia32_addcarryx_u
+# endif
+
+# if __has_builtin(__builtin_ia32_subborrow_u64)
+# define BOOST_MP_SUBB __builtin_ia32_subborrow_u
+# elif __has_builtin(__builtin_ia32_sbb_u64)
+# define BOOST_MP_SUBB __builtin_ia32_sbb_u
+# endif
+
+#endif
+
+#ifndef BOOST_MP_ADDC
+#define BOOST_MP_ADDC _addcarry_u
+#endif
+#ifndef BOOST_MP_SUBB
+#define BOOST_MP_SUBB _subborrow_u
+#endif
+
+#ifdef BOOST_MP_HAS_IMMINTRIN_H
+
+#ifdef BOOST_MSVC
+//
+// This is a subset of the full <immintrin.h> :
+//
+#include <intrin.h>
+#else
+#include <immintrin.h>
+#endif
+
+#if defined(BOOST_HAS_INT128)
+
+namespace boost { namespace multiprecision { namespace detail {
+
+BOOST_MP_FORCEINLINE unsigned char addcarry_limb(unsigned char carry, limb_type a, limb_type b, limb_type* p_result)
+{
+#ifdef BOOST_INTEL
+ using cast_type = unsigned __int64;
+#else
+ using cast_type = unsigned long long;
+#endif
+ return BOOST_JOIN(BOOST_MP_ADDC, 64)(carry, a, b, reinterpret_cast<cast_type*>(p_result));
+}
+
+BOOST_MP_FORCEINLINE unsigned char subborrow_limb(unsigned char carry, limb_type a, limb_type b, limb_type* p_result)
+{
+#ifdef BOOST_INTEL
+ using cast_type = unsigned __int64;
+#else
+ using cast_type = unsigned long long;
+#endif
+ return BOOST_JOIN(BOOST_MP_SUBB, 64)(carry, a, b, reinterpret_cast<cast_type*>(p_result));
+}
+
+}}} // namespace boost::multiprecision::detail
+
+#else
+
+namespace boost { namespace multiprecision { namespace detail {
+
+BOOST_MP_FORCEINLINE unsigned char addcarry_limb(unsigned char carry, limb_type a, limb_type b, limb_type* p_result)
+{
+ return BOOST_JOIN(BOOST_MP_ADDC, 32)(carry, a, b, reinterpret_cast<unsigned int*>(p_result));
+}
+
+BOOST_MP_FORCEINLINE unsigned char subborrow_limb(unsigned char carry, limb_type a, limb_type b, limb_type* p_result)
+{
+ return BOOST_JOIN(BOOST_MP_SUBB, 32)(carry, a, b, reinterpret_cast<unsigned int*>(p_result));
+}
+
+}}} // namespace boost::multiprecision::detail
+
+#endif
+
+#endif
+
+#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/limits.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/limits.hpp
index b19e1ebbe6..df80d02e7e 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/limits.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/limits.hpp
@@ -1,86 +1,150 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
-#ifndef BOOST_MP_CPP_INT_LIM_HPP
-#define BOOST_MP_CPP_INT_LIM_HPP
+#ifndef BOOST_MP_CPP_INT_LIMITS_HPP
+#define BOOST_MP_CPP_INT_LIMITS_HPP
-namespace std{
+#include <boost/multiprecision/traits/max_digits10.hpp>
-namespace detail{
+namespace std {
-#ifdef _MSC_VER
+namespace detail {
+
+#ifdef BOOST_MSVC
#pragma warning(push)
-#pragma warning(disable:4307)
+#pragma warning(disable : 4307)
#endif
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_CXX14_CONSTEXPR_IF_DETECTION boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
+get_min(const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&)
+{
+ // Bounded, signed, and no allocator.
+ using result_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> ;
+ using ui_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked>, ExpressionTemplates>;
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ static
+#else
+ constexpr
+#endif
+ const result_type val = -result_type(~ui_type(0));
+ return val;
+}
+
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
- get_min(const boost::mpl::true_&, const boost::mpl::true_&)
+get_min(const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&)
+{
+ // Bounded, signed, and an allocator (can't be constexpr).
+ using result_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> ;
+ using ui_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked>, ExpressionTemplates>;
+ static const result_type val = -result_type(~ui_type(0));
+ return val;
+}
+
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_CXX14_CONSTEXPR_IF_DETECTION boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
+get_min(const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
{
- // Bounded and signed.
- typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, 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));
+ // Bounded, unsigned, no allocator (can be constexpr):
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ static
+#else
+ constexpr
+#endif
+ const boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> val(0u);
return val;
}
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
- get_min(const boost::mpl::true_&, const boost::mpl::false_&)
+get_min(const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&)
{
- // Bounded and unsigned:
+ // Bounded and std::size_t with allocator (no constexpr):
static const boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> val(0u);
return val;
}
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates, bool has_allocator>
inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
- get_min(const boost::mpl::false_&, const boost::mpl::true_&)
+get_min(const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&, const std::integral_constant<bool, has_allocator>&)
{
- // Unbounded and signed.
+ // Unbounded and signed, never constexpr because there must be an allocator.
// There is no minimum value, just return 0:
static const boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> val(0u);
return val;
}
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates, bool has_allocator>
inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
- get_min(const boost::mpl::false_&, const boost::mpl::false_&)
+get_min(const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&, const std::integral_constant<bool, has_allocator>&)
{
- // Unbound and unsigned:
+ // Unbound and unsigned, never constexpr because there must be an allocator.
static const boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> val(0u);
return val;
}
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_CXX14_CONSTEXPR_IF_DETECTION boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
+get_max(const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&)
+{
+ // Bounded and signed, no allocator, can be constexpr.
+ using result_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> ;
+ using ui_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked>, ExpressionTemplates>;
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ static
+#else
+ constexpr
+#endif
+ const result_type val = ~ui_type(0);
+ return val;
+}
+
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
- get_max(const boost::mpl::true_&, const boost::mpl::true_&)
+get_max(const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&)
{
- // Bounded and signed.
- typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, 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);
+ // Bounded and signed, has an allocator, never constexpr.
+ using result_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> ;
+ using ui_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked>, ExpressionTemplates>;
+ static const result_type val = ~ui_type(0);
return val;
}
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_CXX14_CONSTEXPR_IF_DETECTION boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
+get_max(const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
+{
+ // Bound and unsigned, no allocator so can be constexpr:
+ using result_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> ;
+ using ui_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, Allocator>, ExpressionTemplates>;
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+ static
+#else
+ constexpr
+#endif
+ const result_type val = ~ui_type(0);
+ return val;
+}
+
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
- get_max(const boost::mpl::true_&, const boost::mpl::false_&)
+get_max(const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&)
{
- // Bound and unsigned:
- typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, 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);
+ // Bound and unsigned, has an allocator so can never be constexpr:
+ using result_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> ;
+ using ui_type = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, Allocator>, ExpressionTemplates>;
+ static const result_type val = ~ui_type(0);
return val;
}
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates, bool has_allocator>
inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
- get_max(const boost::mpl::false_&, const boost::mpl::true_&)
+get_max(const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&, const std::integral_constant<bool, has_allocator>&)
{
// Unbounded and signed.
// There is no maximum value, just return 0:
@@ -88,134 +152,114 @@ inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinB
return val;
}
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates, bool has_allocator>
inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
- get_max(const boost::mpl::false_&, const boost::mpl::false_&)
+get_max(const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&, const std::integral_constant<bool, has_allocator>&)
{
// Unbound and unsigned:
static const boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> val(0u);
return val;
}
-}
+} // namespace detail
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >
{
- typedef boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> backend_type;
- typedef boost::multiprecision::number<backend_type, ExpressionTemplates> number_type;
+ using backend_type = boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>;
+ using number_type = boost::multiprecision::number<backend_type, ExpressionTemplates> ;
- struct inititializer
- {
- inititializer()
- {
- (std::numeric_limits<number_type>::max)();
- (std::numeric_limits<number_type>::min)();
- }
- void do_nothing()const{}
- };
-
- static const inititializer init;
-
-public:
- BOOST_STATIC_CONSTEXPR bool is_specialized = true;
+ public:
+ static constexpr bool is_specialized = true;
//
// Largest and smallest numbers are bounded only by available memory, set
// to zero:
//
- static number_type (min)()
+ static BOOST_CXX14_CONSTEXPR_IF_DETECTION number_type(min)()
{
- init.do_nothing();
- return detail::get_min<MinBits, MaxBits, SignType, Checked, Allocator, ExpressionTemplates>(boost::multiprecision::backends::is_fixed_precision<backend_type>(), boost::multiprecision::is_signed_number<backend_type>());
+ return detail::get_min<MinBits, MaxBits, SignType, Checked, Allocator, ExpressionTemplates>(boost::multiprecision::backends::is_fixed_precision<backend_type>(), boost::multiprecision::is_signed_number<backend_type>(), std::integral_constant<bool, std::is_void<Allocator>::value>());
}
- static number_type (max)()
- {
- init.do_nothing();
- return detail::get_max<MinBits, MaxBits, SignType, Checked, Allocator, ExpressionTemplates>(boost::multiprecision::backends::is_fixed_precision<backend_type>(), boost::multiprecision::is_signed_number<backend_type>());
+ static BOOST_CXX14_CONSTEXPR_IF_DETECTION number_type(max)()
+ {
+ return detail::get_max<MinBits, MaxBits, SignType, Checked, Allocator, ExpressionTemplates>(boost::multiprecision::backends::is_fixed_precision<backend_type>(), boost::multiprecision::is_signed_number<backend_type>(), std::integral_constant<bool, std::is_void<Allocator>::value>());
}
- static number_type lowest() { return (min)(); }
- BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::backends::max_precision<backend_type>::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<backend_type>::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<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;
+ static BOOST_CXX14_CONSTEXPR_IF_DETECTION number_type lowest() { return (min)(); }
+ static constexpr int digits = boost::multiprecision::backends::max_precision<backend_type>::value == SIZE_MAX ? INT_MAX : boost::multiprecision::backends::max_precision<backend_type>::value;
+ static constexpr int digits10 = static_cast<int>(boost::multiprecision::detail::calc_digits10_s<static_cast<std::size_t>(digits)>::value);
+ static constexpr int max_digits10 = static_cast<int>(boost::multiprecision::detail::calc_max_digits10_s<static_cast<std::size_t>(digits)>::value);
+ static constexpr bool is_signed = boost::multiprecision::is_signed_number<backend_type>::value;
+ static constexpr bool is_integer = true;
+ static constexpr bool is_exact = true;
+ static constexpr int radix = 2;
+ static BOOST_CXX14_CONSTEXPR_IF_DETECTION number_type epsilon() { return 0; }
+ static BOOST_CXX14_CONSTEXPR_IF_DETECTION number_type round_error() { return 0; }
+ static constexpr int min_exponent = 0;
+ static constexpr int min_exponent10 = 0;
+ static constexpr int max_exponent = 0;
+ static constexpr int max_exponent10 = 0;
+ static constexpr bool has_infinity = false;
+ static constexpr bool has_quiet_NaN = false;
+ static constexpr bool has_signaling_NaN = false;
+ static constexpr float_denorm_style has_denorm = denorm_absent;
+ static constexpr bool has_denorm_loss = false;
+ static BOOST_CXX14_CONSTEXPR_IF_DETECTION number_type infinity() { return 0; }
+ static BOOST_CXX14_CONSTEXPR_IF_DETECTION number_type quiet_NaN() { return 0; }
+ static BOOST_CXX14_CONSTEXPR_IF_DETECTION number_type signaling_NaN() { return 0; }
+ static BOOST_CXX14_CONSTEXPR_IF_DETECTION number_type denorm_min() { return 0; }
+ static constexpr bool is_iec559 = false;
+ static constexpr bool is_bounded = boost::multiprecision::backends::is_fixed_precision<backend_type>::value;
+ static constexpr bool is_modulo = (boost::multiprecision::backends::is_fixed_precision<backend_type>::value && (Checked == boost::multiprecision::unchecked));
+ static constexpr bool traps = false;
+ static constexpr bool tinyness_before = false;
+ static constexpr float_round_style round_style = round_toward_zero;
};
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::inititializer numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::init;
-
-#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
-
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::digits;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::digits10;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::max_digits10;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_signed;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_integer;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_exact;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::radix;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::min_exponent;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::min_exponent10;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::max_exponent;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::max_exponent10;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_infinity;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_quiet_NaN;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_signaling_NaN;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_denorm;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_denorm_loss;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_iec559;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_bounded;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_modulo;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::traps;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::tinyness_before;
-template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::round_style;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::digits;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::digits10;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::max_digits10;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_signed;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_integer;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_exact;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::radix;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::min_exponent;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::min_exponent10;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::max_exponent;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::max_exponent10;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_infinity;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_quiet_NaN;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_signaling_NaN;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_denorm;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::has_denorm_loss;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_iec559;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_bounded;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::is_modulo;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::traps;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::tinyness_before;
+template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::round_style;
-#endif
-#ifdef _MSC_VER
+#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/literals.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/literals.hpp
index ce30fd8484..1401667860 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/literals.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/literals.hpp
@@ -1,124 +1,214 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_LITERALS_HPP
#define BOOST_MP_CPP_INT_LITERALS_HPP
#include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
-namespace boost{ namespace multiprecision{
-
-namespace literals{ namespace detail{
-
-template <char> struct hex_value;
-template <> struct hex_value<'0'> { static constexpr limb_type value = 0; };
-template <> struct hex_value<'1'> { static constexpr limb_type value = 1; };
-template <> struct hex_value<'2'> { static constexpr limb_type value = 2; };
-template <> struct hex_value<'3'> { static constexpr limb_type value = 3; };
-template <> struct hex_value<'4'> { static constexpr limb_type value = 4; };
-template <> struct hex_value<'5'> { static constexpr limb_type value = 5; };
-template <> struct hex_value<'6'> { static constexpr limb_type value = 6; };
-template <> struct hex_value<'7'> { static constexpr limb_type value = 7; };
-template <> struct hex_value<'8'> { static constexpr limb_type value = 8; };
-template <> struct hex_value<'9'> { static constexpr limb_type value = 9; };
-template <> struct hex_value<'a'> { static constexpr limb_type value = 10; };
-template <> struct hex_value<'b'> { static constexpr limb_type value = 11; };
-template <> struct hex_value<'c'> { static constexpr limb_type value = 12; };
-template <> struct hex_value<'d'> { static constexpr limb_type value = 13; };
-template <> struct hex_value<'e'> { static constexpr limb_type value = 14; };
-template <> struct hex_value<'f'> { static constexpr limb_type value = 15; };
-template <> struct hex_value<'A'> { static constexpr limb_type value = 10; };
-template <> struct hex_value<'B'> { static constexpr limb_type value = 11; };
-template <> struct hex_value<'C'> { static constexpr limb_type value = 12; };
-template <> struct hex_value<'D'> { static constexpr limb_type value = 13; };
-template <> struct hex_value<'E'> { static constexpr limb_type value = 14; };
-template <> struct hex_value<'F'> { static constexpr limb_type value = 15; };
+namespace boost { namespace multiprecision {
+
+namespace literals {
+namespace detail {
+
+template <char>
+struct hex_value;
+template <>
+struct hex_value<'0'>
+{
+ static constexpr limb_type value = 0;
+};
+template <>
+struct hex_value<'1'>
+{
+ static constexpr limb_type value = 1;
+};
+template <>
+struct hex_value<'2'>
+{
+ static constexpr limb_type value = 2;
+};
+template <>
+struct hex_value<'3'>
+{
+ static constexpr limb_type value = 3;
+};
+template <>
+struct hex_value<'4'>
+{
+ static constexpr limb_type value = 4;
+};
+template <>
+struct hex_value<'5'>
+{
+ static constexpr limb_type value = 5;
+};
+template <>
+struct hex_value<'6'>
+{
+ static constexpr limb_type value = 6;
+};
+template <>
+struct hex_value<'7'>
+{
+ static constexpr limb_type value = 7;
+};
+template <>
+struct hex_value<'8'>
+{
+ static constexpr limb_type value = 8;
+};
+template <>
+struct hex_value<'9'>
+{
+ static constexpr limb_type value = 9;
+};
+template <>
+struct hex_value<'a'>
+{
+ static constexpr limb_type value = 10;
+};
+template <>
+struct hex_value<'b'>
+{
+ static constexpr limb_type value = 11;
+};
+template <>
+struct hex_value<'c'>
+{
+ static constexpr limb_type value = 12;
+};
+template <>
+struct hex_value<'d'>
+{
+ static constexpr limb_type value = 13;
+};
+template <>
+struct hex_value<'e'>
+{
+ static constexpr limb_type value = 14;
+};
+template <>
+struct hex_value<'f'>
+{
+ static constexpr limb_type value = 15;
+};
+template <>
+struct hex_value<'A'>
+{
+ static constexpr limb_type value = 10;
+};
+template <>
+struct hex_value<'B'>
+{
+ static constexpr limb_type value = 11;
+};
+template <>
+struct hex_value<'C'>
+{
+ static constexpr limb_type value = 12;
+};
+template <>
+struct hex_value<'D'>
+{
+ static constexpr limb_type value = 13;
+};
+template <>
+struct hex_value<'E'>
+{
+ static constexpr limb_type value = 14;
+};
+template <>
+struct hex_value<'F'>
+{
+ static constexpr limb_type value = 15;
+};
template <class Pack, limb_type value>
struct combine_value_to_pack;
-template <limb_type first, limb_type...ARGS, limb_type value>
+template <limb_type first, limb_type... ARGS, limb_type value>
struct combine_value_to_pack<value_pack<first, ARGS...>, value>
{
- typedef value_pack<first | value, ARGS...> type;
+ using type = value_pack<first | value, ARGS...>;
};
-template <char NextChar, char...CHARS>
+template <char NextChar, char... CHARS>
struct pack_values
{
- static constexpr unsigned chars_per_limb = sizeof(limb_type) * CHAR_BIT / 4;
- static constexpr unsigned shift = ((sizeof...(CHARS)) % chars_per_limb) * 4;
- static constexpr limb_type value_to_add = shift ? hex_value<NextChar>::value << shift : hex_value<NextChar>::value;
+ static constexpr std::size_t chars_per_limb = sizeof(limb_type) * CHAR_BIT / 4;
+ static constexpr std::size_t shift = ((sizeof...(CHARS)) % chars_per_limb) * 4;
+ static constexpr limb_type value_to_add = shift ? hex_value<NextChar>::value << shift : hex_value<NextChar>::value;
- typedef typename pack_values<CHARS...>::type recursive_packed_type;
- typedef typename boost::mpl::if_c<shift == 0,
- typename recursive_packed_type::next_type,
- recursive_packed_type>::type pack_type;
- typedef typename combine_value_to_pack<pack_type, value_to_add>::type type;
+ using recursive_packed_type = typename pack_values<CHARS...>::type ;
+ using pack_type = typename std::conditional<shift == 0,
+ typename recursive_packed_type::next_type,
+ recursive_packed_type>::type;
+ using type = typename combine_value_to_pack<pack_type, value_to_add>::type;
};
template <char NextChar>
struct pack_values<NextChar>
{
static constexpr limb_type value_to_add = hex_value<NextChar>::value;
- typedef value_pack<value_to_add> type;
+ using type = value_pack<value_to_add>;
};
template <class T>
struct strip_leading_zeros_from_pack;
-template <limb_type...PACK>
+template <limb_type... PACK>
struct strip_leading_zeros_from_pack<value_pack<PACK...> >
{
- typedef value_pack<PACK...> type;
+ using type = value_pack<PACK...>;
};
-template <limb_type...PACK>
+template <limb_type... PACK>
struct strip_leading_zeros_from_pack<value_pack<0u, PACK...> >
{
- typedef typename strip_leading_zeros_from_pack<value_pack<PACK...> >::type type;
+ using type = typename strip_leading_zeros_from_pack<value_pack<PACK...> >::type;
};
template <limb_type v, class PACK>
struct append_value_to_pack;
-template <limb_type v, limb_type...PACK>
+template <limb_type v, limb_type... PACK>
struct append_value_to_pack<v, value_pack<PACK...> >
{
- typedef value_pack<PACK..., v> type;
+ using type = value_pack<PACK..., v>;
};
template <class T>
struct reverse_value_pack;
-template <limb_type v, limb_type...VALUES>
+template <limb_type v, limb_type... VALUES>
struct reverse_value_pack<value_pack<v, VALUES...> >
{
- typedef typename reverse_value_pack<value_pack<VALUES...> >::type lead_values;
- typedef typename append_value_to_pack<v, lead_values>::type type;
+ using lead_values = typename reverse_value_pack<value_pack<VALUES...> >::type;
+ using type = typename append_value_to_pack<v, lead_values>::type ;
};
template <limb_type v>
struct reverse_value_pack<value_pack<v> >
{
- typedef value_pack<v> type;
+ using type = value_pack<v>;
};
template <>
struct reverse_value_pack<value_pack<> >
{
- typedef value_pack<> type;
+ using type = value_pack<>;
};
-template <char l1, char l2, char...STR>
+template <char l1, char l2, char... STR>
struct make_packed_value_from_str
{
- BOOST_STATIC_ASSERT_MSG(l1 == '0', "Multi-precision integer literals must be in hexadecimal notation.");
- BOOST_STATIC_ASSERT_MSG((l2 == 'X') || (l2 == 'x'), "Multi-precision integer literals must be in hexadecimal notation.");
- typedef typename pack_values<STR...>::type packed_type;
- typedef typename strip_leading_zeros_from_pack<packed_type>::type stripped_type;
- typedef typename reverse_value_pack<stripped_type>::type type;
+ static_assert(l1 == '0', "Multi-precision integer literals must be in hexadecimal notation.");
+ static_assert((l2 == 'X') || (l2 == 'x'), "Multi-precision integer literals must be in hexadecimal notation.");
+ using packed_type = typename pack_values<STR...>::type ;
+ using stripped_type = typename strip_leading_zeros_from_pack<packed_type>::type;
+ using type = typename reverse_value_pack<stripped_type>::type ;
};
template <class Pack, class B>
struct make_backend_from_pack
{
- static constexpr Pack p = {};
+ static constexpr Pack p = {};
static constexpr B value = p;
};
@@ -128,79 +218,76 @@ constexpr B make_backend_from_pack<Pack, B>::value;
template <unsigned Digits>
struct signed_cpp_int_literal_result_type
{
- static constexpr unsigned bits = Digits * 4;
- typedef boost::multiprecision::backends::cpp_int_backend<bits, bits, signed_magnitude, unchecked, void> backend_type;
- typedef number<backend_type, et_off> number_type;
+ static constexpr unsigned bits = Digits * 4;
+ using backend_type = boost::multiprecision::backends::cpp_int_backend<bits, bits, signed_magnitude, unchecked, void>;
+ using number_type = number<backend_type, et_off> ;
};
template <unsigned Digits>
struct unsigned_cpp_int_literal_result_type
{
- static constexpr unsigned bits = Digits * 4;
- typedef boost::multiprecision::backends::cpp_int_backend<bits, bits, unsigned_magnitude, unchecked, void> backend_type;
- typedef number<backend_type, et_off> number_type;
+ static constexpr unsigned bits = Digits * 4;
+ using backend_type = boost::multiprecision::backends::cpp_int_backend<bits, bits, unsigned_magnitude, unchecked, void>;
+ using number_type = number<backend_type, et_off> ;
};
-}
+} // namespace detail
template <char... STR>
-constexpr typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator "" _cppi()
+constexpr typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::number_type operator"" _cppi()
{
- typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;
- return boost::multiprecision::literals::detail::make_backend_from_pack<pt, typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::backend_type>::value;
+ using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type;
+ return boost::multiprecision::literals::detail::make_backend_from_pack<pt, typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::backend_type>::value;
}
template <char... STR>
-constexpr typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator "" _cppui()
+constexpr typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::number_type operator"" _cppui()
{
- typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;
- return boost::multiprecision::literals::detail::make_backend_from_pack<pt, typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::backend_type>::value;
+ using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type;
+ return boost::multiprecision::literals::detail::make_backend_from_pack<pt, typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::backend_type>::value;
}
-#define BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(Bits)\
-template <char... STR> \
-constexpr boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> > operator "" BOOST_JOIN(_cppi, Bits)()\
-{\
- typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;\
- return boost::multiprecision::literals::detail::make_backend_from_pack<\
- pt, \
- boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> \
- >::value;\
-}\
-template <char... STR> \
-constexpr boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> > operator "" BOOST_JOIN(_cppui, Bits)()\
-{\
- typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;\
- return boost::multiprecision::literals::detail::make_backend_from_pack<\
- pt, \
- boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>\
- >::value;\
-}\
+#define BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(Bits) \
+ template <char... STR> \
+ constexpr boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> > operator"" BOOST_JOIN(_cppi, Bits)() \
+ { \
+ using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; \
+ return boost::multiprecision::literals::detail::make_backend_from_pack< \
+ pt, \
+ boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> >::value; \
+ } \
+ template <char... STR> \
+ constexpr boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> > operator"" BOOST_JOIN(_cppui, Bits)() \
+ { \
+ using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; \
+ return boost::multiprecision::literals::detail::make_backend_from_pack< \
+ pt, \
+ boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> >::value; \
+ }
BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(128)
BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(256)
BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(512)
BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(1024)
-}
+} // namespace literals
//
// Overload unary minus operator for constexpr use:
//
-template <unsigned MinBits, cpp_int_check_type Checked>
+template <std::size_t MinBits, cpp_int_check_type Checked>
constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
- operator - (const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>& a)
+operator-(const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>& a)
{
return cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>(a.backend(), boost::multiprecision::literals::detail::make_negate_tag());
}
-template <unsigned MinBits, cpp_int_check_type Checked>
+template <std::size_t MinBits, cpp_int_check_type Checked>
constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
- operator - (number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&& a)
+operator-(number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&& a)
{
return cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>(static_cast<const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&>(a).backend(), boost::multiprecision::literals::detail::make_negate_tag());
}
-}} // namespaces
+}} // namespace boost::multiprecision
#endif // BOOST_MP_CPP_INT_CORE_HPP
-
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/misc.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/misc.hpp
index abbdc295d0..6103f55b8e 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/misc.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/misc.hpp
@@ -1,81 +1,125 @@
///////////////////////////////////////////////////////////////
-// Copyright 2012 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_
+// Copyright 2012-2020 John Maddock.
+// Copyright 2020 Madhur Chauhan.
+// Copyright 2021 Matt Borland.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
//
// Comparison operators for cpp_int_backend:
//
#ifndef BOOST_MP_CPP_INT_MISC_HPP
#define BOOST_MP_CPP_INT_MISC_HPP
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/number_base.hpp>
+#include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
+#include <boost/multiprecision/detail/float128_functions.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+#include <boost/multiprecision/detail/constexpr.hpp>
#include <boost/multiprecision/detail/bitscan.hpp> // lsb etc
-#include <boost/integer/common_factor_rt.hpp> // gcd/lcm
-#include <boost/functional/hash_fwd.hpp>
+#include <boost/multiprecision/detail/hash.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <numeric> // std::gcd
+#include <type_traits>
+#include <stdexcept>
+#include <cmath>
+
+#ifndef BOOST_MP_STANDALONE
+#include <boost/integer/common_factor_rt.hpp>
+#endif
+
+#ifdef BOOST_MP_MATH_AVAILABLE
+#include <boost/math/special_functions/next.hpp>
+#endif
#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
+// Forward decleration of gcd and lcm functions
+namespace boost { namespace multiprecision { namespace detail {
+
+template <typename T>
+inline BOOST_CXX14_CONSTEXPR T constexpr_gcd(T a, T b) noexcept;
+
+template <typename T>
+inline BOOST_CXX14_CONSTEXPR T constexpr_lcm(T a, T b) noexcept;
-namespace boost{ namespace multiprecision{ namespace backends{
+}}} // namespace boost::multiprecision::detail
+
+namespace boost { namespace multiprecision { namespace backends {
+
+template <class T, bool has_limits = std::numeric_limits<T>::is_specialized>
+struct numeric_limits_workaround : public std::numeric_limits<T>
+{
+};
+template <class R>
+struct numeric_limits_workaround<R, false>
+{
+ static constexpr unsigned digits = ~static_cast<R>(0) < 0 ? sizeof(R) * CHAR_BIT - 1 : sizeof(R) * CHAR_BIT;
+ static constexpr R (min)(){ return (static_cast<R>(-1) < 0) ? static_cast<R>(1) << digits : 0; }
+ static constexpr R (max)() { return (static_cast<R>(-1) < 0) ? ~(static_cast<R>(1) << digits) : ~static_cast<R>(0); }
+};
template <class R, class CppInt>
-void check_in_range(const CppInt& val, const mpl::int_<checked>&)
+BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& val, const std::integral_constant<int, checked>&)
{
- typedef typename boost::multiprecision::detail::canonical<R, CppInt>::type cast_type;
- if(val.sign())
+ using cast_type = typename boost::multiprecision::detail::canonical<R, CppInt>::type;
+
+ if (val.sign())
{
- if(std::numeric_limits<R>::is_signed == false)
- BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
- if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::min)())) < 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
+ BOOST_IF_CONSTEXPR (boost::multiprecision::detail::is_signed<R>::value == false)
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
+ if (val.compare(static_cast<cast_type>((numeric_limits_workaround<R>::min)())) < 0)
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
}
else
{
- if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::max)())) > 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
+ if (val.compare(static_cast<cast_type>((numeric_limits_workaround<R>::max)())) > 0)
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
}
}
template <class R, class CppInt>
-inline void check_in_range(const CppInt& /*val*/, const mpl::int_<unchecked>&) BOOST_NOEXCEPT {}
+inline BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& /*val*/, const std::integral_constant<int, unchecked>&) noexcept {}
-inline void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {}
-inline void check_is_negative(const mpl::false_&)
+inline BOOST_MP_CXX14_CONSTEXPR void check_is_negative(const std::integral_constant<bool, true>&) noexcept {}
+inline void check_is_negative(const std::integral_constant<bool, false>&)
{
- BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
}
template <class Integer>
-inline Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT
+inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const std::integral_constant<bool, true>&) noexcept
{
return -i;
}
template <class Integer>
-inline Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT
+inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const std::integral_constant<bool, false>&) noexcept
{
- return ~(i-1);
+ return ~(i - 1);
}
-template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
- eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend)
+template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
+eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend)
{
- typedef mpl::int_<Checked1> checked_type;
+ using checked_type = std::integral_constant<int, Checked1>;
check_in_range<R>(backend, checked_type());
- if (std::numeric_limits<R>::digits < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
+ BOOST_IF_CONSTEXPR(numeric_limits_workaround<R>::digits < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
{
- if ((backend.sign() && std::numeric_limits<R>::is_signed) && (1 + static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0]))
+ if ((backend.sign() && boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) && (1 + static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0]))
{
- *result = (std::numeric_limits<R>::min)();
+ *result = (numeric_limits_workaround<R>::min)();
return;
}
- else if (!backend.sign() && static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0])
+ else if (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value && !backend.sign() && static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0])
{
- *result = (std::numeric_limits<R>::max)();
+ *result = (numeric_limits_workaround<R>::max)();
return;
}
else
@@ -83,11 +127,13 @@ inline typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int
}
else
*result = static_cast<R>(backend.limbs()[0]);
- unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- unsigned i = 1;
- if (std::numeric_limits<R>::digits > cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
+
+ BOOST_IF_CONSTEXPR(numeric_limits_workaround<R>::digits > cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
{
- while ((i < backend.size()) && (shift < static_cast<unsigned>(std::numeric_limits<R>::digits - cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)))
+ std::size_t shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ std::size_t i = 1u;
+
+ while ((i < backend.size()) && (shift < static_cast<unsigned>(numeric_limits_workaround<R>::digits - cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)))
{
*result += static_cast<R>(backend.limbs()[i]) << shift;
shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
@@ -98,19 +144,21 @@ inline typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int
//
if (i < backend.size())
{
- static const limb_type mask = std::numeric_limits<R>::digits - shift == cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits ?
- ~static_cast<limb_type>(0) : (static_cast<limb_type>(1u) << (std::numeric_limits<R>::digits - shift)) - 1;
- *result += (static_cast<R>(backend.limbs()[i]) & mask) << shift;
- if ((static_cast<R>(backend.limbs()[i]) & static_cast<limb_type>(~mask)) || (i + 1 < backend.size()))
+ const limb_type mask = ((numeric_limits_workaround<R>::digits - shift) == cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits) ? ~static_cast<limb_type>(0) : static_cast<limb_type>(static_cast<limb_type>(1u) << (numeric_limits_workaround<R>::digits - shift)) - 1u;
+ const limb_type limb_at_index_masked = static_cast<limb_type>(backend.limbs()[i] & mask);
+
+ *result = static_cast<R>(*result + static_cast<R>(static_cast<R>(limb_at_index_masked) << shift));
+
+ if ((backend.limbs()[i] & static_cast<limb_type>(~mask)) || (i + 1 < backend.size()))
{
// Overflow:
if (backend.sign())
{
- check_is_negative(boost::is_signed<R>());
- *result = (std::numeric_limits<R>::min)();
+ check_is_negative(boost::multiprecision::detail::is_signed<R>());
+ *result = (numeric_limits_workaround<R>::min)();
}
- else
- *result = (std::numeric_limits<R>::max)();
+ else if (boost::multiprecision::detail::is_signed<R>::value)
+ *result = (numeric_limits_workaround<R>::max)();
return;
}
}
@@ -120,51 +168,119 @@ inline typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int
// Overflow:
if (backend.sign())
{
- check_is_negative(boost::is_signed<R>());
- *result = (std::numeric_limits<R>::min)();
+ check_is_negative(boost::multiprecision::detail::is_signed<R>());
+ *result = (numeric_limits_workaround<R>::min)();
}
- else
- *result = (std::numeric_limits<R>::max)();
+ else if (boost::multiprecision::detail::is_signed<R>::value)
+ *result = (numeric_limits_workaround<R>::max)();
return;
}
- if(backend.sign())
+ if (backend.sign())
{
- check_is_negative(boost::is_signed<R>());
- *result = negate_integer(*result, boost::is_signed<R>());
+ check_is_negative(std::integral_constant<bool, boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value>());
+ *result = negate_integer(*result, std::integral_constant<bool, boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value>());
}
}
-template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<is_floating_point<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
- eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_MP_NOEXCEPT_IF(is_arithmetic<R>::value)
+template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_floating_point<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
+eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) noexcept(boost::multiprecision::detail::is_arithmetic<R>::value)
{
- typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
- unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- *result = static_cast<R>(*p);
- for(unsigned i = 1; i < backend.size(); ++i)
+ BOOST_MP_FLOAT128_USING using std::ldexp;
+ if (eval_is_zero(backend))
+ {
+ *result = 0.0f;
+ return;
+ }
+
+#ifdef BOOST_HAS_FLOAT128
+ std::ptrdiff_t bits_to_keep = static_cast<std::ptrdiff_t>(std::is_same<R, float128_type>::value ? 113 : std::numeric_limits<R>::digits);
+#else
+ std::ptrdiff_t bits_to_keep = static_cast<std::ptrdiff_t>(std::numeric_limits<R>::digits);
+#endif
+ std::ptrdiff_t bits = static_cast<std::ptrdiff_t>(eval_msb_imp(backend) + 1);
+
+ if (bits > bits_to_keep)
+ {
+ // Extract the bits we need, and then manually round the result:
+ *result = 0.0f;
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
+ limb_type mask = ~static_cast<limb_type>(0u);
+ std::size_t index = backend.size() - 1;
+ std::size_t shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits * index;
+ while (bits_to_keep > 0)
+ {
+ if (bits_to_keep < (std::ptrdiff_t)cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
+ {
+ if(index != backend.size() - 1)
+ {
+ const std::ptrdiff_t left_shift_amount = static_cast<std::ptrdiff_t>(static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits) - bits_to_keep);
+
+ mask <<= left_shift_amount;
+ }
+ else
+ {
+ std::ptrdiff_t bits_in_first_limb = static_cast<std::ptrdiff_t>(bits % static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits));
+ if (bits_in_first_limb == 0)
+ bits_in_first_limb = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ if (bits_in_first_limb > bits_to_keep)
+ mask <<= bits_in_first_limb - bits_to_keep;
+ }
+ }
+ *result += ldexp(static_cast<R>(p[index] & mask), static_cast<int>(shift));
+ shift -= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+
+ const bool bits_has_non_zero_remainder = (bits % static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits) != 0);
+
+ bits_to_keep -= ((index == backend.size() - 1) && bits_has_non_zero_remainder)
+ ? bits % static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
+ : static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
+ --index;
+ }
+ // Perform rounding:
+ bits -= 1 + std::numeric_limits<R>::digits;
+ if (eval_bit_test(backend, static_cast<unsigned>(bits)))
+ {
+ if ((eval_lsb_imp(backend) < static_cast<std::size_t>(bits)) || eval_bit_test(backend, static_cast<std::size_t>(bits + 1)))
+ {
+ #ifdef BOOST_MP_MATH_AVAILABLE
+ *result = boost::math::float_next(*result);
+ #else
+ *result = std::nextafter(*result, *result * 2);
+ #endif
+ }
+ }
+ }
+ else
{
- *result += static_cast<R>(std::ldexp(static_cast<long double>(p[i]), shift));
- shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
+ std::size_t shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ *result = static_cast<R>(*p);
+ for (std::size_t i = 1; i < backend.size(); ++i)
+ {
+ *result += static_cast<R>(ldexp(static_cast<long double>(p[i]), static_cast<int>(shift)));
+ shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ }
}
- if(backend.sign())
+ if (backend.sign())
*result = -*result;
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
- eval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
+eval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept
{
return (val.size() == 1) && (val.limbs()[0] == 0);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, int>::type
- eval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, int>::type
+eval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept
{
return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1;
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_abs(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_abs(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
result = val;
result.sign(false);
@@ -173,39 +289,45 @@ BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<Mi
//
// Get the location of the least-significant-bit:
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
- eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
+eval_lsb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& 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()))
+ std::size_t 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]);
+ std::size_t result = boost::multiprecision::detail::find_lsb(a.limbs()[index]);
return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
+eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
+{
+ using default_ops::eval_get_sign;
+ if (eval_get_sign(a) == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
+ }
+ if (a.sign())
+ {
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
+ }
+ return eval_lsb_imp(a);
+}
+
//
// Get the location of the most-significant-bit:
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
{
//
@@ -214,118 +336,131 @@ eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allo
return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
- eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
+eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
{
using default_ops::eval_get_sign;
- if(eval_get_sign(a) == 0)
+ if (eval_get_sign(a) == 0)
{
- BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
}
- if(a.sign())
+ if (a.sign())
{
- BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
}
return eval_msb_imp(a);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
- eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
+#ifdef BOOST_GCC
+//
+// We really shouldn't need to be disabling this warning, but it really does appear to be
+// spurious. The warning appears only when in release mode, and asserts are on.
+//
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
+eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index) noexcept
{
- unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
- if(offset >= val.size())
+ std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::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 <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
+#ifdef BOOST_GCC
+#pragma GCC diagnostic pop
+#endif
+
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index)
{
- unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
- if(offset >= val.size())
+ std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
+ if (offset >= val.size())
{
- unsigned os = val.size();
+ std::size_t os = val.size();
val.resize(offset + 1, offset + 1);
- if(offset >= val.size())
- return; // fixed precision overflow
- for(unsigned i = os; i <= offset; ++i)
+ if (offset >= val.size())
+ return; // fixed precision overflow
+ for (std::size_t i = os; i <= offset; ++i)
val.limbs()[i] = 0;
}
val.limbs()[offset] |= mask;
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index) noexcept
{
- unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
- if(offset >= val.size())
+ std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::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 <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index)
{
- unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
- if(offset >= val.size())
+ std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
+ limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
+ if (offset >= val.size())
{
- unsigned os = val.size();
+ std::size_t os = val.size();
val.resize(offset + 1, offset + 1);
- if(offset >= val.size())
- return; // fixed precision overflow
- for(unsigned i = os; i <= offset; ++i)
+ if (offset >= val.size())
+ return; // fixed precision overflow
+ for (std::size_t i = os; i <= offset; ++i)
val.limbs()[i] = 0;
}
val.limbs()[offset] ^= mask;
val.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_qr(
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& y,
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_qr(
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& y,
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
divide_unsigned_helper(&q, x, y, r);
q.sign(x.sign() != y.sign());
r.sign(x.sign());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_qr(
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
- limb_type y,
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_qr(
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
+ limb_type y,
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
divide_unsigned_helper(&q, x, y, r);
q.sign(x.sign());
r.sign(x.sign());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class U>
-inline typename enable_if_c<is_integral<U>::value>::type eval_qr(
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
- U y,
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class U>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<U>::value>::type eval_qr(
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
+ U y,
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
using default_ops::eval_qr;
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
@@ -333,332 +468,893 @@ inline typename enable_if_c<is_integral<U>::value>::type eval_qr(
eval_qr(x, t, q, r);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
-inline typename enable_if_c<is_unsigned<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
- eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
+eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, Integer mod)
{
- if((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits<limb_type>::max)()))
+ BOOST_IF_CONSTEXPR (sizeof(Integer) <= sizeof(limb_type))
{
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> d;
- divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), x, static_cast<limb_type>(val), d);
- return d.limbs()[0];
+ if (mod <= (std::numeric_limits<limb_type>::max)())
+ {
+ const std::ptrdiff_t n = a.size();
+ const double_limb_type two_n_mod = static_cast<limb_type>(1u) + (~static_cast<limb_type>(0u) - mod) % mod;
+ limb_type res = a.limbs()[n - 1] % mod;
+
+ for (std::ptrdiff_t i = n - 2; i >= 0; --i)
+ res = static_cast<limb_type>((res * two_n_mod + a.limbs()[i]) % mod);
+ return res;
+ }
+ else
+ return default_ops::eval_integer_modulus(a, mod);
}
else
{
- return default_ops::eval_integer_modulus(x, val);
+ return default_ops::eval_integer_modulus(a, mod);
}
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_signed<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
- eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
+eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& 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)
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_type eval_gcd(limb_type u, limb_type v)
{
+ // boundary cases
+ if (!u || !v)
+ return u | v;
+#if (defined(__cpp_lib_gcd_lcm) && (__cpp_lib_gcd_lcm >= 201606L))
+ return std::gcd(u, v);
+#else
+ std::size_t shift = boost::multiprecision::detail::find_lsb(u | v);
+ u >>= boost::multiprecision::detail::find_lsb(u);
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;
+ if (u > v)
+ std_constexpr::swap(u, v);
+ v -= u;
+ } while (v);
+ return u << shift;
+#endif
}
-inline double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type v)
+inline BOOST_MP_CXX14_CONSTEXPR double_limb_type eval_gcd(double_limb_type u, double_limb_type v)
{
+#if (defined(__cpp_lib_gcd_lcm) && (__cpp_lib_gcd_lcm >= 201606L)) && (!defined(BOOST_HAS_INT128) || !defined(__STRICT_ANSI__))
+ return std::gcd(u, v);
+#else
+ if (u == 0)
+ return v;
+
+ std::size_t shift = boost::multiprecision::detail::find_lsb(u | v);
+ u >>= boost::multiprecision::detail::find_lsb(u);
do
{
- if(u > v)
- std::swap(u, v);
- if(u == v)
- break;
- if(v <= ~static_cast<limb_type>(0))
- {
- u = integer_gcd_reduce(static_cast<limb_type>(v), static_cast<limb_type>(u));
- break;
- }
+ v >>= boost::multiprecision::detail::find_lsb(v);
+ if (u > v)
+ std_constexpr::swap(u, v);
v -= u;
-#ifdef __MSVC_RUNTIME_CHECKS
- while((v & 1u) == 0)
-#else
- while((static_cast<unsigned>(v) & 1u) == 0)
+ } while (v);
+ return u << shift;
#endif
- v >>= 1;
- } while(true);
- return u;
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_gcd(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
- limb_type v)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_gcd(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
+ limb_type b)
{
- using default_ops::eval_lsb;
- using default_ops::eval_is_zero;
- using default_ops::eval_get_sign;
-
- int shift;
+ int s = eval_get_sign(a);
+ if (!b || !s)
+ {
+ result = a;
+ *result.limbs() |= b;
+ }
+ else
+ {
+ eval_modulus(result, a, b);
+ limb_type& res = *result.limbs();
+ res = eval_gcd(res, b);
+ }
+ result.sign(false);
+}
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a);
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_gcd(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
+ double_limb_type b)
+{
+ int s = eval_get_sign(a);
+ if (!b || !s)
+ {
+ if (!s)
+ result = b;
+ else
+ result = a;
+ return;
+ }
+ double_limb_type res = 0;
+ if(a.sign() == 0)
+ res = eval_integer_modulus(a, b);
+ else
+ {
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(a);
+ t.negate();
+ res = eval_integer_modulus(t, b);
+ }
+ res = eval_gcd(res, b);
+ result = res;
+ result.sign(false);
+}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_gcd(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
+ signed_double_limb_type v)
+{
+ eval_gcd(result, a, static_cast<double_limb_type>(v < 0 ? -v : v));
+}
+//
+// These 2 overloads take care of gcd against an (unsigned) short etc:
+//
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_gcd(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
+ const Integer& v)
+{
+ eval_gcd(result, a, static_cast<limb_type>(v));
+}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_gcd(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
+ const Integer& v)
+{
+ eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));
+}
+//
+// What follows is Lehmer's GCD algorithm:
+// Essentially this uses the leading digit(s) of U and V
+// only to run a "simulated" Euclid algorithm. It stops
+// when the calculated quotient differs from what would have been
+// the true quotient. At that point the cosequences are used to
+// calculate the new U and V. A nice lucid description appears
+// in "An Analysis of Lehmer's Euclidean GCD Algorithm",
+// by Jonathan Sorenson. https://www.researchgate.net/publication/2424634_An_Analysis_of_Lehmer%27s_Euclidean_GCD_Algorithm
+// DOI: 10.1145/220346.220378.
+//
+// There are two versions of this algorithm here, and both are "double digit"
+// variations: which is to say if there are k bits per limb, then they extract
+// 2k bits into a double_limb_type and then run the algorithm on that. The first
+// version is a straightforward version of the algorithm, and is designed for
+// situations where double_limb_type is a native integer (for example where
+// limb_type is a 32-bit integer on a 64-bit machine). For 32-bit limbs it
+// reduces the size of U by about 30 bits per call. The second is a more complex
+// version for situations where double_limb_type is a synthetic type: for example
+// __int128. For 64 bit limbs it reduces the size of U by about 62 bits per call.
+//
+// The complexity of the algorithm given by Sorenson is roughly O(ln^2(N)) for
+// two N bit numbers.
+//
+// The original double-digit version of the algorithm is described in:
+//
+// "A Double Digit Lehmer-Euclid Algorithm for Finding the GCD of Long Integers",
+// Tudor Jebelean, J Symbolic Computation, 1995 (19), 145.
+//
+#ifndef BOOST_HAS_INT128
+//
+// When double_limb_type is a native integer type then we should just use it and not worry about the consequences.
+// This can eliminate approximately a full limb with each call.
+//
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Storage>
+void eval_gcd_lehmer(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& U, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& V, std::size_t lu, Storage& storage)
+{
+ //
+ // Extract the leading 2 * bits_per_limb bits from U and V:
+ //
+ std::size_t h = lu % bits_per_limb;
+ double_limb_type u = (static_cast<double_limb_type>((U.limbs()[U.size() - 1])) << bits_per_limb) | U.limbs()[U.size() - 2];
+ double_limb_type v = (static_cast<double_limb_type>((V.size() < U.size() ? 0 : V.limbs()[V.size() - 1])) << bits_per_limb) | V.limbs()[U.size() - 2];
+ if (h)
+ {
+ u <<= bits_per_limb - h;
+ u |= U.limbs()[U.size() - 3] >> h;
+ v <<= bits_per_limb - h;
+ v |= V.limbs()[U.size() - 3] >> h;
+ }
+ //
+ // Co-sequences x an y: we need only the last 3 values of these,
+ // the first 2 values are known correct, the third gets checked
+ // in each loop operation, and we terminate when they go wrong.
+ //
+ // x[i+0] is positive for even i.
+ // y[i+0] is positive for odd i.
+ //
+ // However we track only absolute values here:
+ //
+ double_limb_type x[3] = {1, 0};
+ double_limb_type y[3] = {0, 1};
+ std::size_t i = 0;
- int s = eval_get_sign(u);
+#ifdef BOOST_MP_GCD_DEBUG
+ cpp_int UU, VV;
+ UU = U;
+ VV = V;
+#endif
- /* GCD(0,x) := x */
- if(s < 0)
+ while (true)
{
- u.negate();
+ double_limb_type q = u / v;
+ x[2] = x[0] + q * x[1];
+ y[2] = y[0] + q * y[1];
+ double_limb_type tu = u;
+ u = v;
+ v = tu - q * v;
+ ++i;
+ //
+ // We must make sure that y[2] occupies a single limb otherwise
+ // the multiprecision multiplications below would be much more expensive.
+ // This can sometimes lose us one iteration, but is worth it for improved
+ // calculation efficiency.
+ //
+ if (y[2] >> bits_per_limb)
+ break;
+ //
+ // These are Jebelean's exact termination conditions:
+ //
+ if ((i & 1u) == 0)
+ {
+ BOOST_MP_ASSERT(u > v);
+ if ((v < x[2]) || ((u - v) < (y[2] + y[1])))
+ break;
+ }
+ else
+ {
+ BOOST_MP_ASSERT(u > v);
+ if ((v < y[2]) || ((u - v) < (x[2] + x[1])))
+ break;
+ }
+#ifdef BOOST_MP_GCD_DEBUG
+ BOOST_MP_ASSERT(q == UU / VV);
+ UU %= VV;
+ UU.swap(VV);
+#endif
+ x[0] = x[1];
+ x[1] = x[2];
+ y[0] = y[1];
+ y[1] = y[2];
}
- else if(s == 0)
+ if (i == 1)
{
- result = v;
+ // No change to U and V we've stalled!
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
+ eval_modulus(t, U, V);
+ U.swap(V);
+ V.swap(t);
return;
}
- if(v == 0)
+ //
+ // Update U and V.
+ // We have:
+ //
+ // U = x[0]U + y[0]V and
+ // V = x[1]U + y[1]V.
+ //
+ // But since we track only absolute values of x and y
+ // we have to take account of the implied signs and perform
+ // the appropriate subtraction depending on the whether i is
+ // even or odd:
+ //
+ std::size_t ts = U.size() + 1;
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t1(storage, ts), t2(storage, ts), t3(storage, ts);
+ eval_multiply(t1, U, static_cast<limb_type>(x[0]));
+ eval_multiply(t2, V, static_cast<limb_type>(y[0]));
+ eval_multiply(t3, U, static_cast<limb_type>(x[1]));
+ if ((i & 1u) == 0)
{
- result = u;
- return;
+ if (x[0] == 0)
+ U = t2;
+ else
+ {
+ BOOST_MP_ASSERT(t2.compare(t1) >= 0);
+ eval_subtract(U, t2, t1);
+ BOOST_MP_ASSERT(U.sign() == false);
+ }
+ }
+ else
+ {
+ BOOST_MP_ASSERT(t1.compare(t2) >= 0);
+ eval_subtract(U, t1, t2);
+ BOOST_MP_ASSERT(U.sign() == false);
}
+ eval_multiply(t2, V, static_cast<limb_type>(y[1]));
+ if (i & 1u)
+ {
+ if (x[1] == 0)
+ V = t2;
+ else
+ {
+ BOOST_MP_ASSERT(t2.compare(t3) >= 0);
+ eval_subtract(V, t2, t3);
+ BOOST_MP_ASSERT(V.sign() == false);
+ }
+ }
+ else
+ {
+ BOOST_MP_ASSERT(t3.compare(t2) >= 0);
+ eval_subtract(V, t3, t2);
+ BOOST_MP_ASSERT(V.sign() == false);
+ }
+ BOOST_MP_ASSERT(U.compare(V) >= 0);
+ BOOST_MP_ASSERT(lu > eval_msb(U));
+#ifdef BOOST_MP_GCD_DEBUG
- /* Let shift := lg K, where K is the greatest power of 2
- dividing both u and v. */
+ BOOST_MP_ASSERT(UU == U);
+ BOOST_MP_ASSERT(VV == 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;
+ extern std::size_t total_lehmer_gcd_calls;
+ extern std::size_t total_lehmer_gcd_bits_saved;
+ extern std::size_t total_lehmer_gcd_cycles;
- do
+ ++total_lehmer_gcd_calls;
+ total_lehmer_gcd_bits_saved += lu - eval_msb(U);
+ total_lehmer_gcd_cycles += i;
+#endif
+ if (lu < 2048)
{
- /* 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)
+ //
+ // Since we have stripped all common powers of 2 from U and V at the start
+ // if either are even at this point, we can remove stray powers of 2 now.
+ // Note that it is not possible for *both* U and V to be even at this point.
+ //
+ // This has an adverse effect on performance for high bit counts, but has
+ // a significant positive effect for smaller counts.
+ //
+ if ((U.limbs()[0] & 1u) == 0)
{
- if(u.size() == 1)
- v = integer_gcd_reduce(*u.limbs(), v);
- else
- {
- double_limb_type i;
- i = u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
- v = static_cast<limb_type>(integer_gcd_reduce(i, static_cast<double_limb_type>(v)));
- }
- break;
+ eval_right_shift(U, eval_lsb(U));
+ if (U.compare(V) < 0)
+ U.swap(V);
}
- eval_subtract(u, v);
- us = eval_lsb(u);
- eval_right_shift(u, us);
- }
- while(true);
-
- result = v;
- eval_left_shift(result, shift);
+ else if ((V.limbs()[0] & 1u) == 0)
+ {
+ eval_right_shift(V, eval_lsb(V));
+ }
+ }
+ storage.deallocate(ts * 3);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
-inline typename enable_if_c<is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_gcd(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
- const Integer& v)
+
+#else
+//
+// This branch is taken when double_limb_type is a synthetic type with no native hardware support.
+// For example __int128. The assumption is that add/subtract/multiply of double_limb_type are efficient,
+// but that division is very slow.
+//
+// We begin with a specialized routine for division.
+// We know that most of the time this is called the result will be 1.
+// For small limb counts, this almost doubles the performance of Lehmer's routine!
+//
+BOOST_FORCEINLINE void divide_subtract(double_limb_type& q, double_limb_type& u, const double_limb_type& v)
{
- eval_gcd(result, a, static_cast<limb_type>(v));
+ BOOST_MP_ASSERT(q == 1); // precondition on entry.
+ u -= v;
+ while (u >= v)
+ {
+ u -= v;
+ if (++q > 30)
+ {
+ double_limb_type t = u / v;
+ u -= t * v;
+ q += t;
+ }
+ }
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
-inline typename enable_if_c<is_signed<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_gcd(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
- const Integer& v)
+
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Storage>
+void eval_gcd_lehmer(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& U, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& V, std::size_t lu, Storage& storage)
{
- eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));
+ //
+ // Extract the leading 2*bits_per_limb bits from U and V:
+ //
+ std::size_t h = lu % bits_per_limb;
+ double_limb_type u, v;
+ if (h)
+ {
+ u = (static_cast<double_limb_type>((U.limbs()[U.size() - 1])) << bits_per_limb) | U.limbs()[U.size() - 2];
+ v = (static_cast<double_limb_type>((V.size() < U.size() ? 0 : V.limbs()[V.size() - 1])) << bits_per_limb) | V.limbs()[U.size() - 2];
+ u <<= bits_per_limb - h;
+ u |= U.limbs()[U.size() - 3] >> h;
+ v <<= bits_per_limb - h;
+ v |= V.limbs()[U.size() - 3] >> h;
+ }
+ else
+ {
+ u = (static_cast<double_limb_type>(U.limbs()[U.size() - 1]) << bits_per_limb) | U.limbs()[U.size() - 2];
+ v = (static_cast<double_limb_type>(V.limbs()[U.size() - 1]) << bits_per_limb) | V.limbs()[U.size() - 2];
+ }
+ //
+ // Cosequences are stored as limb_types, we take care not to overflow these:
+ //
+ // x[i+0] is positive for even i.
+ // y[i+0] is positive for odd i.
+ //
+ // However we track only absolute values here:
+ //
+ limb_type x[3] = { 1, 0 };
+ limb_type y[3] = { 0, 1 };
+ std::size_t i = 0;
+
+#ifdef BOOST_MP_GCD_DEBUG
+ cpp_int UU, VV;
+ UU = U;
+ VV = V;
+#endif
+ //
+ // We begine by running a single digit version of Lehmer's algorithm, we still have
+ // to track u and v at double precision, but this adds only a tiny performance penalty.
+ // What we gain is fast division, and fast termination testing.
+ // When you see static_cast<limb_type>(u >> bits_per_limb) here, this is really just
+ // a direct access to the upper bits_per_limb of the double limb type. For __int128
+ // this is simple a load of the upper 64 bits and the "shift" is optimised away.
+ //
+ double_limb_type old_u, old_v;
+ while (true)
+ {
+ limb_type q = static_cast<limb_type>(u >> bits_per_limb) / static_cast<limb_type>(v >> bits_per_limb);
+ x[2] = x[0] + q * x[1];
+ y[2] = y[0] + q * y[1];
+ double_limb_type tu = u;
+ old_u = u;
+ old_v = v;
+ u = v;
+ double_limb_type t = q * v;
+ if (tu < t)
+ {
+ ++i;
+ break;
+ }
+ v = tu - t;
+ ++i;
+ BOOST_MP_ASSERT((u <= v) || (t / q == old_v));
+ if (u <= v)
+ {
+ // We've gone terribly wrong, probably numeric overflow:
+ break;
+ }
+ if ((i & 1u) == 0)
+ {
+ if ((static_cast<limb_type>(v >> bits_per_limb) < x[2]) || ((static_cast<limb_type>(u >> bits_per_limb) - static_cast<limb_type>(v >> bits_per_limb)) < (y[2] + y[1])))
+ break;
+ }
+ else
+ {
+ if ((static_cast<limb_type>(v >> bits_per_limb) < y[2]) || ((static_cast<limb_type>(u >> bits_per_limb) - static_cast<limb_type>(v >> bits_per_limb)) < (x[2] + x[1])))
+ break;
+ }
+#ifdef BOOST_MP_GCD_DEBUG
+ BOOST_MP_ASSERT(q == UU / VV);
+ UU %= VV;
+ UU.swap(VV);
+#endif
+ x[0] = x[1];
+ x[1] = x[2];
+ y[0] = y[1];
+ y[1] = y[2];
+ }
+ //
+ // We get here when the single digit algorithm has gone wrong, back up i, u and v:
+ //
+ --i;
+ u = old_u;
+ v = old_v;
+ //
+ // Now run the full double-digit algorithm:
+ //
+ while (true)
+ {
+ double_limb_type q = 1u;
+ double_limb_type tt = u;
+ divide_subtract(q, u, v);
+ std::swap(u, v);
+ tt = y[0] + q * static_cast<double_limb_type>(y[1]);
+ //
+ // If calculation of y[2] would overflow a single limb, then we *must* terminate.
+ // Note that x[2] < y[2] so there is no need to check that as well:
+ //
+ if (tt >> bits_per_limb)
+ {
+ ++i;
+ break;
+ }
+ x[2] = static_cast<limb_type>(x[0] + static_cast<double_limb_type>(q * x[1]));
+ y[2] = static_cast<limb_type>(tt);
+ ++i;
+ if ((i & 1u) == 0)
+ {
+ BOOST_MP_ASSERT(u > v);
+ if ((v < x[2]) || ((u - v) < (static_cast<double_limb_type>(y[2]) + y[1])))
+ break;
+ }
+ else
+ {
+ BOOST_MP_ASSERT(u > v);
+ if ((v < y[2]) || ((u - v) < (static_cast<double_limb_type>(x[2]) + x[1])))
+ break;
+ }
+#ifdef BOOST_MP_GCD_DEBUG
+ BOOST_MP_ASSERT(q == UU / VV);
+ UU %= VV;
+ UU.swap(VV);
+#endif
+ x[0] = x[1];
+ x[1] = x[2];
+ y[0] = y[1];
+ y[1] = y[2];
+ }
+ if (i == 1)
+ {
+ // No change to U and V we've stalled!
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
+ eval_modulus(t, U, V);
+ U.swap(V);
+ V.swap(t);
+ return;
+ }
+ //
+ // Update U and V.
+ // We have:
+ //
+ // U = x[0]U + y[0]V and
+ // V = x[1]U + y[1]V.
+ //
+ // But since we track only absolute values of x and y
+ // we have to take account of the implied signs and perform
+ // the appropriate subtraction depending on the whether i is
+ // even or odd:
+ //
+ std::size_t ts = U.size() + 1;
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t1(storage, ts), t2(storage, ts), t3(storage, ts);
+ eval_multiply(t1, U, x[0]);
+ eval_multiply(t2, V, y[0]);
+ eval_multiply(t3, U, x[1]);
+ if ((i & 1u) == 0)
+ {
+ if (x[0] == 0)
+ U = t2;
+ else
+ {
+ BOOST_MP_ASSERT(t2.compare(t1) >= 0);
+ eval_subtract(U, t2, t1);
+ BOOST_MP_ASSERT(U.sign() == false);
+ }
+ }
+ else
+ {
+ BOOST_MP_ASSERT(t1.compare(t2) >= 0);
+ eval_subtract(U, t1, t2);
+ BOOST_MP_ASSERT(U.sign() == false);
+ }
+ eval_multiply(t2, V, y[1]);
+ if (i & 1u)
+ {
+ if (x[1] == 0)
+ V = t2;
+ else
+ {
+ BOOST_MP_ASSERT(t2.compare(t3) >= 0);
+ eval_subtract(V, t2, t3);
+ BOOST_MP_ASSERT(V.sign() == false);
+ }
+ }
+ else
+ {
+ BOOST_MP_ASSERT(t3.compare(t2) >= 0);
+ eval_subtract(V, t3, t2);
+ BOOST_MP_ASSERT(V.sign() == false);
+ }
+ BOOST_MP_ASSERT(U.compare(V) >= 0);
+ BOOST_MP_ASSERT(lu > eval_msb(U));
+#ifdef BOOST_MP_GCD_DEBUG
+
+ BOOST_MP_ASSERT(UU == U);
+ BOOST_MP_ASSERT(VV == V);
+
+ extern std::size_t total_lehmer_gcd_calls;
+ extern std::size_t total_lehmer_gcd_bits_saved;
+ extern std::size_t total_lehmer_gcd_cycles;
+
+ ++total_lehmer_gcd_calls;
+ total_lehmer_gcd_bits_saved += lu - eval_msb(U);
+ total_lehmer_gcd_cycles += i;
+#endif
+ if (lu < 2048)
+ {
+ //
+ // Since we have stripped all common powers of 2 from U and V at the start
+ // if either are even at this point, we can remove stray powers of 2 now.
+ // Note that it is not possible for *both* U and V to be even at this point.
+ //
+ // This has an adverse effect on performance for high bit counts, but has
+ // a significant positive effect for smaller counts.
+ //
+ if ((U.limbs()[0] & 1u) == 0)
+ {
+ eval_right_shift(U, eval_lsb(U));
+ if (U.compare(V) < 0)
+ U.swap(V);
+ }
+ else if ((V.limbs()[0] & 1u) == 0)
+ {
+ eval_right_shift(V, eval_lsb(V));
+ }
+ }
+ storage.deallocate(ts * 3);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_gcd(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b)
+#endif
+
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_gcd(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b)
{
- using default_ops::eval_lsb;
- using default_ops::eval_is_zero;
using default_ops::eval_get_sign;
+ using default_ops::eval_is_zero;
+ using default_ops::eval_lsb;
- if(a.size() == 1)
+ if (a.size() == 1)
{
eval_gcd(result, b, *a.limbs());
return;
}
- if(b.size() == 1)
+ if (b.size() == 1)
{
eval_gcd(result, a, *b.limbs());
return;
}
+ std::size_t temp_size = (std::max)(a.size(), b.size()) + 1;
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::scoped_shared_storage storage(a, temp_size * 6);
- int shift;
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> U(storage, temp_size);
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> V(storage, temp_size);
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(storage, temp_size);
+ U = a;
+ V = b;
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a), v(b);
-
- int s = eval_get_sign(u);
+ int s = eval_get_sign(U);
/* GCD(0,x) := x */
- if(s < 0)
+ if (s < 0)
{
- u.negate();
+ U.negate();
}
- else if(s == 0)
+ else if (s == 0)
{
- result = v;
+ result = V;
return;
}
- s = eval_get_sign(v);
- if(s < 0)
+ s = eval_get_sign(V);
+ if (s < 0)
{
- v.negate();
+ V.negate();
}
- else if(s == 0)
+ else if (s == 0)
{
- result = u;
+ result = U;
return;
}
+ //
+ // Remove common factors of 2:
+ //
+ std::size_t us = eval_lsb(U);
+ std::size_t vs = eval_lsb(V);
+ std::size_t shift = (std::min)(us, vs);
+ if (us)
+ eval_right_shift(U, us);
+ if (vs)
+ eval_right_shift(V, vs);
- /* 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);
+ if (U.compare(V) < 0)
+ U.swap(V);
- do
+ while (!eval_is_zero(V))
{
- /* 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 (U.size() <= 2)
{
- if(v.size() == 1)
- u = integer_gcd_reduce(*v.limbs(), *u.limbs());
+ //
+ // Special case: if V has no more than 2 limbs
+ // then we can reduce U and V to a pair of integers and perform
+ // direct integer gcd:
+ //
+ if (U.size() == 1)
+ U = eval_gcd(*V.limbs(), *U.limbs());
else
{
- double_limb_type i, j;
- i = v.limbs()[0] | (static_cast<double_limb_type>(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
- j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
- u = integer_gcd_reduce(i, j);
+ double_limb_type i = U.limbs()[0] | (static_cast<double_limb_type>(U.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
+ double_limb_type j = (V.size() == 1) ? *V.limbs() : V.limbs()[0] | (static_cast<double_limb_type>(V.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
+ U = eval_gcd(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);
+ std::size_t lu = eval_msb(U) + 1;
+ std::size_t lv = eval_msb(V) + 1;
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (!BOOST_MP_IS_CONST_EVALUATED(lu) && (lu - lv <= bits_per_limb / 2))
+#else
+ if (lu - lv <= bits_per_limb / 2)
+#endif
+ {
+ eval_gcd_lehmer(U, V, lu, storage);
+ }
+ else
+ {
+ eval_modulus(t, U, V);
+ U.swap(V);
+ V.swap(t);
+ }
+ }
+ result = U;
+ if (shift)
+ eval_left_shift(result, shift);
}
//
// Now again for trivial backends:
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_gcd(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_NOEXCEPT
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_gcd(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) noexcept
{
- *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs());
+ *result.limbs() = boost::multiprecision::detail::constexpr_gcd(*a.limbs(), *b.limbs());
+ result.sign(false);
}
// This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version:
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::type
- eval_lcm(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::type
+eval_lcm(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- *result.limbs() = boost::integer::lcm(*a.limbs(), *b.limbs());
+ *result.limbs() = boost::multiprecision::detail::constexpr_lcm(*a.limbs(), *b.limbs());
result.normalize(); // result may overflow the specified number of bits
+ result.sign(false);
}
-inline void conversion_overflow(const mpl::int_<checked>&)
+inline void conversion_overflow(const std::integral_constant<int, checked>&)
{
- BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));
}
-inline void conversion_overflow(const mpl::int_<unchecked>&){}
+inline BOOST_MP_CXX14_CONSTEXPR void conversion_overflow(const std::integral_constant<int, unchecked>&) {}
-template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
- >::type
- eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
+#if defined(__clang__) && defined(__MINGW32__)
+//
+// clang-11 on Mingw segfaults on conversion of __int128 -> float.
+// See: https://bugs.llvm.org/show_bug.cgi?id=48941
+// These workarounds pass everything through an intermediate uint64_t.
+//
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_same<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, double_limb_type>::value>::type
+eval_convert_to(float* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
{
- typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
- if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
+ float f = static_cast<std::uint64_t>((*val.limbs()) >> 64);
+ *result = std::ldexp(f, 64);
+ *result += static_cast<std::uint64_t>((*val.limbs()));
+ if(val.sign())
+ *result = -*result;
+}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_same<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, double_limb_type>::value>::type
+eval_convert_to(double* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
+{
+ float f = static_cast<std::uint64_t>((*val.limbs()) >> 64);
+ *result = std::ldexp(f, 64);
+ *result += static_cast<std::uint64_t>((*val.limbs()));
+ if(val.sign())
+ *result = -*result;
+}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_same<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, double_limb_type>::value>::type
+eval_convert_to(long double* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
+{
+ float f = static_cast<std::uint64_t>((*val.limbs()) >> 64);
+ *result = std::ldexp(f, 64);
+ *result += static_cast<std::uint64_t>((*val.limbs()));
+ if(val.sign())
+ *result = -*result;
+}
+#endif
+
+template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::type
+eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
+{
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized)
{
- if(val.isneg())
+ using common_type = typename std::common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type;
+
+ if (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)()))
{
- check_is_negative(mpl::bool_<std::numeric_limits<R>::is_signed || (number_category<R>::value == number_kind_floating_point)>());
- if(static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)()))
+ if (val.isneg())
+ {
+ check_is_negative(std::integral_constant < bool, (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) || (number_category<R>::value == number_kind_floating_point) > ());
+ if (static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)()))
+ conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
+ *result = (std::numeric_limits<R>::min)();
+ }
+ else
+ {
conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
- *result = (std::numeric_limits<R>::min)();
+ *result = boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
+ }
}
else
{
- conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
- *result = (std::numeric_limits<R>::max)();
+ *result = static_cast<R>(*val.limbs());
+ if (val.isneg())
+ {
+ check_is_negative(std::integral_constant < bool, (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) || (number_category<R>::value == number_kind_floating_point) > ());
+ *result = negate_integer(*result, std::integral_constant < bool, is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point) > ());
+ }
}
}
else
{
*result = static_cast<R>(*val.limbs());
- if(val.isneg())
+ if (val.isneg())
{
- check_is_negative(mpl::bool_<std::numeric_limits<R>::is_signed || (number_category<R>::value == number_kind_floating_point)>());
- *result = negate_integer(*result, mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>());
+ check_is_negative(std::integral_constant<bool, (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) || (number_category<R>::value == number_kind_floating_point) > ());
+ *result = negate_integer(*result, std::integral_constant<bool, is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point) > ());
}
}
}
-template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
- >::type
- eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
+template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::type
+eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
{
- typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
- if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized)
{
- conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
- *result = (std::numeric_limits<R>::max)();
+ using common_type = typename std::common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type;
+
+ if(static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)()))
+ {
+ conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
+ *result = boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
+ }
+ else
+ *result = static_cast<R>(*val.limbs());
}
else
*result = static_cast<R>(*val.limbs());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
- eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
+eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
{
using default_ops::eval_get_sign;
- if(eval_get_sign(a) == 0)
+ if (eval_get_sign(a) == 0)
{
- BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
}
- if(a.sign())
+ if (a.sign())
{
- BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
}
//
// Find the index of the least significant bit within that limb:
@@ -666,8 +1362,8 @@ inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits
return boost::multiprecision::detail::find_lsb(*a.limbs());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
{
//
@@ -676,31 +1372,31 @@ eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allo
return boost::multiprecision::detail::find_msb(*a.limbs());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
- eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
+eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
{
using default_ops::eval_get_sign;
- if(eval_get_sign(a) == 0)
+ if (eval_get_sign(a) == 0)
{
- BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
}
- if(a.sign())
+ if (a.sign())
{
- BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
}
return eval_msb_imp(a);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept
{
std::size_t result = 0;
- for(unsigned i = 0; i < val.size(); ++i)
+ for (std::size_t i = 0; i < val.size(); ++i)
{
- boost::hash_combine(result, val.limbs()[i]);
+ boost::multiprecision::detail::hash_combine(result, val.limbs()[i]);
}
- boost::hash_combine(result, val.sign());
+ boost::multiprecision::detail::hash_combine(result, val.sign());
return result;
}
@@ -708,6 +1404,42 @@ inline std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType
#pragma warning(pop)
#endif
-}}} // namespaces
+} // Namespace backends
+
+namespace detail {
+
+#ifndef BOOST_MP_STANDALONE
+template <typename T>
+inline BOOST_CXX14_CONSTEXPR T constexpr_gcd(T a, T b) noexcept
+{
+ return boost::integer::gcd(a, b);
+}
+
+template <typename T>
+inline BOOST_CXX14_CONSTEXPR T constexpr_lcm(T a, T b) noexcept
+{
+ return boost::integer::lcm(a, b);
+}
+
+#else
+
+template <typename T>
+inline BOOST_CXX14_CONSTEXPR T constexpr_gcd(T a, T b) noexcept
+{
+ return boost::multiprecision::backends::eval_gcd(a, b);
+}
+
+template <typename T>
+inline BOOST_CXX14_CONSTEXPR T constexpr_lcm(T a, T b) noexcept
+{
+ const T ab_gcd = boost::multiprecision::detail::constexpr_gcd(a, b);
+ return (a * b) / ab_gcd;
+}
+
+#endif // BOOST_MP_STANDALONE
+
+}
+
+}} // Namespace boost::multiprecision
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/multiply.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/multiply.hpp
index 151b2294c7..b72297ab6d 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/multiply.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/multiply.hpp
@@ -1,39 +1,49 @@
///////////////////////////////////////////////////////////////
-// Copyright 2012 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_
+// Copyright 2012-20 John Maddock.
+// Copyright 2019-20 Christopher Kormanyos.
+// Copyright 2019-20 Madhur Chauhan.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
-#ifndef BOOST_MP_CPP_INT_MUL_HPP
-#define BOOST_MP_CPP_INT_MUL_HPP
+#ifndef BOOST_MP_CPP_INT_MULTIPLY_HPP
+#define BOOST_MP_CPP_INT_MULTIPLY_HPP
-namespace boost{ namespace multiprecision{ namespace backends{
+#include <limits>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/endian.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+#include <boost/multiprecision/integer.hpp>
-#ifdef _MSC_VER
+namespace boost { namespace multiprecision { namespace backends {
+
+#ifdef BOOST_MSVC
#pragma warning(push)
-#pragma warning(disable:4127) // conditional expression is constant
+#pragma warning(disable : 4127) // conditional expression is constant
#endif
-
- template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+//
+// Multiplication by a single limb:
+//
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const limb_type& val) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- if(!val)
+ if (!val)
{
result = static_cast<limb_type>(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<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer p = result.limbs();
- typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pe = result.limbs() + result.size();
- typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer pa = a.limbs();
- while(p != pe)
+ double_limb_type carry = 0;
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer p = result.limbs();
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pe = result.limbs() + result.size();
+ typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer pa = a.limbs();
+ while (p != pe)
{
carry += static_cast<double_limb_type>(*pa) * static_cast<double_limb_type>(val);
#ifdef __MSVC_RUNTIME_CHECKS
@@ -44,15 +54,15 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
++p, ++pa;
}
- if(carry)
+ if (carry)
{
- unsigned i = result.size();
+ std::size_t i = result.size();
result.resize(i + 1, i + 1);
- if(result.size() > i)
+ if (result.size() > i)
result.limbs()[i] = static_cast<limb_type>(carry);
}
result.sign(a.sign());
- if(!cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable)
+ if (is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
result.normalize();
}
@@ -61,36 +71,345 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
// for "required" elements could possibly have failed, *and* we have checking enabled.
// This will cause an overflow error inside resize():
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& /*result*/, unsigned /*required*/){}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& /*result*/, std::size_t /*required*/) {}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, class Allocator1>
-inline void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, checked, Allocator1>& result, unsigned required)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, class Allocator1>
+inline BOOST_MP_CXX14_CONSTEXPR void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, checked, Allocator1>& result, std::size_t required)
{
- if(result.size() < required)
+ if (result.size() < required)
result.resize(required, required);
}
+//
+// Minimum number of limbs required for Karatsuba to be worthwhile:
+//
+#ifdef BOOST_MP_KARATSUBA_CUTOFF
+const size_t karatsuba_cutoff = BOOST_MP_KARATSUBA_CUTOFF;
+#else
+const size_t karatsuba_cutoff = 40;
+#endif
+//
+// Core (recursive) Karatsuba multiplication, all the storage required is allocated upfront and
+// passed down the stack in this routine. Note that all the cpp_int_backend's must be the same type
+// and full variable precision. Karatsuba really doesn't play nice with fixed-size integers. If necessary
+// fixed precision integers will get aliased as variable-precision types before this is called.
+//
+template <std::size_t MinBits, std::size_t MaxBits, cpp_int_check_type Checked, class Allocator>
+inline void multiply_karatsuba(
+ cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& result,
+ const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a,
+ const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& b,
+ typename cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>::scoped_shared_storage& storage)
+{
+ using cpp_int_type = cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>;
+
+ std::size_t as = a.size();
+ std::size_t bs = b.size();
+ //
+ // Termination condition: if either argument is smaller than karatsuba_cutoff
+ // then schoolboy multiplication will be faster:
+ //
+ if ((as < karatsuba_cutoff) || (bs < karatsuba_cutoff))
+ {
+ eval_multiply(result, a, b);
+ return;
+ }
+ //
+ // Partitioning size: split the larger of a and b into 2 halves
+ //
+ std::size_t n = (as > bs ? as : bs) / 2 + 1;
+ //
+ // Partition a and b into high and low parts.
+ // ie write a, b as a = a_h * 2^n + a_l, b = b_h * 2^n + b_l
+ //
+ // We could copy the high and low parts into new variables, but we'll
+ // use aliasing to reference the internal limbs of a and b. There is one wart here:
+ // if a and b are mismatched in size, then n may be larger than the smaller
+ // of a and b. In that situation the high part is zero, and we have no limbs
+ // to alias, so instead alias a local variable.
+ // This raises 2 questions:
+ // * Is this the best way to partition a and b?
+ // * Since we have one high part zero, the arithmetic simplifies considerably,
+ // so should we have a special routine for this?
+ //
+ std::size_t sz = (std::min)(as, n);
+ const cpp_int_type a_l(a.limbs(), 0, sz);
+
+ sz = (std::min)(bs, n);
+ const cpp_int_type b_l(b.limbs(), 0, sz);
+
+ limb_type zero = 0;
+ const cpp_int_type a_h(as > n ? a.limbs() + n : &zero, 0, as > n ? as - n : 1);
+ const cpp_int_type b_h(bs > n ? b.limbs() + n : &zero, 0, bs > n ? bs - n : 1);
+ //
+ // The basis for the Karatsuba algorithm is as follows:
+ //
+ // let x = a_h * b_ h
+ // y = a_l * b_l
+ // z = (a_h + a_l)*(b_h + b_l) - x - y
+ // and therefore a * b = x * (2 ^ (2 * n))+ z * (2 ^ n) + y
+ //
+ // Begin by allocating our temporaries, these alias the memory already allocated in the shared storage:
+ //
+ cpp_int_type t1(storage, 2 * n + 2);
+ cpp_int_type t2(storage, n + 1);
+ cpp_int_type t3(storage, n + 1);
+ //
+ // Now we want:
+ //
+ // result = | a_h*b_h | a_l*b_l |
+ // (bits) <-- 2*n -->
+ //
+ // We create aliases for the low and high parts of result, and multiply directly into them:
+ //
+ cpp_int_type result_low(result.limbs(), 0, 2 * n);
+ cpp_int_type result_high(result.limbs(), 2 * n, result.size() - 2 * n);
+ //
+ // low part of result is a_l * b_l:
+ //
+ multiply_karatsuba(result_low, a_l, b_l, storage);
+ //
+ // We haven't zeroed out memory in result, so set to zero any unused limbs,
+ // if a_l and b_l have mostly random bits then nothing happens here, but if
+ // one is zero or nearly so, then a memset might be faster... it's not clear
+ // that it's worth the extra logic though (and is darn hard to measure
+ // what the "average" case is).
+ //
+ for (std::size_t i = result_low.size(); i < 2 * n; ++i)
+ result.limbs()[i] = 0;
+ //
+ // Set the high part of result to a_h * b_h:
+ //
+ multiply_karatsuba(result_high, a_h, b_h, storage);
+ for (std::size_t i = result_high.size() + 2 * n; i < result.size(); ++i)
+ result.limbs()[i] = 0;
+ //
+ // Now calculate (a_h+a_l)*(b_h+b_l):
+ //
+ add_unsigned(t2, a_l, a_h);
+ add_unsigned(t3, b_l, b_h);
+ multiply_karatsuba(t1, t2, t3, storage); // t1 = (a_h+a_l)*(b_h+b_l)
+ //
+ // There is now a slight deviation from Karatsuba, we want to subtract
+ // a_l*b_l + a_h*b_h from t1, but rather than use an addition and a subtraction
+ // plus one temporary, we'll use 2 subtractions. On the minus side, a subtraction
+ // is on average slightly slower than an addition, but we save a temporary (ie memory)
+ // and also hammer the same piece of memory over and over rather than 2 disparate
+ // memory regions. Overall it seems to be a slight win.
+ //
+ subtract_unsigned(t1, t1, result_high);
+ subtract_unsigned(t1, t1, result_low);
+ //
+ // The final step is to left shift t1 by n bits and add to the result.
+ // Rather than do an actual left shift, we can simply alias the result
+ // and add to the alias:
+ //
+ cpp_int_type result_alias(result.limbs(), n, result.size() - n);
+ add_unsigned(result_alias, result_alias, t1);
+ //
+ // Free up storage for use by sister branches to this one:
+ //
+ storage.deallocate(t1.capacity() + t2.capacity() + t3.capacity());
+
+ result.normalize();
+}
+
+inline std::size_t karatsuba_storage_size(std::size_t s)
+{
+ //
+ // This estimates how much memory we will need based on
+ // s-limb multiplication. In an ideal world the number of limbs
+ // would halve with each recursion, and our storage requirements
+ // would be 4s in the limit, and rather less in practice since
+ // we bail out long before we reach one limb. In the real world
+ // we don't quite halve s in each recursion, so this is an heuristic
+ // which over-estimates how much we need. We could compute an exact
+ // value, but it would be rather time consuming.
+ //
+ return 5 * s;
+}
+//
+// There are 2 entry point routines for Karatsuba multiplication:
+// one for variable precision types, and one for fixed precision types.
+// These are responsible for allocating all the storage required for the recursive
+// routines above, and are always at the outermost level.
+//
+// Normal variable precision case comes first:
+//
+template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
+inline typename std::enable_if<!is_fixed_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value>::type
+setup_karatsuba(
+ cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result,
+ const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& a,
+ const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& b)
+{
+ std::size_t as = a.size();
+ std::size_t bs = b.size();
+ std::size_t s = as > bs ? as : bs;
+ std::size_t storage_size = karatsuba_storage_size(s);
+ if (storage_size < 300)
+ {
+ //
+ // Special case: if we don't need too much memory, we can use stack based storage
+ // and save a call to the allocator, this allows us to use Karatsuba multiply
+ // at lower limb counts than would otherwise be possible:
+ //
+ limb_type limbs[300];
+ typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::scoped_shared_storage storage(limbs, storage_size);
+ multiply_karatsuba(result, a, b, storage);
+ }
+ else
+ {
+ typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::scoped_shared_storage storage(result.allocator(), storage_size);
+ multiply_karatsuba(result, a, b, storage);
+ }
+}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, 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>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+inline typename std::enable_if<is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_fixed_precision<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value || is_fixed_precision<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
+setup_karatsuba(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
+{
+ //
+ // Now comes the fixed precision case.
+ // In fact Karatsuba doesn't really work with fixed precision since the logic
+ // requires that we calculate all the bits of the result (especially in the
+ // temporaries used internally). So... we'll convert all the arguments
+ // to variable precision types by aliasing them, this also
+ // reduce the number of template instantations:
+ //
+ using variable_precision_type = cpp_int_backend<0, 0, signed_magnitude, unchecked, std::allocator<limb_type> >;
+ variable_precision_type a_t(a.limbs(), 0, a.size()), b_t(b.limbs(), 0, b.size());
+ std::size_t as = a.size();
+ std::size_t bs = b.size();
+ std::size_t s = as > bs ? as : bs;
+ std::size_t sz = as + bs;
+ std::size_t storage_size = karatsuba_storage_size(s);
+
+ if (!is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || (sz * sizeof(limb_type) * CHAR_BIT <= MaxBits1))
+ {
+ // Result is large enough for all the bits of the result, so we can use aliasing:
+ result.resize(sz, sz);
+ variable_precision_type t(result.limbs(), 0, result.size());
+ typename variable_precision_type::scoped_shared_storage storage(t.allocator(), storage_size);
+ multiply_karatsuba(t, a_t, b_t, storage);
+ result.resize(t.size(), t.size());
+ }
+ else
+ {
+ //
+ // Not enough bit in result for the answer, so we must use a temporary
+ // and then truncate (ie modular arithmetic):
+ //
+ typename variable_precision_type::scoped_shared_storage storage(variable_precision_type::allocator_type(), sz + storage_size);
+ variable_precision_type t(storage, sz);
+ multiply_karatsuba(t, a_t, b_t, storage);
+ //
+ // If there is truncation, and result is a checked type then this will throw:
+ //
+ result = t;
+ }
+}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+inline typename std::enable_if<!is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_fixed_precision<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_fixed_precision<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
+setup_karatsuba(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
{
- // 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:
+ // Variable precision, mixed arguments, just alias and forward:
//
- unsigned as = a.size();
- unsigned bs = b.size();
+ using variable_precision_type = cpp_int_backend<0, 0, signed_magnitude, unchecked, std::allocator<limb_type> >;
+ variable_precision_type a_t(a.limbs(), 0, a.size()), b_t(b.limbs(), 0, b.size());
+ std::size_t as = a.size();
+ std::size_t bs = b.size();
+ std::size_t s = as > bs ? as : bs;
+ std::size_t sz = as + bs;
+ std::size_t storage_size = karatsuba_storage_size(s);
+
+ result.resize(sz, sz);
+ variable_precision_type t(result.limbs(), 0, result.size());
+ typename variable_precision_type::scoped_shared_storage storage(t.allocator(), storage_size);
+ multiply_karatsuba(t, a_t, b_t, storage);
+}
+
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+inline BOOST_MP_CXX14_CONSTEXPR void
+eval_multiply_comba(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+{
+ //
+ // see PR #182
+ // Comba Multiplier - based on Paul Comba's
+ // Exponentiation cryptosystems on the IBM PC, 1990
+ //
+ std::ptrdiff_t as = a.size(),
+ bs = b.size(),
+ rs = result.size();
+ typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs();
+
+ double_limb_type carry = 0,
+ temp = 0;
+ limb_type overflow = 0;
+ const std::size_t limb_bits = sizeof(limb_type) * CHAR_BIT;
+ const bool must_throw = rs < as + bs - 1;
+ for (std::ptrdiff_t r = 0, lim = (std::min)(rs, as + bs - 1); r < lim; ++r, overflow = 0)
+ {
+ std::ptrdiff_t i = r >= as ? as - 1 : r,
+ j = r - i,
+ k = i < bs - j ? i + 1 : bs - j; // min(i+1, bs-j);
+
+ typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer pa = a.limbs() + i;
+ typename cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>::const_limb_pointer pb = b.limbs() + j;
+
+ temp = carry;
+ carry += static_cast<double_limb_type>(*(pa)) * (*(pb));
+ overflow += carry < temp;
+ for (--k; k; k--)
+ {
+ temp = carry;
+ carry += static_cast<double_limb_type>(*(--pa)) * (*(++pb));
+ overflow += carry < temp;
+ }
+ *(pr++) = static_cast<limb_type>(carry);
+ carry = (static_cast<double_limb_type>(overflow) << limb_bits) | (carry >> limb_bits);
+ }
+ if (carry || must_throw)
+ {
+ resize_for_carry(result, as + bs);
+ if (static_cast<int>(result.size()) >= as + bs)
+ *pr = static_cast<limb_type>(carry);
+ }
+}
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
+ noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && (karatsuba_cutoff * sizeof(limb_type) * CHAR_BIT > MaxBits1)
+ && (karatsuba_cutoff * sizeof(limb_type)* CHAR_BIT > MaxBits2)
+ && (karatsuba_cutoff * sizeof(limb_type)* CHAR_BIT > MaxBits3)))
+{
+ // Uses simple (O(n^2)) multiplication when the limbs are less
+ // otherwise switches to karatsuba algorithm based on experimental value (~40 limbs)
+ //
+ // Trivial cases first:
+ //
+ std::size_t as = a.size();
+ std::size_t bs = b.size();
typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer pa = a.limbs();
typename cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>::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<double_limb_type>(*pa) * static_cast<double_limb_type>(*pb);
}
@@ -102,52 +421,82 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
result.sign(s);
return;
}
- if(bs == 1)
+ if (bs == 1)
{
- bool s = b.sign() != a.sign();
+ bool s = b.sign() != a.sign();
limb_type l = *pb;
eval_multiply(result, a, l);
result.sign(s);
return;
}
- if((void*)&result == (void*)&a)
+ if ((void*)&result == (void*)&a)
{
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(a);
eval_multiply(result, t, b);
return;
}
- if((void*)&result == (void*)&b)
+ if ((void*)&result == (void*)&b)
{
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(b);
eval_multiply(result, a, t);
return;
}
+ constexpr double_limb_type limb_max = static_cast<double_limb_type>(~static_cast<limb_type>(0u));
+ constexpr double_limb_type double_limb_max = static_cast<double_limb_type>(~static_cast<double_limb_type>(0u));
+
result.resize(as + bs, as + bs - 1);
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (!BOOST_MP_IS_CONST_EVALUATED(as) && (as >= karatsuba_cutoff && bs >= karatsuba_cutoff))
+#else
+ if (as >= karatsuba_cutoff && bs >= karatsuba_cutoff)
+#endif
+ {
+ setup_karatsuba(result, a, b);
+ //
+ // Set the sign of the result:
+ //
+ result.sign(a.sign() != b.sign());
+ return;
+ }
typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs();
+ static_assert(double_limb_max - 2 * limb_max >= limb_max * limb_max, "failed limb size sanity check");
- static const double_limb_type limb_max = ~static_cast<limb_type>(0u);
- static const double_limb_type double_limb_max = ~static_cast<double_limb_type>(0u);
- BOOST_STATIC_ASSERT(double_limb_max - 2 * limb_max >= limb_max * limb_max);
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(as))
+ {
+ for (std::size_t i = 0; i < result.size(); ++i)
+ pr[i] = 0;
+ }
+ else
+#endif
+ std::memset(pr, 0, result.size() * sizeof(limb_type));
+
+#if defined(BOOST_MP_COMBA)
+ //
+ // Comba Multiplier might not be efficient because of less efficient assembly
+ // by the compiler as of 09/01/2020 (DD/MM/YY). See PR #182
+ // Till then this will lay dormant :(
+ //
+ eval_multiply_comba(result, a, b);
+#else
double_limb_type carry = 0;
- std::memset(pr, 0, result.size() * sizeof(limb_type));
- for(unsigned i = 0; i < as; ++i)
+ for (std::size_t i = 0; i < as; ++i)
{
- unsigned inner_limit = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable ? bs : (std::min)(result.size() - i, bs);
- unsigned j;
- for(j = 0; j < inner_limit; ++j)
+ BOOST_MP_ASSERT(result.size() > i);
+ std::size_t inner_limit = !is_fixed_precision<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value ? bs : (std::min)(result.size() - i, bs);
+ std::size_t j = 0;
+ for (; j < inner_limit; ++j)
{
- BOOST_ASSERT(i+j < result.size());
+ BOOST_MP_ASSERT(i + j < result.size());
#if (!defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || !BOOST_WORKAROUND(BOOST_GCC_VERSION, <= 50100)
- BOOST_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized
- || ((std::numeric_limits<double_limb_type>::max)() - carry
- >
- static_cast<double_limb_type>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value) * static_cast<double_limb_type>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value)));
+ BOOST_MP_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized || ((std::numeric_limits<double_limb_type>::max)() - carry >
+ static_cast<double_limb_type>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value) * static_cast<double_limb_type>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value)));
#endif
carry += static_cast<double_limb_type>(pa[i]) * static_cast<double_limb_type>(pb[j]);
- BOOST_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized || ((std::numeric_limits<double_limb_type>::max)() - carry >= pr[i+j]));
+ BOOST_MP_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized || ((std::numeric_limits<double_limb_type>::max)() - carry >= pr[i + j]));
carry += pr[i + j];
#ifdef __MSVC_RUNTIME_CHECKS
pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
@@ -155,12 +504,12 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
pr[i + j] = static_cast<limb_type>(carry);
#endif
carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
- BOOST_ASSERT(carry <= (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value));
+ BOOST_MP_ASSERT(carry <= (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::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<limb_type>(carry & ~static_cast<limb_type>(0));
#else
@@ -169,6 +518,8 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
}
carry = 0;
}
+#endif // ifdef(BOOST_MP_COMBA) ends
+
result.normalize();
//
// Set the sign of the result:
@@ -176,36 +527,42 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
result.sign(a.sign() != b.sign());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a)
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>()))))
{
- eval_multiply(result, result, a);
+ eval_multiply(result, result, a);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& val)
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const limb_type&>()))))
{
eval_multiply(result, result, val);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const double_limb_type& val)
+ noexcept(
+ (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const limb_type&>())))
+ && (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>())))
+ )
{
- if(val <= (std::numeric_limits<limb_type>::max)())
+ if (val <= (std::numeric_limits<limb_type>::max)())
{
eval_multiply(result, a, static_cast<limb_type>(val));
}
else
{
-#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE)
+#if BOOST_MP_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
#else
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
@@ -215,21 +572,23 @@ BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<Mi
}
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const double_limb_type& val)
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const double_limb_type&>()))))
{
eval_multiply(result, result, val);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const signed_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const signed_limb_type& val)
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const limb_type&>()))))
{
- if(val > 0)
+ if (val > 0)
eval_multiply(result, a, static_cast<limb_type>(val));
else
{
@@ -238,35 +597,40 @@ BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<Mi
}
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const signed_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const signed_limb_type& val)
+ noexcept((noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const limb_type&>()))))
{
eval_multiply(result, result, val);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ const signed_double_limb_type& val)
+ noexcept(
+ (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const limb_type&>())))
+ && (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>())))
+ )
{
- if(val > 0)
+ if (val > 0)
{
- if(val <= (std::numeric_limits<limb_type>::max)())
+ if (val <= (std::numeric_limits<limb_type>::max)())
{
eval_multiply(result, a, static_cast<limb_type>(val));
return;
}
}
- else if(val >= -static_cast<signed_double_limb_type>((std::numeric_limits<limb_type>::max)()))
+ else if (val >= -static_cast<signed_double_limb_type>((std::numeric_limits<limb_type>::max)()))
{
eval_multiply(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(val)));
result.negate();
return;
}
-#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE)
+#if BOOST_MP_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
#else
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
@@ -275,9 +639,13 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
eval_multiply(result, a, t);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const signed_double_limb_type& val)
+ noexcept(
+ (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const limb_type&>())))
+ && (noexcept(eval_multiply(std::declval<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>(), std::declval<const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&>())))
+ )
{
eval_multiply(result, result, val);
}
@@ -285,61 +653,49 @@ BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<Mi
//
// Now over again for trivial cpp_int's:
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
- >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
result.sign(result.sign() != o.sign());
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
- >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
result.sign(a.sign() != b.sign());
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
*result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
result.normalize();
@@ -348,32 +704,31 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
//
// Special routines for multiplying two integers to obtain a multiprecision result:
//
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- signed_double_limb_type a, signed_double_limb_type b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ signed_double_limb_type a, signed_double_limb_type b)
{
- static const signed_double_limb_type mask = ~static_cast<limb_type>(0);
- static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
+ constexpr signed_double_limb_type mask = static_cast<signed_double_limb_type>(~static_cast<limb_type>(0));
+ constexpr std::size_t limb_bits = static_cast<std::size_t>(sizeof(limb_type) * CHAR_BIT);
+
bool s = false;
- double_limb_type w, x, y, z;
- if(a < 0)
+ if (a < 0)
{
a = -a;
s = true;
}
- if(b < 0)
+ if (b < 0)
{
b = -b;
s = !s;
}
- w = a & mask;
- x = a >> limb_bits;
- y = b & mask;
- z = b >> limb_bits;
+ double_limb_type w = a & mask;
+ double_limb_type x = static_cast<double_limb_type>(a >> limb_bits);
+ double_limb_type y = b & mask;
+ double_limb_type z = static_cast<double_limb_type>(b >> limb_bits);
result.resize(4, 4);
limb_type* pr = result.limbs();
@@ -402,22 +757,20 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- double_limb_type a, double_limb_type b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ double_limb_type a, double_limb_type b)
{
- static const signed_double_limb_type mask = ~static_cast<limb_type>(0);
- static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
+ constexpr signed_double_limb_type mask = static_cast<signed_double_limb_type>(~static_cast<limb_type>(0));
+ constexpr std::size_t limb_bits = static_cast<std::size_t>(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;
+ double_limb_type w = a & mask;
+ double_limb_type x = a >> limb_bits;
+ double_limb_type y = b & mask;
+ double_limb_type z = b >> limb_bits;
result.resize(4, 4);
limb_type* pr = result.limbs();
@@ -454,45 +807,42 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1,
- unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-BOOST_MP_FORCEINLINE typename enable_if_c<
- !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- >::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& a,
- cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1,
+ std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& a,
+ cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& b)
{
- typedef typename boost::multiprecision::detail::canonical<typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::type canonical_type;
+ using canonical_type = typename boost::multiprecision::detail::canonical<typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::type;
eval_multiply(result, static_cast<canonical_type>(*a.limbs()), static_cast<canonical_type>(*b.limbs()));
result.sign(a.sign() != b.sign());
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class SI>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_signed<SI>::value && (sizeof(SI) <= sizeof(signed_double_limb_type) / 2)>::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- SI a, SI b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class SI>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<SI>::value && boost::multiprecision::detail::is_integral<SI>::value && (sizeof(SI) <= sizeof(signed_double_limb_type) / 2)>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ SI a, SI b)
{
result = static_cast<signed_double_limb_type>(a) * static_cast<signed_double_limb_type>(b);
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class UI>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_unsigned<UI>::value && (sizeof(UI) <= sizeof(signed_double_limb_type) / 2)>::type
- eval_multiply(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- UI a, UI b)
+template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class UI>
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<UI>::value && (sizeof(UI) <= sizeof(signed_double_limb_type) / 2)>::type
+eval_multiply(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ UI a, UI b)
{
result = static_cast<double_limb_type>(a) * static_cast<double_limb_type>(b);
}
-#ifdef _MSC_VER
+#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
-}}} // namespaces
+}}} // namespace boost::multiprecision::backends
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/serialize.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/serialize.hpp
index 042a9f89f7..e419619460 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/serialize.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/serialize.hpp
@@ -1,35 +1,40 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_SERIALIZE_HPP
#define BOOST_MP_CPP_INT_SERIALIZE_HPP
+#ifndef BOOST_MP_STANDALONE
+
namespace boost {
-namespace archive{
+namespace archive {
class binary_oarchive;
class binary_iarchive;
-}
+} // namespace archive
namespace serialization {
namespace mp = boost::multiprecision;
-namespace cpp_int_detail{
+namespace cpp_int_detail {
using namespace boost::multiprecision;
using namespace boost::multiprecision::backends;
template <class T>
-struct is_binary_archive : public mpl::false_ {};
+struct is_binary_archive : public std::integral_constant<bool, false>
+{};
template <>
-struct is_binary_archive<boost::archive::binary_oarchive> : public mpl::true_ {};
+struct is_binary_archive<boost::archive::binary_oarchive> : public std::integral_constant<bool, true>
+{};
template <>
-struct is_binary_archive<boost::archive::binary_iarchive> : public mpl::true_ {};
+struct is_binary_archive<boost::archive::binary_iarchive> : public std::integral_constant<bool, true>
+{};
//
// We have 8 serialization methods to fill out (and test), they are all permutations of:
@@ -38,162 +43,169 @@ struct is_binary_archive<boost::archive::binary_iarchive> : public mpl::true_ {}
// Binary or not archive.
//
template <class Archive, class Int>
-void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::false_ const&)
+void do_serialize(Archive& ar, Int& val, std::integral_constant<bool, false> const&, std::integral_constant<bool, false> const&, std::integral_constant<bool, false> const&)
{
// Load.
// Non-trivial.
// Non binary.
- bool s;
- ar & s;
+ using boost::make_nvp;
+ bool s;
+ ar& make_nvp("sign", s);
std::size_t limb_count;
std::size_t byte_count;
- ar & byte_count;
+ ar& make_nvp("byte-count", 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)
+ 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)
+ for (std::size_t j = 0; (j < sizeof(limb_type)) && byte_count; ++j)
{
unsigned char byte;
- ar & byte;
+ ar& make_nvp("byte", byte);
pl[i] |= static_cast<limb_type>(byte) << (j * CHAR_BIT);
--byte_count;
}
}
- if(s != val.sign())
+ if (s != val.sign())
val.negate();
val.normalize();
}
template <class Archive, class Int>
-void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::false_ const&)
+void do_serialize(Archive& ar, Int& val, std::integral_constant<bool, true> const&, std::integral_constant<bool, false> const&, std::integral_constant<bool, false> const&)
{
// Store.
// Non-trivial.
// Non binary.
- bool s = val.sign();
- ar & s;
- limb_type* pl = val.limbs();
+ using boost::make_nvp;
+ bool s = val.sign();
+ ar& make_nvp("sign", 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;
+ ar& make_nvp("byte-count", byte_count);
- for(std::size_t i = 0; i < limb_count; ++i)
+ 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)
+ for (std::size_t j = 0; j < sizeof(limb_type); ++j)
{
unsigned char byte = static_cast<unsigned char>((l >> (j * CHAR_BIT)) & ((1u << CHAR_BIT) - 1));
- ar & byte;
+ ar& make_nvp("byte", byte);
}
}
}
template <class Archive, class Int>
-void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::false_ const&)
+void do_serialize(Archive& ar, Int& val, std::integral_constant<bool, false> const&, std::integral_constant<bool, true> const&, std::integral_constant<bool, false> const&)
{
// Load.
// Trivial.
// Non binary.
- bool s;
+ using boost::make_nvp;
+ 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)
+ ar& make_nvp("sign", s);
+ std::size_t byte_count;
+ ar& make_nvp("byte-count", byte_count);
+ for (std::size_t i = 0; i < byte_count; ++i)
{
unsigned char b;
- ar & b;
+ ar& make_nvp("byte", b);
l |= static_cast<typename Int::local_limb_type>(b) << (i * CHAR_BIT);
}
*val.limbs() = l;
- if(s != val.sign())
+ if (s != val.sign())
val.negate();
}
template <class Archive, class Int>
-void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::false_ const&)
+void do_serialize(Archive& ar, Int& val, std::integral_constant<bool, true> const&, std::integral_constant<bool, true> const&, std::integral_constant<bool, false> const&)
{
// Store.
// Trivial.
// Non binary.
- bool s = val.sign();
+ using boost::make_nvp;
+ 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)
+ ar& make_nvp("sign", s);
+ std::size_t limb_count = sizeof(l);
+ ar& make_nvp("byte-count", limb_count);
+ for (std::size_t i = 0; i < limb_count; ++i)
{
unsigned char b = static_cast<unsigned char>(static_cast<typename Int::local_limb_type>(l >> (i * CHAR_BIT)) & static_cast<typename Int::local_limb_type>((1u << CHAR_BIT) - 1));
- ar & b;
+ ar& make_nvp("byte", b);
}
}
template <class Archive, class Int>
-void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::true_ const&)
+void do_serialize(Archive& ar, Int& val, std::integral_constant<bool, false> const&, std::integral_constant<bool, false> const&, std::integral_constant<bool, true> const&)
{
// Load.
// Non-trivial.
// Binary.
- bool s;
+ bool s;
std::size_t c;
- ar & s;
- ar & c;
+ ar& s;
+ ar& c;
val.resize(c, c);
ar.load_binary(val.limbs(), c * sizeof(limb_type));
- if(s != val.sign())
+ if (s != val.sign())
val.negate();
val.normalize();
}
template <class Archive, class Int>
-void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::true_ const&)
+void do_serialize(Archive& ar, Int& val, std::integral_constant<bool, true> const&, std::integral_constant<bool, false> const&, std::integral_constant<bool, true> const&)
{
// Store.
// Non-trivial.
// Binary.
- bool s = val.sign();
+ bool s = val.sign();
std::size_t c = val.size();
- ar & s;
- ar & c;
+ ar& s;
+ ar& c;
ar.save_binary(val.limbs(), c * sizeof(limb_type));
}
template <class Archive, class Int>
-void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::true_ const&)
+void do_serialize(Archive& ar, Int& val, std::integral_constant<bool, false> const&, std::integral_constant<bool, true> const&, std::integral_constant<bool, true> const&)
{
// Load.
// Trivial.
// Binary.
bool s;
- ar & s;
+ ar& s;
ar.load_binary(val.limbs(), sizeof(*val.limbs()));
- if(s != val.sign())
+ if (s != val.sign())
val.negate();
}
template <class Archive, class Int>
-void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::true_ const&)
+void do_serialize(Archive& ar, Int& val, std::integral_constant<bool, true> const&, std::integral_constant<bool, true> const&, std::integral_constant<bool, true> const&)
{
// Store.
// Trivial.
// Binary.
bool s = val.sign();
- ar & s;
+ ar& s;
ar.save_binary(val.limbs(), sizeof(*val.limbs()));
}
-}
+} // namespace cpp_int_detail
-template<class Archive, unsigned MinBits, unsigned MaxBits, mp::cpp_integer_type SignType, mp::cpp_int_check_type Checked, class Allocator>
-void serialize(Archive & ar, mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& val, const unsigned int /*version*/)
+template <class Archive, std::size_t MinBits, std::size_t MaxBits, mp::cpp_integer_type SignType, mp::cpp_int_check_type Checked, class Allocator>
+void serialize(Archive& ar, mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& val, const unsigned int /*version*/)
{
- typedef typename Archive::is_saving save_tag;
- typedef mpl::bool_<mp::backends::is_trivial_cpp_int<mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> trivial_tag;
- typedef typename cpp_int_detail::is_binary_archive<Archive>::type binary_tag;
+ using archive_save_tag = typename Archive::is_saving ;
+ using save_tag = std::integral_constant<bool, archive_save_tag::value> ;
+ using trivial_tag = std::integral_constant<bool, mp::backends::is_trivial_cpp_int<mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value>;
+ using binary_tag = typename cpp_int_detail::is_binary_archive<Archive>::type ;
// Just dispatch to the correct method:
cpp_int_detail::do_serialize(ar, val, save_tag(), trivial_tag(), binary_tag());
}
-}} // namespaces
+} // namespace serialization
+} // namespace boost
-#endif // BOOST_MP_CPP_INT_SERIALIZE_HPP
+#endif // BOOST_MP_STANDALONE
+#endif // BOOST_MP_CPP_INT_SERIALIZE_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/value_pack.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/value_pack.hpp
index 29d9562e04..bb3fe880d5 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/value_pack.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/cpp_int/value_pack.hpp
@@ -1,36 +1,42 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_VP_HPP
#define BOOST_MP_CPP_INT_VP_HPP
-namespace boost{ namespace multiprecision{
+namespace boost {
+namespace multiprecision {
-namespace literals{ namespace detail{
+namespace literals { namespace detail {
-template <limb_type...VALUES>
+template <limb_type... VALUES>
struct value_pack
{
- constexpr value_pack(){}
+ constexpr value_pack() {}
- typedef value_pack<0, VALUES...> next_type;
+ using next_type = value_pack<0, VALUES...>;
};
template <class T>
-struct is_value_pack{ static constexpr bool value = false; };
-template <limb_type...VALUES>
-struct is_value_pack<value_pack<VALUES...> >{ static constexpr bool value = true; };
+struct is_value_pack
+{
+ static constexpr bool value = false;
+};
+template <limb_type... VALUES>
+struct is_value_pack<value_pack<VALUES...> >
+{
+ static constexpr bool value = true;
+};
-struct negate_tag{};
+struct negate_tag
+{};
constexpr negate_tag make_negate_tag()
{
return negate_tag();
}
-
-}}}} // namespaces
+}}}} // namespace boost::multiprecision::literals::detail
#endif // BOOST_MP_CPP_INT_CORE_HPP
-
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/assert.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/assert.hpp
new file mode 100644
index 0000000000..9e7c795c94
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/assert.hpp
@@ -0,0 +1,29 @@
+// (C) Copyright Matt Borland 2021.
+// Use, modification and distribution are subject to 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)
+//
+// We deliberately use assert in here:
+//
+// boost-no-inspect
+
+#ifndef BOOST_MP_DETAIL_ASSERT_HPP
+#define BOOST_MP_DETAIL_ASSERT_HPP
+
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+#ifndef BOOST_MP_STANDALONE
+
+#include <boost/assert.hpp>
+#define BOOST_MP_ASSERT(expr) BOOST_ASSERT(expr)
+#define BOOST_MP_ASSERT_MSG(expr, msg) BOOST_ASSERT_MSG(expr, msg)
+
+#else // Standalone mode - use cassert
+
+#include <cassert>
+#define BOOST_MP_ASSERT(expr) assert(expr)
+#define BOOST_MP_ASSERT_MSG(expr, msg) assert((expr)&&(msg))
+
+#endif
+
+#endif // BOOST_MP_DETAIL_ASSERT_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/bitscan.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/bitscan.hpp
index c12606551f..2a696b83ee 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/bitscan.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/bitscan.hpp
@@ -1,26 +1,30 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
#ifndef BOOST_MP_DETAIL_BITSCAN_HPP
#define BOOST_MP_DETAIL_BITSCAN_HPP
-#include <boost/detail/endian.hpp>
+#include <cstdint>
+#include <climits>
+#include <type_traits>
+#include <boost/multiprecision/detail/endian.hpp>
+#include <boost/multiprecision/detail/standalone_config.hpp>
#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
#include <intrin.h>
#endif
-namespace boost{ namespace multiprecision{ namespace detail{
+namespace boost { namespace multiprecision { namespace detail {
template <class Unsigned>
-inline unsigned find_lsb(Unsigned mask, const mpl::int_<0>&)
+inline BOOST_MP_CXX14_CONSTEXPR std::size_t find_lsb_default(Unsigned mask)
{
- unsigned result = 0;
- while(!(mask & 1u))
+ std::size_t result = 0;
+ while (!(mask & 1u))
{
mask >>= 1;
++result;
@@ -29,10 +33,10 @@ inline unsigned find_lsb(Unsigned mask, const mpl::int_<0>&)
}
template <class Unsigned>
-inline unsigned find_msb(Unsigned mask, const mpl::int_<0>&)
+inline BOOST_MP_CXX14_CONSTEXPR std::size_t find_msb_default(Unsigned mask)
{
- unsigned index = 0;
- while(mask)
+ std::size_t index = 0;
+ while (mask)
{
++index;
mask >>= 1;
@@ -40,18 +44,30 @@ inline unsigned find_msb(Unsigned mask, const mpl::int_<0>&)
return --index;
}
+template <class Unsigned>
+inline BOOST_MP_CXX14_CONSTEXPR std::size_t find_lsb(Unsigned mask, const std::integral_constant<int, 0>&)
+{
+ return find_lsb_default(mask);
+}
+
+template <class Unsigned>
+inline BOOST_MP_CXX14_CONSTEXPR std::size_t find_msb(Unsigned mask, const std::integral_constant<int, 0>&)
+{
+ return find_msb_default(mask);
+}
+
#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
-#pragma intrinsic(_BitScanForward,_BitScanReverse)
+#pragma intrinsic(_BitScanForward, _BitScanReverse)
-BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, const mpl::int_<1>&)
+BOOST_FORCEINLINE std::size_t find_lsb(unsigned long mask, const std::integral_constant<int, 1>&)
{
unsigned long result;
_BitScanForward(&result, mask);
return result;
}
-BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, const mpl::int_<1>&)
+BOOST_FORCEINLINE std::size_t find_msb(unsigned long mask, const std::integral_constant<int, 1>&)
{
unsigned long result;
_BitScanReverse(&result, mask);
@@ -59,16 +75,16 @@ BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, const mpl::int_<1>&)
}
#ifdef _M_X64
-#pragma intrinsic(_BitScanForward64,_BitScanReverse64)
+#pragma intrinsic(_BitScanForward64, _BitScanReverse64)
-BOOST_FORCEINLINE unsigned find_lsb(unsigned __int64 mask, const mpl::int_<2>&)
+BOOST_FORCEINLINE std::size_t find_lsb(unsigned __int64 mask, const std::integral_constant<int, 2>&)
{
unsigned long result;
_BitScanForward64(&result, mask);
return result;
}
template <class Unsigned>
-BOOST_FORCEINLINE unsigned find_msb(Unsigned mask, const mpl::int_<2>&)
+BOOST_FORCEINLINE std::size_t find_msb(Unsigned mask, const std::integral_constant<int, 2>&)
{
unsigned long result;
_BitScanReverse64(&result, mask);
@@ -77,188 +93,225 @@ BOOST_FORCEINLINE unsigned find_msb(Unsigned mask, const mpl::int_<2>&)
#endif
template <class Unsigned>
-BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
+BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR std::size_t find_lsb(Unsigned mask)
{
- typedef typename make_unsigned<Unsigned>::type ui_type;
- typedef typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned long),
- mpl::int_<1>,
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<Unsigned>::type;
+ using tag_type = typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned long),
+ std::integral_constant<int, 1>,
#ifdef _M_X64
- typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(__int64),
- mpl::int_<2>,
- mpl::int_<0>
- >::type
+ typename std::conditional<
+ sizeof(Unsigned) <= sizeof(__int64),
+ std::integral_constant<int, 2>,
+ std::integral_constant<int, 0> >::type
#else
- mpl::int_<0>
+ std::integral_constant<int, 0>
#endif
- >::type tag_type;
- return find_lsb(static_cast<ui_type>(mask), tag_type());
+ >::type;
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(mask))
+ {
+ return find_lsb_default(mask);
+ }
+ else
+#endif
+ return find_lsb(static_cast<ui_type>(mask), tag_type());
}
template <class Unsigned>
-BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
+BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR std::size_t find_msb(Unsigned mask)
{
- typedef typename make_unsigned<Unsigned>::type ui_type;
- typedef typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned long),
- mpl::int_<1>,
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<Unsigned>::type;
+ using tag_type = typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned long),
+ std::integral_constant<int, 1>,
#ifdef _M_X64
- typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(__int64),
- mpl::int_<2>,
- mpl::int_<0>
- >::type
+ typename std::conditional<
+ sizeof(Unsigned) <= sizeof(__int64),
+ std::integral_constant<int, 2>,
+ std::integral_constant<int, 0> >::type
#else
- mpl::int_<0>
+ std::integral_constant<int, 0>
#endif
- >::type tag_type;
- return find_msb(static_cast<ui_type>(mask), tag_type());
+ >::type;
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(mask))
+ {
+ return find_msb_default(mask);
+ }
+ else
+#endif
+ return find_msb(static_cast<ui_type>(mask), tag_type());
}
#elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
-BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
+BOOST_FORCEINLINE std::size_t find_lsb(std::size_t mask, std::integral_constant<int, 1> const&)
{
- return __builtin_ctz(mask);
+ return static_cast<std::size_t>(__builtin_ctz(static_cast<unsigned int>(mask)));
}
-BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, mpl::int_<2> const&)
+BOOST_FORCEINLINE std::size_t find_lsb(unsigned long mask, std::integral_constant<int, 2> const&)
{
- return __builtin_ctzl(mask);
+ return static_cast<std::size_t>(__builtin_ctzl(static_cast<unsigned long>(mask)));
}
-BOOST_FORCEINLINE unsigned find_lsb(boost::ulong_long_type mask, mpl::int_<3> const&)
+BOOST_FORCEINLINE std::size_t find_lsb(unsigned long long mask, std::integral_constant<int, 3> const&)
{
- return __builtin_ctzll(mask);
+ return static_cast<std::size_t>(__builtin_ctzll(static_cast<unsigned long long>(mask)));
}
-BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
+BOOST_FORCEINLINE std::size_t find_msb(std::size_t mask, std::integral_constant<int, 1> const&)
{
- return sizeof(unsigned) * CHAR_BIT - 1 - __builtin_clz(mask);
+ return static_cast<std::size_t>(static_cast<std::size_t>(sizeof(unsigned) * static_cast<std::size_t>(CHAR_BIT) - 1u) - static_cast<std::size_t>(__builtin_clz(static_cast<unsigned int>(mask))));
}
-BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, mpl::int_<2> const&)
+BOOST_FORCEINLINE std::size_t find_msb(unsigned long mask, std::integral_constant<int, 2> const&)
{
- return sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(mask);
+ return static_cast<std::size_t>(static_cast<std::size_t>(sizeof(unsigned long) * static_cast<std::size_t>(CHAR_BIT) - 1u) - static_cast<std::size_t>(__builtin_clzl(static_cast<unsigned long>(mask))));
}
-BOOST_FORCEINLINE unsigned find_msb(boost::ulong_long_type mask, mpl::int_<3> const&)
+BOOST_FORCEINLINE std::size_t find_msb(unsigned long long mask, std::integral_constant<int, 3> const&)
{
- return sizeof(boost::ulong_long_type) * CHAR_BIT - 1 - __builtin_clzll(mask);
+ return static_cast<std::size_t>(static_cast<std::size_t>(sizeof(unsigned long long) * static_cast<std::size_t>(CHAR_BIT) - 1u) - static_cast<std::size_t>(__builtin_clzll(static_cast<unsigned long long>(mask))));
}
#ifdef BOOST_HAS_INT128
-__extension__ typedef unsigned __int128 uint128_type;
-
-BOOST_FORCEINLINE unsigned find_msb(uint128_type mask, mpl::int_<0> const&)
+BOOST_FORCEINLINE std::size_t find_msb(uint128_type mask, std::integral_constant<int, 0> const&)
{
- union { uint128_type v; boost::uint64_t sv[2]; } val;
+ union
+ {
+ uint128_type v;
+ std::uint64_t sv[2];
+ } val;
val.v = mask;
-#ifdef BOOST_LITTLE_ENDIAN
- if(val.sv[1])
- return find_msb(val.sv[1], mpl::int_<3>()) + 64;
- return find_msb(val.sv[0], mpl::int_<3>());
+#if BOOST_MP_ENDIAN_LITTLE_BYTE
+ if (val.sv[1])
+ return find_msb(val.sv[1], std::integral_constant<int, 3>()) + 64;
+ return find_msb(val.sv[0], std::integral_constant<int, 3>());
#else
- if(val.sv[0])
- return find_msb(val.sv[0], mpl::int_<3>()) + 64;
- return find_msb(val.sv[1], mpl::int_<3>());
+ if (val.sv[0])
+ return find_msb(val.sv[0], std::integral_constant<int, 3>()) + 64;
+ return find_msb(val.sv[1], std::integral_constant<int, 3>());
#endif
}
-BOOST_FORCEINLINE unsigned find_lsb(uint128_type mask, mpl::int_<0> const&)
+BOOST_FORCEINLINE std::size_t find_lsb(uint128_type mask, std::integral_constant<int, 0> const&)
{
- union { uint128_type v; boost::uint64_t sv[2]; } val;
+ union
+ {
+ uint128_type v;
+ std::uint64_t sv[2];
+ } val;
val.v = mask;
-#ifdef BOOST_LITTLE_ENDIAN
- if(val.sv[0] == 0)
- return find_lsb(val.sv[1], mpl::int_<3>()) + 64;
- return find_lsb(val.sv[0], mpl::int_<3>());
+#if BOOST_MP_ENDIAN_LITTLE_BYTE
+ if (val.sv[0] == 0)
+ return find_lsb(val.sv[1], std::integral_constant<int, 3>()) + 64;
+ return find_lsb(val.sv[0], std::integral_constant<int, 3>());
#else
- if(val.sv[1] == 0)
- return find_lsb(val.sv[0], mpl::int_<3>()) + 64;
- return find_lsb(val.sv[1], mpl::int_<3>());
+ if (val.sv[1] == 0)
+ return find_lsb(val.sv[0], std::integral_constant<int, 3>()) + 64;
+ return find_lsb(val.sv[1], std::integral_constant<int, 3>());
#endif
}
#endif
template <class Unsigned>
-BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
+BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR std::size_t find_lsb(Unsigned mask)
{
- typedef typename make_unsigned<Unsigned>::type ui_type;
- typedef typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned),
- mpl::int_<1>,
- typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned long),
- mpl::int_<2>,
- typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(boost::ulong_long_type),
- mpl::int_<3>,
- mpl::int_<0>
- >::type
- >::type
- >::type tag_type;
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<Unsigned>::type;
+ using tag_type = typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned),
+ std::integral_constant<int, 1>,
+ typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned long),
+ std::integral_constant<int, 2>,
+ typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned long long),
+ std::integral_constant<int, 3>,
+ std::integral_constant<int, 0> >::type>::type>::type;
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(mask))
+ {
+ return find_lsb_default(mask);
+ }
+ else
+#endif
return find_lsb(static_cast<ui_type>(mask), tag_type());
}
template <class Unsigned>
-BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
+BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR std::size_t find_msb(Unsigned mask)
{
- typedef typename make_unsigned<Unsigned>::type ui_type;
- typedef typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned),
- mpl::int_<1>,
- typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned long),
- mpl::int_<2>,
- typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(boost::ulong_long_type),
- mpl::int_<3>,
- mpl::int_<0>
- >::type
- >::type
- >::type tag_type;
- return find_msb(static_cast<ui_type>(mask), tag_type());
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<Unsigned>::type;
+ using tag_type = typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned),
+ std::integral_constant<int, 1>,
+ typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned long),
+ std::integral_constant<int, 2>,
+ typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned long long),
+ std::integral_constant<int, 3>,
+ std::integral_constant<int, 0> >::type>::type>::type;
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(mask))
+ {
+ return find_msb_default(mask);
+ }
+ else
+#endif
+ return find_msb(static_cast<ui_type>(mask), tag_type());
}
#elif defined(BOOST_INTEL)
-BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
+BOOST_FORCEINLINE std::size_t find_lsb(std::size_t mask, std::integral_constant<int, 1> const&)
{
return _bit_scan_forward(mask);
}
-BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
+BOOST_FORCEINLINE std::size_t find_msb(std::size_t mask, std::integral_constant<int, 1> const&)
{
return _bit_scan_reverse(mask);
}
template <class Unsigned>
-BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
+BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR std::size_t find_lsb(Unsigned mask)
{
- typedef typename make_unsigned<Unsigned>::type ui_type;
- typedef typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned),
- mpl::int_<1>,
- mpl::int_<0>
- >::type tag_type;
- return find_lsb(static_cast<ui_type>(mask), tag_type());
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<Unsigned>::type;
+ using tag_type = typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned),
+ std::integral_constant<int, 1>,
+ std::integral_constant<int, 0> >::type;
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(mask))
+ {
+ return find_lsb_default(mask);
+ }
+ else
+#endif
+ return find_lsb(static_cast<ui_type>(mask), tag_type());
}
template <class Unsigned>
-BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
+BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR std::size_t find_msb(Unsigned mask)
{
- typedef typename make_unsigned<Unsigned>::type ui_type;
- typedef typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned),
- mpl::int_<1>,
- mpl::int_<0>
- >::type tag_type;
- return find_msb(static_cast<ui_type>(mask), tag_type());
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<Unsigned>::type;
+ using tag_type = typename std::conditional<
+ sizeof(Unsigned) <= sizeof(unsigned),
+ std::integral_constant<int, 1>,
+ std::integral_constant<int, 0> >::type;
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(mask))
+ {
+ return find_msb_default(mask);
+ }
+ else
+#endif
+ return find_msb(static_cast<ui_type>(mask), tag_type());
}
#else
template <class Unsigned>
-BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
+BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR std::size_t find_lsb(Unsigned mask)
{
- return find_lsb(mask, mpl::int_<0>());
+ return find_lsb(mask, std::integral_constant<int, 0>());
}
template <class Unsigned>
-BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
+BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR std::size_t find_msb(Unsigned mask)
{
- return find_msb(mask, mpl::int_<0>());
+ return find_msb(mask, std::integral_constant<int, 0>());
}
#endif
-}}}
+}}} // namespace boost::multiprecision::detail
#endif
-
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/check_cpp11_config.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/check_cpp11_config.hpp
new file mode 100644
index 0000000000..f798ef64d2
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/check_cpp11_config.hpp
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2011 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_MP_CHECK_CPP11_CONFIG_HPP
+#define BOOST_MP_CHECK_CPP11_CONFIG_HPP
+
+//
+// We now require C++11, if something we use is not supported, then error and say why:
+//
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_RVALUE_REFERENCES being set"
+#endif
+#ifdef BOOST_NO_CXX11_TEMPLATE_ALIASES
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_TEMPLATE_ALIASES being set"
+#endif
+#ifdef BOOST_NO_CXX11_HDR_ARRAY
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_HDR_ARRAY being set"
+#endif
+#ifdef BOOST_NO_CXX11_HDR_TYPE_TRAITS
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_HDR_TYPE_TRAITS being set"
+#endif
+#ifdef BOOST_NO_CXX11_ALLOCATOR
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_ALLOCATOR being set"
+#endif
+#ifdef BOOST_NO_CXX11_CONSTEXPR
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_CONSTEXPR being set"
+#endif
+#ifdef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS being set"
+#endif
+#ifdef BOOST_NO_CXX11_REF_QUALIFIERS
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_REF_QUALIFIERS being set"
+#endif
+#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_HDR_FUNCTIONAL being set"
+#endif
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_VARIADIC_TEMPLATES being set"
+#endif
+#ifdef BOOST_NO_CXX11_USER_DEFINED_LITERALS
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_USER_DEFINED_LITERALS being set"
+#endif
+#ifdef BOOST_NO_CXX11_DECLTYPE
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_DECLTYPE being set"
+#endif
+#ifdef BOOST_NO_CXX11_STATIC_ASSERT
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_STATIC_ASSERT being set"
+#endif
+#ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_DEFAULTED_FUNCTIONS being set"
+#endif
+#ifdef BOOST_NO_CXX11_NOEXCEPT
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_NOEXCEPT being set"
+#endif
+#ifdef BOOST_NO_CXX11_REF_QUALIFIERS
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_REF_QUALIFIERS being set"
+#endif
+#ifdef BOOST_NO_CXX11_USER_DEFINED_LITERALS
+#error "This library now requires a C++11 or later compiler - this message was generated as a result of BOOST_NO_CXX11_USER_DEFINED_LITERALS being set"
+#endif
+
+#endif // BOOST_MP_CHECK_CPP11_CONFIG_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/constexpr.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/constexpr.hpp
new file mode 100644
index 0000000000..6b4d952889
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/constexpr.hpp
@@ -0,0 +1,88 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2019 John Maddock. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_MP_DETAIL_CONSTEXPR_HPP
+#define BOOST_MP_DETAIL_CONSTEXPR_HPP
+
+#include <cstring>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+namespace boost {
+
+namespace multiprecision {
+
+namespace std_constexpr {
+
+template <class T>
+inline BOOST_CXX14_CONSTEXPR void swap(T& a, T& b)
+{
+ T t(a);
+ a = b;
+ b = t;
+}
+
+template <class InputIterator, class OutputIterator>
+inline BOOST_CXX14_CONSTEXPR OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
+{
+ //
+ // There are 3 branches here, only one of which is selected at compile time:
+ //
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(*first))
+ {
+ // constexpr safe code, never generates runtime code:
+ while (first != last)
+ {
+ *result = *first;
+ ++first;
+ ++result;
+ }
+ return result;
+ }
+ else
+#endif
+ {
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+ if constexpr (std::is_pointer<InputIterator>::value && std::is_pointer<OutputIterator>::value && std::is_trivially_copyable<typename std::remove_reference<decltype(*first)>::type>::value)
+ {
+ // The normal runtime branch:
+ std::memcpy(result, first, static_cast<std::size_t>(static_cast<std::size_t>(last - first) * sizeof(*first)));
+ return result + (last - first);
+ }
+ else
+#endif
+ {
+ // Alternate runtime branch:
+ while (first != last)
+ {
+ *result = *first;
+ ++first;
+ ++result;
+ }
+ return result;
+ }
+ }
+}
+
+template <class I>
+inline BOOST_CXX14_CONSTEXPR bool equal(const I* first, const I* last, const I* other)
+{
+ while (first != last)
+ {
+ if (*first != *other)
+ return false;
+ ++first;
+ ++other;
+ }
+ return true;
+}
+
+}
+
+}
+
+} // namespace boost::multiprecision::std_constexpr
+
+#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/default_ops.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/default_ops.hpp
index c45eec447f..d959f56faa 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/default_ops.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/default_ops.hpp
@@ -1,58 +1,85 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright 2011 John Maddock. Distributed under the Boost
+// Copyright 2011-21 John Maddock.
+// Copyright 2021 Iskandarov Lev. 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_MATH_BIG_NUM_DEF_OPS
-#define BOOST_MATH_BIG_NUM_DEF_OPS
+#ifndef BOOST_MP_DEFAULT_OPS
+#define BOOST_MP_DEFAULT_OPS
-#include <boost/math/policies/error_handling.hpp>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
#include <boost/multiprecision/detail/number_base.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+#include <boost/multiprecision/traits/is_backend.hpp>
+#include <boost/multiprecision/detail/fpclassify.hpp>
+#include <cstdint>
+#include <complex>
+#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
+#include <string_view>
+#endif
+
+#ifdef BOOST_MP_MATH_AVAILABLE
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/special_functions/next.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/mpl/front.hpp>
-#include <boost/mpl/fold.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/math/special_functions/hypot.hpp>
+#include <boost/math/policies/error_handling.hpp>
+#endif
#ifndef INSTRUMENT_BACKEND
#ifndef BOOST_MP_INSTRUMENT
#define INSTRUMENT_BACKEND(x)
#else
-#define INSTRUMENT_BACKEND(x)\
+#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 <class T>
- struct is_backend;
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/);
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/);
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
- template <class To, class From>
- void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
- template <class To, class From>
- void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
- template <class To, class From>
- void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/);
- template <class To, class From>
- void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/);
- template <class To, class From>
- void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR Integer karatsuba_sqrt(const Integer& x, Integer& r, size_t bits);
-}
-
-namespace default_ops{
+} // namespace detail
+
+namespace default_ops {
+
+template <class T>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val);
+
+template <class T>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val) { return val < 0; }
+
+inline int eval_signbit(float val) { return (std::signbit)(val); }
+inline int eval_signbit(double val) { return (std::signbit)(val); }
+inline int eval_signbit(long double val) { return (std::signbit)(val); }
+#ifdef BOOST_HAS_FLOAT128
+extern "C" int signbitq(float128_type) throw();
+inline int eval_signbit(float128_type val) { return signbitq(val); }
+#endif
+
+template <class T>
+BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val);
#ifdef BOOST_MSVC
// warning C4127: conditional expression is constant
// 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
@@ -66,165 +93,165 @@ namespace default_ops{
// code even more....
//
template <class T, class V>
-inline typename disable_if_c<is_convertible<V, T>::value >::type
- eval_add(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
+eval_add(T& result, V const& v)
{
T t;
t = v;
eval_add(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, T>::value >::type
- eval_add(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
+eval_add(T& result, V const& v)
{
T t(v);
eval_add(result, t);
}
template <class T, class V>
-inline typename disable_if_c<is_convertible<V, T>::value>::type
- eval_subtract(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
+eval_subtract(T& result, V const& v)
{
T t;
t = v;
eval_subtract(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, T>::value>::type
- eval_subtract(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
+eval_subtract(T& result, V const& v)
{
T t(v);
eval_subtract(result, t);
}
template <class T, class V>
-inline typename disable_if_c<is_convertible<V, T>::value>::type
- eval_multiply(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
+eval_multiply(T& result, V const& v)
{
T t;
t = v;
eval_multiply(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, T>::value>::type
- eval_multiply(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
+eval_multiply(T& result, V const& v)
{
T t(v);
eval_multiply(result, t);
}
template <class T, class U, class V>
-void eval_multiply(T& t, const U& u, const V& v);
+BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v);
template <class T, class U, class V>
-inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::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 <class T, class U, class V>
-inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
{
eval_multiply_add(t, v, u);
}
template <class T, class U, class V>
-inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::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 <class T, class U, class V>
-inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
{
eval_multiply_subtract(t, v, u);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
- eval_divide(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
+eval_divide(T& result, V const& v)
{
T t;
t = v;
eval_divide(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
- eval_divide(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
+eval_divide(T& result, V const& v)
{
T t(v);
eval_divide(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
- eval_modulus(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
+eval_modulus(T& result, V const& v)
{
T t;
t = v;
eval_modulus(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value&& is_convertible<V, T>::value>::type
- eval_modulus(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
+eval_modulus(T& result, V const& v)
{
T t(v);
eval_modulus(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
- eval_bitwise_and(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
+eval_bitwise_and(T& result, V const& v)
{
T t;
t = v;
eval_bitwise_and(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
- eval_bitwise_and(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
+eval_bitwise_and(T& result, V const& v)
{
T t(v);
eval_bitwise_and(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
- eval_bitwise_or(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
+eval_bitwise_or(T& result, V const& v)
{
T t;
t = v;
eval_bitwise_or(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
- eval_bitwise_or(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
+eval_bitwise_or(T& result, V const& v)
{
T t(v);
eval_bitwise_or(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
- eval_bitwise_xor(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
+eval_bitwise_xor(T& result, V const& v)
{
T t;
t = v;
eval_bitwise_xor(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
- eval_bitwise_xor(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
+eval_bitwise_xor(T& result, V const& v)
{
T t(v);
eval_bitwise_xor(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
- eval_complement(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
+eval_complement(T& result, V const& v)
{
T t;
t = v;
eval_complement(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
- eval_complement(T& result, V const& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
+eval_complement(T& result, V const& v)
{
T t(v);
eval_complement(result, t);
@@ -234,16 +261,16 @@ inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_co
// Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions:
//
template <class T, class U, class V>
-void eval_add(T& t, const U& u, const V& v);
+BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v);
template <class T>
-inline void eval_add_default(T& t, const T& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const T& u, const T& v)
{
- if(&t == &v)
+ if (&t == &v)
{
eval_add(t, u);
}
- else if(&t == &u)
+ else if (&t == &u)
{
eval_add(t, v);
}
@@ -254,29 +281,37 @@ inline void eval_add_default(T& t, const T& u, const T& v)
}
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
{
T vv;
vv = v;
eval_add(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
{
T vv(v);
eval_add(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
{
eval_add(t, v, u);
}
template <class T, class U, class V>
-inline void eval_add_default(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const U& u, const V& v)
{
- if(is_same<T, V>::value && ((void*)&t == (void*)&v))
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
{
- eval_add(t, u);
+ if ((void*)&t == (void*)&v)
+ {
+ eval_add(t, u);
+ }
+ else
+ {
+ t = u;
+ eval_add(t, v);
+ }
}
else
{
@@ -285,23 +320,23 @@ inline void eval_add_default(T& t, const U& u, const V& v)
}
}
template <class T, class U, class V>
-inline void eval_add(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v)
{
eval_add_default(t, u, v);
}
template <class T, class U, class V>
-void eval_subtract(T& t, const U& u, const V& v);
+void BOOST_MP_CXX14_CONSTEXPR eval_subtract(T& t, const U& u, const V& v);
template <class T>
-inline void eval_subtract_default(T& t, const T& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const T& u, const T& v)
{
- if((&t == &v) && is_signed_number<T>::value)
+ if ((&t == &v) && is_signed_number<T>::value)
{
eval_subtract(t, u);
t.negate();
}
- else if(&t == &u)
+ else if (&t == &u)
{
eval_subtract(t, v);
}
@@ -312,44 +347,59 @@ inline void eval_subtract_default(T& t, const T& u, const T& v)
}
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
{
T vv;
vv = v;
eval_subtract(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
{
T vv(v);
eval_subtract(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value && (number_category<T>::value != number_kind_complex)>::type eval_subtract_default(T& t, const U& u, const T& v)
+{
+ eval_subtract(t, v, u);
+ if(!eval_is_zero(t) || (eval_signbit(u) != eval_signbit(v)))
+ t.negate();
+}
+template <class T, class U>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value && (number_category<T>::value == number_kind_complex)>::type eval_subtract_default(T& t, const U& u, const T& v)
{
eval_subtract(t, v, u);
t.negate();
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
{
T temp;
temp = u;
eval_subtract(t, temp, v);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
{
T temp(u);
eval_subtract(t, temp, v);
}
template <class T, class U, class V>
-inline void eval_subtract_default(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const U& u, const V& v)
{
- if(is_same<T, V>::value && ((void*)&t == (void*)&v))
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
{
- eval_subtract(t, u);
- t.negate();
+ if ((void*)&t == (void*)&v)
+ {
+ eval_subtract(t, u);
+ t.negate();
+ }
+ else
+ {
+ t = u;
+ eval_subtract(t, v);
+ }
}
else
{
@@ -358,19 +408,19 @@ inline void eval_subtract_default(T& t, const U& u, const V& v)
}
}
template <class T, class U, class V>
-inline void eval_subtract(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(T& t, const U& u, const V& v)
{
eval_subtract_default(t, u, v);
}
template <class T>
-inline void eval_multiply_default(T& t, const T& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const T& u, const T& v)
{
- if(&t == &v)
+ if (&t == &v)
{
eval_multiply(t, u);
}
- else if(&t == &u)
+ else if (&t == &u)
{
eval_multiply(t, v);
}
@@ -382,30 +432,38 @@ inline void eval_multiply_default(T& t, const T& u, const T& v)
}
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
{
T vv;
vv = v;
eval_multiply(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
{
T vv(v);
eval_multiply(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
{
eval_multiply(t, v, u);
}
#endif
template <class T, class U, class V>
-inline void eval_multiply_default(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const U& u, const V& v)
{
- if(is_same<T, V>::value && ((void*)&t == (void*)&v))
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
{
- eval_multiply(t, u);
+ if ((void*)&t == (void*)&v)
+ {
+ eval_multiply(t, u);
+ }
+ else
+ {
+ t = number<T>::canonical_value(u);
+ eval_multiply(t, v);
+ }
}
else
{
@@ -414,15 +472,15 @@ inline void eval_multiply_default(T& t, const U& u, const V& v)
}
}
template <class T, class U, class V>
-inline void eval_multiply(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v)
{
eval_multiply_default(t, u, v);
}
template <class T>
-inline void eval_multiply_add(T& t, const T& u, const T& v, const T& x)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_add(T& t, const T& u, const T& v, const T& x)
{
- if((void*)&x == (void*)&t)
+ if ((void*)&x == (void*)&t)
{
T z;
z = number<T>::canonical_value(x);
@@ -436,32 +494,32 @@ inline void eval_multiply_add(T& t, const T& u, const T& v, const T& x)
}
template <class T, class U>
-inline typename boost::disable_if_c<boost::is_same<T, U>::value, T>::type make_T(const U& u)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_same<T, U>::value, T>::type make_T(const U& u)
{
T t;
t = number<T>::canonical_value(u);
- return BOOST_MP_MOVE(t);
+ return t;
}
template <class T>
-inline const T& make_T(const T& t)
+inline BOOST_MP_CXX14_CONSTEXPR const T& make_T(const T& t)
{
return t;
}
template <class T, class U, class V, class X>
-inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
{
eval_multiply_add(t, make_T<T>(u), make_T<T>(v), make_T<T>(x));
}
template <class T, class U, class V, class X>
-inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
{
eval_multiply_add(t, v, u, x);
}
template <class T, class U, class V, class X>
-inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
{
- if((void*)&x == (void*)&t)
+ if ((void*)&x == (void*)&t)
{
T z;
z = x;
@@ -474,20 +532,20 @@ inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::typ
}
}
template <class T, class U, class V, class X>
-inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
{
eval_multiply_subtract(t, v, u, x);
}
template <class T, class U, class V>
-void eval_divide(T& t, const U& u, const V& v);
+BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v);
template <class T>
-inline void eval_divide_default(T& t, const T& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const T& u, const T& v)
{
- if(&t == &u)
+ if (&t == &u)
eval_divide(t, v);
- else if(&t == &v)
+ else if (&t == &v)
{
T temp;
eval_divide(temp, u, v);
@@ -501,41 +559,49 @@ inline void eval_divide_default(T& t, const T& u, const T& v)
}
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
{
T vv;
vv = v;
eval_divide(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
{
T vv(v);
eval_divide(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
{
T uu;
uu = u;
eval_divide(t, uu, v);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
{
T uu(u);
eval_divide(t, uu, v);
}
#endif
template <class T, class U, class V>
-inline void eval_divide_default(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const U& u, const V& v)
{
- if(is_same<T, V>::value && ((void*)&t == (void*)&v))
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
{
- T temp;
- temp = u;
- eval_divide(temp, v);
- t = temp;
+ if ((void*)&t == (void*)&v)
+ {
+ T temp;
+ temp = u;
+ eval_divide(temp, v);
+ t = temp;
+ }
+ else
+ {
+ t = u;
+ eval_divide(t, v);
+ }
}
else
{
@@ -544,20 +610,20 @@ inline void eval_divide_default(T& t, const U& u, const V& v)
}
}
template <class T, class U, class V>
-inline void eval_divide(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v)
{
eval_divide_default(t, u, v);
}
template <class T, class U, class V>
-void eval_modulus(T& t, const U& u, const V& v);
+BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v);
template <class T>
-inline void eval_modulus_default(T& t, const T& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const T& u, const T& v)
{
- if(&t == &u)
+ if (&t == &u)
eval_modulus(t, v);
- else if(&t == &v)
+ else if (&t == &v)
{
T temp;
eval_modulus(temp, u, v);
@@ -570,39 +636,47 @@ inline void eval_modulus_default(T& t, const T& u, const T& v)
}
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
{
T vv;
vv = v;
eval_modulus(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
{
T vv(v);
eval_modulus(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
{
T uu;
uu = u;
eval_modulus(t, uu, v);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
{
T uu(u);
eval_modulus(t, uu, v);
}
template <class T, class U, class V>
-inline void eval_modulus_default(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const U& u, const V& v)
{
- if(is_same<T, V>::value && ((void*)&t == (void*)&v))
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
{
- T temp(u);
- eval_modulus(temp, v);
- t = temp;
+ if ((void*)&t == (void*)&v)
+ {
+ T temp(u);
+ eval_modulus(temp, v);
+ t = temp;
+ }
+ else
+ {
+ t = u;
+ eval_modulus(t, v);
+ }
}
else
{
@@ -611,22 +685,22 @@ inline void eval_modulus_default(T& t, const U& u, const V& v)
}
}
template <class T, class U, class V>
-inline void eval_modulus(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v)
{
eval_modulus_default(t, u, v);
}
template <class T, class U, class V>
-void eval_bitwise_and(T& t, const U& u, const V& v);
+BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v);
template <class T>
-inline void eval_bitwise_and_default(T& t, const T& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and_default(T& t, const T& u, const T& v)
{
- if(&t == &v)
+ if (&t == &v)
{
eval_bitwise_and(t, u);
}
- else if(&t == &u)
+ else if (&t == &u)
{
eval_bitwise_and(t, v);
}
@@ -637,46 +711,46 @@ inline void eval_bitwise_and_default(T& t, const T& u, const T& v)
}
}
template <class T, class U>
-inline typename disable_if_c<is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<U, T>::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 <class T, class U>
-inline typename enable_if_c<is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
{
T vv(v);
eval_bitwise_and(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
{
eval_bitwise_and(t, v, u);
}
template <class T, class U, class V>
-inline typename disable_if_c<is_same<T, U>::value || is_same<T, V>::value>::type eval_bitwise_and_default(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value || std::is_same<T, V>::value>::type eval_bitwise_and_default(T& t, const U& u, const V& v)
{
t = u;
eval_bitwise_and(t, v);
}
template <class T, class U, class V>
-inline void eval_bitwise_and(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v)
{
eval_bitwise_and_default(t, u, v);
}
template <class T, class U, class V>
-void eval_bitwise_or(T& t, const U& u, const V& v);
+BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v);
template <class T>
-inline void eval_bitwise_or_default(T& t, const T& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const T& u, const T& v)
{
- if(&t == &v)
+ if (&t == &v)
{
eval_bitwise_or(t, u);
}
- else if(&t == &u)
+ else if (&t == &u)
{
eval_bitwise_or(t, v);
}
@@ -687,29 +761,37 @@ inline void eval_bitwise_or_default(T& t, const T& u, const T& v)
}
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::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 <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
{
T vv(v);
eval_bitwise_or(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
{
eval_bitwise_or(t, v, u);
}
template <class T, class U, class V>
-inline void eval_bitwise_or_default(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const U& u, const V& v)
{
- if(is_same<T, V>::value && ((void*)&t == (void*)&v))
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
{
- eval_bitwise_or(t, u);
+ if ((void*)&t == (void*)&v)
+ {
+ eval_bitwise_or(t, u);
+ }
+ else
+ {
+ t = u;
+ eval_bitwise_or(t, v);
+ }
}
else
{
@@ -718,22 +800,22 @@ inline void eval_bitwise_or_default(T& t, const U& u, const V& v)
}
}
template <class T, class U, class V>
-inline void eval_bitwise_or(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v)
{
eval_bitwise_or_default(t, u, v);
}
template <class T, class U, class V>
-void eval_bitwise_xor(T& t, const U& u, const V& v);
+BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v);
template <class T>
-inline void eval_bitwise_xor_default(T& t, const T& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const T& u, const T& v)
{
- if(&t == &v)
+ if (&t == &v)
{
eval_bitwise_xor(t, u);
}
- else if(&t == &u)
+ else if (&t == &u)
{
eval_bitwise_xor(t, v);
}
@@ -744,29 +826,37 @@ inline void eval_bitwise_xor_default(T& t, const T& u, const T& v)
}
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::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 <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
{
T vv(v);
eval_bitwise_xor(t, u, vv);
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
{
eval_bitwise_xor(t, v, u);
}
template <class T, class U, class V>
-inline void eval_bitwise_xor_default(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const U& u, const V& v)
{
- if(is_same<T, V>::value && ((void*)&t == (void*)&v))
+ BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
{
- eval_bitwise_xor(t, u);
+ if ((void*)&t == (void*)&v)
+ {
+ eval_bitwise_xor(t, u);
+ }
+ else
+ {
+ t = u;
+ eval_bitwise_xor(t, v);
+ }
}
else
{
@@ -775,53 +865,89 @@ inline void eval_bitwise_xor_default(T& t, const U& u, const V& v)
}
}
template <class T, class U, class V>
-inline void eval_bitwise_xor(T& t, const U& u, const V& v)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v)
{
eval_bitwise_xor_default(t, u, v);
}
template <class T>
-inline void eval_increment(T& val)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(T& val)
{
- typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
eval_add(val, static_cast<ui_type>(1u));
}
template <class T>
-inline void eval_decrement(T& val)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(T& val)
{
- typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
eval_subtract(val, static_cast<ui_type>(1u));
}
-template <class T, class V>
-inline void eval_left_shift(T& result, const T& arg, const V val)
+template <class T, class U, class V>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_left_shift(T& result, const U& arg, const V val)
{
result = arg;
eval_left_shift(result, val);
}
-template <class T, class V>
-inline void eval_right_shift(T& result, const T& arg, const V val)
+template <class T, class U, class V>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_right_shift(T& result, const U& arg, const V val)
{
result = arg;
eval_right_shift(result, val);
}
template <class T>
-inline bool eval_is_zero(const T& val)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val)
{
- typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
return val.compare(static_cast<ui_type>(0)) == 0;
}
template <class T>
-inline int eval_get_sign(const T& val)
+inline BOOST_MP_CXX14_CONSTEXPR int eval_get_sign(const T& val)
{
- typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
return val.compare(static_cast<ui_type>(0));
}
-template <class T, class V>
-inline void assign_components_imp(T& result, const V& v1, const V& v2, const mpl::int_<number_kind_rational>&)
+template <class T, class V, class U>
+inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::false_type&, const std::false_type&)
+{
+ using component_number_type = typename component_type<number<T> >::type;
+
+ boost::multiprecision::detail::scoped_precision_options<component_number_type> sp(result);
+ (void)sp;
+
+ component_number_type x(v1), y(v2);
+ assign_components(result, x.backend(), y.backend());
+}
+template <class T, class V, class U>
+inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::true_type&, const std::false_type&)
+{
+ boost::multiprecision::detail::scoped_source_precision<number<V>> scope;
+ (void)scope;
+ assign_components_imp2(result, number<V>(v1), v2, std::false_type(), std::false_type());
+}
+template <class T, class V, class U>
+inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::true_type&, const std::true_type&)
+{
+ boost::multiprecision::detail::scoped_source_precision<number<V>> scope1;
+ boost::multiprecision::detail::scoped_source_precision<number<U>> scope2;
+ (void)scope1;
+ (void)scope2;
+ assign_components_imp2(result, number<V>(v1), number<U>(v2), std::false_type(), std::false_type());
+}
+template <class T, class V, class U>
+inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::false_type&, const std::true_type&)
+{
+ boost::multiprecision::detail::scoped_source_precision<number<U>> scope;
+ (void)scope;
+ assign_components_imp2(result, v1, number<U>(v2), std::false_type(), std::false_type());
+}
+
+
+template <class T, class V, class U>
+inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const std::integral_constant<int, number_kind_rational>&)
{
result = v1;
T t;
@@ -829,134 +955,231 @@ inline void assign_components_imp(T& result, const V& v1, const V& v2, const mpl
eval_divide(result, t);
}
-template <class T, class V>
-inline void assign_components(T& result, const V& v1, const V& v2)
+template <class T, class V, class U, int N>
+inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const std::integral_constant<int, N>&)
{
- return assign_components_imp(result, v1, v2, typename number_category<T>::type());
+ assign_components_imp2(result, v1, v2, boost::multiprecision::detail::is_backend<V>(), boost::multiprecision::detail::is_backend<U>());
}
+template <class T, class V, class U>
+inline BOOST_MP_CXX14_CONSTEXPR void assign_components(T& result, const V& v1, const U& v2)
+{
+ return assign_components_imp(result, v1, v2, typename number_category<T>::type());
+}
+#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
+template <class Result, class Traits>
+inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& 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 <class Result, class Traits>
+inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& 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 <class R, int b>
struct has_enough_bits
{
template <class T>
- struct type : public mpl::and_<mpl::not_<is_same<R, T> >, mpl::bool_<std::numeric_limits<T>::digits >= b> >{};
+ struct type : public std::integral_constant<bool, !std::is_same<R, T>::value && (std::numeric_limits<T>::digits >= b)>
+ {};
};
template <class R>
struct terminal
{
- terminal(const R& v) : value(v){}
- terminal(){}
- terminal& operator = (R val) { value = val; return *this; }
+ BOOST_MP_CXX14_CONSTEXPR terminal(const R& v) : value(v) {}
+ BOOST_MP_CXX14_CONSTEXPR terminal() {}
+ BOOST_MP_CXX14_CONSTEXPR terminal& operator=(R val)
+ {
+ value = val;
+ return *this;
+ }
R value;
- operator R()const { return value; }
+ BOOST_MP_CXX14_CONSTEXPR operator R() const { return value; }
};
-template<class R, class B>
+template <class Tuple, int i, class T, bool = (i == std::tuple_size<Tuple>::value)>
+struct find_index_of_type
+{
+ static constexpr int value =
+ std::is_same<T, typename std::tuple_element<static_cast<std::size_t>(i), Tuple>::type>::value
+ ? i
+ : find_index_of_type<Tuple, i + 1, T>::value;
+};
+template <class Tuple, int i, class T>
+struct find_index_of_type<Tuple, i, T, true>
+{
+ static constexpr int value = -1;
+};
+
+
+template <class R, class B>
struct calculate_next_larger_type
{
// Find which list we're looking through:
- typedef typename mpl::if_<
- is_signed<R>,
- typename B::signed_types,
- typename mpl::if_<
- is_unsigned<R>,
- 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<R>::digits>::template type<mpl::_> 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<R, mpl::_>
- >::type start_last;
- // Where we're starting from, either the start of the sequence or the last type found:
- typedef typename mpl::if_<is_same<start_last, typename mpl::end<list_type>::type>, typename mpl::begin<list_type>::type, start_last>::type start_seq;
- // The range we're searching:
- typedef mpl::iterator_range<start_seq, typename mpl::end<list_type>::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<
- is_same<typename mpl::end<list_type>::type, iter_type>,
- mpl::identity<terminal<R> >,
- mpl::deref<iter_type>
- >::type type;
+ using list_type = typename std::conditional<
+ boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value,
+ typename B::signed_types,
+ typename std::conditional<
+ boost::multiprecision::detail::is_unsigned<R>::value,
+ typename B::unsigned_types,
+ typename B::float_types>::type>::type;
+ static constexpr int start = find_index_of_type<list_type, 0, R>::value;
+ static constexpr int index_of_type = boost::multiprecision::detail::find_index_of_large_enough_type<list_type, start == INT_MAX ? 0 : start + 1, boost::multiprecision::detail::bits_of<R>::value> ::value;
+ using type = typename boost::multiprecision::detail::dereference_tuple<index_of_type, list_type, terminal<R> >::type;
};
template <class R, class T>
-inline typename boost::enable_if_c<boost::is_integral<R>::value, bool>::type check_in_range(const T& t)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value, bool>::type check_in_range(const T& t)
{
// Can t fit in an R?
- if((t > 0) && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
+ if ((t > 0) && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
return true;
else
- return false;
+ return false;
}
template <class R, class B>
-inline typename boost::enable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
{
- typedef typename calculate_next_larger_type<R, B>::type next_type;
- next_type n;
+ using next_type = typename calculate_next_larger_type<R, B>::type;
+ next_type n = next_type();
eval_convert_to(&n, backend);
- if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (n > (next_type)(std::numeric_limits<R>::max)()))
+ BOOST_IF_CONSTEXPR(!boost::multiprecision::detail::is_unsigned<R>::value && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded)
{
- *result = (std::numeric_limits<R>::max)();
+ if(n > static_cast<next_type>((std::numeric_limits<R>::max)()))
+ {
+ *result = (std::numeric_limits<R>::max)();
+ return;
+ }
}
- else if (std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (n < (next_type)(std::numeric_limits<R>::min)()))
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized&& std::numeric_limits<R>::is_bounded)
{
- *result = (std::numeric_limits<R>::min)();
+ if (n < static_cast<next_type>((std::numeric_limits<R>::min)()))
+ {
+ *result = (std::numeric_limits<R>::min)();
+ return;
+ }
}
- else
- *result = static_cast<R>(n);
+ *result = static_cast<R>(n);
}
template <class R, class B>
-inline typename boost::disable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !boost::multiprecision::detail::is_integral<R>::value && !std::is_enum<R>::value>::type eval_convert_to(R* result, const B& backend)
{
- typedef typename calculate_next_larger_type<R, B>::type next_type;
- next_type n;
+ using next_type = typename calculate_next_larger_type<R, B>::type;
+ next_type n = next_type();
eval_convert_to(&n, backend);
- if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && ((n > (next_type)(std::numeric_limits<R>::max)() || (n < (next_type)-(std::numeric_limits<R>::max)()) )))
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded)
{
- *result = n > 0 ? (std::numeric_limits<R>::max)() : -(std::numeric_limits<R>::max)();
+ if ((n > (next_type)(std::numeric_limits<R>::max)() || (n < (next_type) - (std::numeric_limits<R>::max)())))
+ {
+ *result = n > 0 ? (std::numeric_limits<R>::max)() : -(std::numeric_limits<R>::max)();
+ }
+ else
+ *result = static_cast<R>(n);
}
else
*result = static_cast<R>(n);
}
template <class R, class B>
-inline void eval_convert_to(terminal<R>* result, const B& backend)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_enum<R>::value>::type eval_convert_to(R* result, const B& backend)
+{
+ typename std::underlying_type<R>::type t{};
+ eval_convert_to(&t, backend);
+ *result = static_cast<R>(t);
+}
+
+#ifndef BOOST_MP_STANDALONE
+template <class R, class B>
+inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, false>&)
{
//
// We ran out of types to try for the conversion, try
// a lexical_cast and hope for the best:
//
- if (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::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
- {
+ BOOST_IF_CONSTEXPR (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed)
+ if (eval_get_sign(backend) < 0)
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
+ BOOST_MP_TRY {
result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
}
- catch (const bad_lexical_cast&)
+ BOOST_MP_CATCH (const bad_lexical_cast&)
{
if (eval_get_sign(backend) < 0)
{
- *result = std::numeric_limits<R>::is_integer && std::numeric_limits<R>::is_signed ? (std::numeric_limits<R>::min)() : -(std::numeric_limits<R>::max)();
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed)
+ *result = (std::numeric_limits<R>::max)(); // we should never get here, exception above will be raised.
+ else BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_integer)
+ *result = (std::numeric_limits<R>::min)();
+ else
+ *result = -(std::numeric_limits<R>::max)();
}
else
*result = (std::numeric_limits<R>::max)();
}
+ BOOST_MP_CATCH_END
+}
+
+template <class R, class B>
+inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, true>&)
+{
+ //
+ // Last chance conversion to an unsigned integer.
+ // We ran out of types to try for the conversion, try
+ // a lexical_cast and hope for the best:
+ //
+ if (eval_get_sign(backend) < 0)
+ BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
+ BOOST_MP_TRY {
+ B t(backend);
+ R mask = ~static_cast<R>(0u);
+ eval_bitwise_and(t, mask);
+ result->value = boost::lexical_cast<R>(t.str(0, std::ios_base::fmtflags(0)));
+ }
+ BOOST_MP_CATCH (const bad_lexical_cast&)
+ {
+ // We should never really get here...
+ *result = (std::numeric_limits<R>::max)();
+ }
+ BOOST_MP_CATCH_END
+}
+#else // Using standalone mode
+
+template <class R, class B>
+inline void last_chance_eval_convert_to(terminal<R>*, const B&, const std::integral_constant<bool, false>&)
+{
+ static_assert(sizeof(R) == 1, "This type can not be used in standalone mode. Please de-activate and file a bug at https://github.com/boostorg/multiprecision/");
+}
+
+template <class R, class B>
+inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, true>&)
+{
+ static_cast<void>(result);
+ static_cast<void>(backend);
+
+ static_assert(sizeof(R) == 1, "This type can not be used in standalone mode. Please de-activate and file a bug at https://github.com/boostorg/multiprecision/");
+}
+#endif
+
+template <class R, class B>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<R>* result, const B& backend)
+{
+ using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_unsigned<R>::value && number_category<B>::value == number_kind_integer>;
+ last_chance_eval_convert_to(result, backend, tag_type());
}
template <class B1, class B2, expression_template_option et>
-inline void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend)
{
//
// We ran out of types to try for the conversion, try
@@ -966,52 +1189,86 @@ inline void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend
}
template <class B>
-inline void eval_convert_to(std::string* result, const B& backend)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::string* result, const B& backend)
{
*result = backend.str(0, std::ios_base::fmtflags(0));
}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<float>* result, const B& backend)
+{
+ using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
+ scalar_type re, im;
+ eval_real(re.backend(), backend);
+ eval_imag(im.backend(), backend);
+
+ *result = std::complex<float>(re.template convert_to<float>(), im.template convert_to<float>());
+}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<double>* result, const B& backend)
+{
+ using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
+ scalar_type re, im;
+ eval_real(re.backend(), backend);
+ eval_imag(im.backend(), backend);
+
+ *result = std::complex<double>(re.template convert_to<double>(), im.template convert_to<double>());
+}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<long double>* result, const B& backend)
+{
+ using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
+ scalar_type re, im;
+ eval_real(re.backend(), backend);
+ eval_imag(im.backend(), backend);
+
+ *result = std::complex<long double>(re.template convert_to<long double>(), im.template convert_to<long double>());
+}
+
//
// Functions:
//
-template <class T>
-void eval_abs(T& result, const T& arg)
+template <class T, class U>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(T& result, const U& arg)
{
- typedef typename T::signed_types type_list;
- typedef typename mpl::front<type_list>::type front;
+ using type_list = typename U::signed_types ;
+ using front = typename std::tuple_element<0, type_list>::type;
result = arg;
- if(arg.compare(front(0)) < 0)
+ if (arg.compare(front(0)) < 0)
result.negate();
}
-template <class T>
-void eval_fabs(T& result, const T& arg)
+template <class T, class U>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(T& result, const U& arg)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::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_list>::type front;
+ static_assert(number_category<T>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
+ using type_list = typename U::signed_types ;
+ using front = typename std::tuple_element<0, type_list>::type;
result = arg;
- if(arg.compare(front(0)) < 0)
+ if (arg.compare(front(0)) < 0)
result.negate();
}
template <class Backend>
-inline int eval_fpclassify(const Backend& arg)
+inline BOOST_MP_CXX14_CONSTEXPR int eval_fpclassify(const Backend& arg)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
+ static_assert(number_category<Backend>::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 <class T>
-inline void eval_fmod(T& result, const T& a, const T& b)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_fmod(T& result, const T& a, const T& b)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
- if((&result == &a) || (&result == &b))
+ static_assert(number_category<T>::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))
+ switch (eval_fpclassify(a))
{
case FP_ZERO:
result = a;
@@ -1019,54 +1276,54 @@ inline void eval_fmod(T& result, const T& a, const T& b)
case FP_INFINITE:
case FP_NAN:
result = std::numeric_limits<number<T> >::quiet_NaN().backend();
- errno = EDOM;
+ errno = EDOM;
return;
}
- switch(eval_fpclassify(b))
+ switch (eval_fpclassify(b))
{
case FP_ZERO:
case FP_NAN:
result = std::numeric_limits<number<T> >::quiet_NaN().backend();
- errno = EDOM;
+ errno = EDOM;
return;
}
T n;
eval_divide(result, a, b);
- if(eval_get_sign(result) < 0)
+ 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<class T, class A>
-inline typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const T& x, const A& a)
+template <class T, class A>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_fmod(T& result, const T& x, const A& a)
{
- typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
- typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
- cast_type c;
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
+ cast_type c;
c = a;
eval_fmod(result, x, c);
}
-template<class T, class A>
-inline typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const A& x, const T& a)
+template <class T, class A>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_fmod(T& result, const A& x, const T& a)
{
- typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
- typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
- cast_type c;
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
+ cast_type c;
c = x;
eval_fmod(result, c, a);
}
template <class T>
-void eval_round(T& result, const T& a);
+BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a);
template <class T>
-inline void eval_remquo(T& result, const T& a, const T& b, int* pi)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_remquo(T& result, const T& a, const T& b, int* pi)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The remquo function is only valid for floating point types.");
- if((&result == &a) || (&result == &b))
+ static_assert(number_category<T>::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);
@@ -1079,54 +1336,59 @@ inline void eval_remquo(T& result, const T& a, const T& b, int* pi)
eval_convert_to(pi, n);
eval_multiply(n, b);
eval_subtract(result, a, n);
+ if (eval_is_zero(result))
+ {
+ if (eval_signbit(a))
+ result.negate();
+ }
}
-template<class T, class A>
-inline typename enable_if<is_arithmetic<A>, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi)
+template <class T, class A>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi)
{
- typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
- typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
- cast_type c;
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
+ cast_type c = cast_type();
c = a;
eval_remquo(result, x, c, pi);
}
-template<class T, class A>
-inline typename enable_if<is_arithmetic<A>, void>::type eval_remquo(T& result, const A& x, const T& a, int* pi)
+template <class T, class A>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_remquo(T& result, const A& x, const T& a, int* pi)
{
- typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
- typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
- cast_type c;
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
+ cast_type c = cast_type();
c = x;
eval_remquo(result, c, a, pi);
}
template <class T, class U, class V>
-inline void eval_remainder(T& result, const U& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_remainder(T& result, const U& a, const V& b)
{
- int i;
+ int i(0);
eval_remquo(result, a, b, &i);
}
template <class B>
-bool eval_gt(const B& a, const B& b);
+BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const B& a, const B& b);
template <class T, class U>
-bool eval_gt(const T& a, const U& b);
+BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const T& a, const U& b);
template <class B>
-bool eval_lt(const B& a, const B& b);
+BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const B& a, const B& b);
template <class T, class U>
-bool eval_lt(const T& a, const U& b);
+BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const T& a, const U& b);
-template<class T>
-inline void eval_fdim(T& result, const T& a, const T& b)
+template <class T>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_fdim(T& result, const T& a, const T& b)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- static const ui_type zero = 0u;
- switch(eval_fpclassify(b))
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ const ui_type zero = 0u;
+ switch (eval_fpclassify(b))
{
case FP_NAN:
case FP_INFINITE:
result = zero;
return;
}
- switch(eval_fpclassify(a))
+ switch (eval_fpclassify(a))
{
case FP_NAN:
result = zero;
@@ -1135,7 +1397,7 @@ inline void eval_fdim(T& result, const T& a, const T& b)
result = a;
return;
}
- if(eval_gt(a, b))
+ if (eval_gt(a, b))
{
eval_subtract(result, a, b);
}
@@ -1143,21 +1405,21 @@ inline void eval_fdim(T& result, const T& a, const T& b)
result = zero;
}
-template<class T, class A>
-inline typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fdim(T& result, const T& a, const A& b)
+template <class T, class A>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value>::type eval_fdim(T& result, const T& a, const A& b)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- typedef typename boost::multiprecision::detail::canonical<A, T>::type arithmetic_type;
- static const ui_type zero = 0u;
- arithmetic_type canonical_b = b;
- switch((::boost::math::fpclassify)(b))
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ using arithmetic_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ const ui_type zero = 0u;
+ arithmetic_type canonical_b = b;
+ switch (BOOST_MP_FPCLASSIFY(b))
{
case FP_NAN:
case FP_INFINITE:
result = zero;
return;
}
- switch(eval_fpclassify(a))
+ switch (eval_fpclassify(a))
{
case FP_NAN:
result = zero;
@@ -1166,7 +1428,7 @@ inline typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fd
result = a;
return;
}
- if(eval_gt(a, canonical_b))
+ if (eval_gt(a, canonical_b))
{
eval_subtract(result, a, canonical_b);
}
@@ -1174,21 +1436,21 @@ inline typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fd
result = zero;
}
-template<class T, class A>
-inline typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fdim(T& result, const A& a, const T& b)
+template <class T, class A>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value>::type eval_fdim(T& result, const A& a, const T& b)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- typedef typename boost::multiprecision::detail::canonical<A, T>::type arithmetic_type;
- static const ui_type zero = 0u;
- arithmetic_type canonical_a = a;
- switch(eval_fpclassify(b))
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ using arithmetic_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ 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))
+ switch (BOOST_MP_FPCLASSIFY(a))
{
case FP_NAN:
result = zero;
@@ -1197,7 +1459,7 @@ inline typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fd
result = std::numeric_limits<number<T> >::infinity().backend();
return;
}
- if(eval_gt(canonical_a, b))
+ if (eval_gt(canonical_a, b))
{
eval_subtract(result, canonical_a, b);
}
@@ -1206,10 +1468,10 @@ inline typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fd
}
template <class T>
-inline void eval_trunc(T& result, const T& a)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_trunc(T& result, const T& a)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
- switch(eval_fpclassify(a))
+ static_assert(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
+ switch (eval_fpclassify(a))
{
case FP_NAN:
errno = EDOM;
@@ -1219,32 +1481,32 @@ inline void eval_trunc(T& result, const T& a)
result = a;
return;
}
- if(eval_get_sign(a) < 0)
+ if (eval_get_sign(a) < 0)
eval_ceil(result, a);
else
eval_floor(result, a);
}
template <class T>
-inline void eval_modf(T& result, T const& arg, T* pipart)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_modf(T& result, T const& arg, T* pipart)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- int c = eval_fpclassify(arg);
- if(c == (int)FP_NAN)
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ int c = eval_fpclassify(arg);
+ if (c == static_cast<int>(FP_NAN))
{
- if(pipart)
+ if (pipart)
*pipart = arg;
result = arg;
return;
}
- else if(c == (int)FP_INFINITE)
+ else if (c == static_cast<int>(FP_INFINITE))
{
- if(pipart)
+ if (pipart)
*pipart = arg;
result = ui_type(0u);
return;
}
- if(pipart)
+ if (pipart)
{
eval_trunc(*pipart, arg);
eval_subtract(result, arg, *pipart);
@@ -1258,22 +1520,22 @@ inline void eval_modf(T& result, T const& arg, T* pipart)
}
template <class T>
-inline void eval_round(T& result, const T& a)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
- typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
- int c = eval_fpclassify(a);
- if(c == (int)FP_NAN)
+ static_assert(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
+ using fp_type = typename boost::multiprecision::detail::canonical<float, T>::type;
+ int c = eval_fpclassify(a);
+ if (c == static_cast<int>(FP_NAN))
{
result = a;
- errno = EDOM;
+ errno = EDOM;
return;
}
- if((c == FP_ZERO) || (c == (int)FP_INFINITE))
+ if ((c == FP_ZERO) || (c == static_cast<int>(FP_INFINITE)))
{
result = a;
}
- else if(eval_get_sign(a) < 0)
+ else if (eval_get_sign(a) < 0)
{
eval_subtract(result, a, fp_type(0.5f));
eval_ceil(result, result);
@@ -1286,77 +1548,76 @@ inline void eval_round(T& result, const T& a)
}
template <class B>
-void eval_lcm(B& result, const B& a, const B& b);
+BOOST_MP_CXX14_CONSTEXPR void eval_lcm(B& result, const B& a, const B& b);
template <class B>
-void eval_gcd(B& result, const B& a, const B& b);
+BOOST_MP_CXX14_CONSTEXPR void eval_gcd(B& result, const B& a, const B& b);
template <class T, class Arithmetic>
-inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
{
- typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
+ using si_type = typename boost::multiprecision::detail::canonical<Arithmetic, T>::type;
using default_ops::eval_gcd;
T t;
t = static_cast<si_type>(b);
eval_gcd(result, a, t);
}
template <class T, class Arithmetic>
-inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
{
eval_gcd(result, b, a);
}
template <class T, class Arithmetic>
-inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
{
- typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
+ using si_type = typename boost::multiprecision::detail::canonical<Arithmetic, T>::type;
using default_ops::eval_lcm;
T t;
t = static_cast<si_type>(b);
eval_lcm(result, a, t);
}
template <class T, class Arithmetic>
-inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
{
eval_lcm(result, b, a);
}
template <class T>
-inline unsigned eval_lsb(const T& val)
+inline BOOST_MP_CXX14_CONSTEXPR std::size_t eval_lsb(const T& val)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- int c = eval_get_sign(val);
- if(c == 0)
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ int c = eval_get_sign(val);
+ if (c == 0)
{
- BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
}
- if(c < 0)
+ if (c < 0)
{
- BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
}
- unsigned result = 0;
- T mask, t;
+ std::size_t 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));
-
+ } while (eval_is_zero(t));
+
return --result;
}
template <class T>
-inline int eval_msb(const T& val)
+inline BOOST_MP_CXX14_CONSTEXPR std::ptrdiff_t eval_msb(const T& val)
{
int c = eval_get_sign(val);
- if(c == 0)
+ if (c == 0)
{
- BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
}
- if(c < 0)
+ if (c < 0)
{
- BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
}
//
// This implementation is really really rubbish - it does
@@ -1366,21 +1627,23 @@ inline int eval_msb(const T& val)
// 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))
+ std::size_t result = 0;
+ T t(val);
+ while (!eval_is_zero(t))
{
eval_right_shift(t, 1);
++result;
}
- return --result;
+ --result;
+
+ return static_cast<std::ptrdiff_t>(result);
}
template <class T>
-inline bool eval_bit_test(const T& val, unsigned index)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_bit_test(const T& val, std::size_t index)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- T mask, t;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ T mask, t;
mask = ui_type(1);
eval_left_shift(mask, index);
eval_bitwise_and(t, mask, val);
@@ -1388,39 +1651,118 @@ inline bool eval_bit_test(const T& val, unsigned index)
}
template <class T>
-inline void eval_bit_set(T& val, unsigned index)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_set(T& val, std::size_t index)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- T mask;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ T mask;
mask = ui_type(1);
eval_left_shift(mask, index);
eval_bitwise_or(val, mask);
}
template <class T>
-inline void eval_bit_flip(T& val, unsigned index)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_flip(T& val, std::size_t index)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- T mask;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ T mask;
mask = ui_type(1);
eval_left_shift(mask, index);
eval_bitwise_xor(val, mask);
}
template <class T>
-inline void eval_bit_unset(T& val, unsigned index)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_unset(T& val, std::size_t index)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- T mask, t;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ T mask, t;
mask = ui_type(1);
eval_left_shift(mask, index);
eval_bitwise_and(t, mask, val);
- if(!eval_is_zero(t))
+ if (!eval_is_zero(t))
eval_bitwise_xor(val, mask);
}
+template <class Backend>
+BOOST_MP_CXX14_CONSTEXPR void eval_qr(const Backend& x, const Backend& y, Backend& q, Backend& r);
+
+template <class Backend>
+BOOST_MP_CXX14_CONSTEXPR void eval_karatsuba_sqrt(Backend& result, const Backend& x, Backend& r, Backend& t, size_t bits)
+{
+ using default_ops::eval_is_zero;
+ using default_ops::eval_subtract;
+ using default_ops::eval_right_shift;
+ using default_ops::eval_left_shift;
+ using default_ops::eval_bit_set;
+ using default_ops::eval_decrement;
+ using default_ops::eval_bitwise_and;
+ using default_ops::eval_add;
+ using default_ops::eval_qr;
+
+ using small_uint = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
+
+ constexpr small_uint zero = 0u;
+
+ // we can calculate it faster with std::sqrt
+#ifdef BOOST_HAS_INT128
+ if (bits <= 128)
+ {
+ uint128_type a{}, b{}, c{};
+ eval_convert_to(&a, x);
+ c = boost::multiprecision::detail::karatsuba_sqrt(a, b, bits);
+ r = number<Backend>::canonical_value(b);
+ result = number<Backend>::canonical_value(c);
+ return;
+ }
+#else
+ if (bits <= std::numeric_limits<std::uintmax_t>::digits)
+ {
+ std::uintmax_t a{ 0 }, b{ 0 }, c{ 0 };
+ eval_convert_to(&a, x);
+ c = boost::multiprecision::detail::karatsuba_sqrt(a, b, bits);
+ r = number<Backend>::canonical_value(b);
+ result = number<Backend>::canonical_value(c);
+ return;
+ }
+#endif
+ // https://hal.inria.fr/file/index/docid/72854/filename/RR-3805.pdf
+ std::size_t b = bits / 4;
+ Backend q(x);
+ eval_right_shift(q, b * 2);
+ Backend s;
+ eval_karatsuba_sqrt(s, q, r, t, bits - b * 2);
+ t = zero;
+ eval_bit_set(t, static_cast<unsigned>(b * 2));
+ eval_left_shift(r, b);
+ eval_decrement(t);
+ eval_bitwise_and(t, x);
+ eval_right_shift(t, b);
+ eval_add(t, r);
+ eval_left_shift(s, 1u);
+ eval_qr(t, s, q, r);
+ eval_left_shift(r, b);
+ t = zero;
+ eval_bit_set(t, static_cast<unsigned>(b));
+ eval_decrement(t);
+ eval_bitwise_and(t, x);
+ eval_add(r, t);
+ eval_left_shift(s, b - 1);
+ eval_add(s, q);
+ eval_multiply(q, q);
+ // we substract after, so it works for unsigned integers too
+ if (r.compare(q) < 0)
+ {
+ t = s;
+ eval_left_shift(t, 1u);
+ eval_decrement(t);
+ eval_add(r, t);
+ eval_decrement(s);
+ }
+ eval_subtract(r, q);
+ result = s;
+}
+
template <class B>
-void eval_integer_sqrt(B& s, B& r, const B& x)
+void BOOST_MP_CXX14_CONSTEXPR eval_integer_sqrt_bitwise(B& s, B& r, const B& x)
{
//
// This is slow bit-by-bit integer square root, see for example
@@ -1429,81 +1771,120 @@ void eval_integer_sqrt(B& s, B& r, const B& x)
// 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<unsigned char, B>::type ui_type;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned char, B>::type;
s = ui_type(0u);
- if(eval_get_sign(x) == 0)
+ if (eval_get_sign(x) == 0)
{
r = ui_type(0u);
return;
}
- int g = eval_msb(x);
- if(g <= 1)
+ std::ptrdiff_t g = static_cast<std::ptrdiff_t>(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);
+ std::ptrdiff_t org_g = g;
+ eval_bit_set(s, static_cast<std::size_t>(g));
+ eval_bit_set(t, static_cast<std::size_t>(2 * g));
eval_subtract(r, x, t);
--g;
- if(eval_get_sign(r) == 0)
+ if (eval_get_sign(r) == 0)
return;
- int msbr = eval_msb(r);
+ std::ptrdiff_t msbr = static_cast<std::ptrdiff_t>(eval_msb(r));
do
{
- if(msbr >= org_g + g + 1)
+ 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)
+ eval_left_shift(t, static_cast<std::size_t>(g + 1));
+ eval_bit_set(t, static_cast<std::size_t>(2 * g));
+ if (t.compare(r) <= 0)
{
- BOOST_ASSERT(g >= 0);
- eval_bit_set(s, g);
+ BOOST_MP_ASSERT(g >= 0);
+ eval_bit_set(s, static_cast<std::size_t>(g));
eval_subtract(r, t);
- if(eval_get_sign(r) == 0)
+ if (eval_get_sign(r) == 0)
return;
- msbr = eval_msb(r);
+ msbr = static_cast<std::ptrdiff_t>(eval_msb(r));
}
}
--g;
+ } while (g >= 0);
+}
+
+template <class Backend>
+BOOST_MP_CXX14_CONSTEXPR void eval_integer_sqrt(Backend& result, Backend& r, const Backend& x)
+{
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ // recursive Karatsuba sqrt can cause issues in constexpr context:
+ if (BOOST_MP_IS_CONST_EVALUATED(result.size()))
+ return eval_integer_sqrt_bitwise(result, r, x);
+#endif
+ using small_uint = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
+
+ constexpr small_uint zero = 0u;
+
+ if (eval_is_zero(x))
+ {
+ r = zero;
+ result = zero;
+ return;
}
- while(g >= 0);
+ Backend t;
+ eval_karatsuba_sqrt(result, x, r, t, eval_msb(x) + 1);
+}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_conj(B& result, const B& val)
+{
+ result = val; // assume non-complex result.
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR 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.
//
template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_floor();
+typename std::enable_if<sizeof(T) == 0>::type eval_floor();
+template <class T>
+typename std::enable_if<sizeof(T) == 0>::type eval_ceil();
+template <class T>
+typename std::enable_if<sizeof(T) == 0>::type eval_trunc();
+template <class T>
+typename std::enable_if<sizeof(T) == 0>::type eval_sqrt();
template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_ceil();
+typename std::enable_if<sizeof(T) == 0>::type eval_ldexp();
template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_trunc();
+typename std::enable_if<sizeof(T) == 0>::type eval_frexp();
+// TODO implement default versions of these:
template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_sqrt();
+typename std::enable_if<sizeof(T) == 0>::type eval_asinh();
template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_ldexp();
+typename std::enable_if<sizeof(T) == 0>::type eval_acosh();
template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_frexp();
+typename std::enable_if<sizeof(T) == 0>::type eval_atanh();
//
// eval_logb and eval_scalbn simply assume base 2 and forward to
// eval_ldexp and eval_frexp:
//
template <class B>
-inline typename B::exponent_type eval_ilogb(const B& val)
+inline BOOST_MP_CXX14_CONSTEXPR typename B::exponent_type eval_ilogb(const B& val)
{
- BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
- typename B::exponent_type e;
- switch(eval_fpclassify(val))
+ static_assert(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
+ typename B::exponent_type e(0);
+ switch (eval_fpclassify(val))
{
case FP_NAN:
#ifdef FP_ILOGBNAN
@@ -1521,17 +1902,14 @@ inline typename B::exponent_type eval_ilogb(const B& val)
return e - 1;
}
-template <class T>
-int eval_signbit(const T& val);
-
template <class B>
-inline void eval_logb(B& result, const B& val)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_logb(B& result, const B& val)
{
- switch(eval_fpclassify(val))
+ switch (eval_fpclassify(val))
{
case FP_NAN:
result = val;
- errno = EDOM;
+ errno = EDOM;
return;
case FP_ZERO:
result = std::numeric_limits<number<B> >::infinity().backend();
@@ -1540,74 +1918,74 @@ inline void eval_logb(B& result, const B& val)
return;
case FP_INFINITE:
result = val;
- if(eval_signbit(val))
+ if (eval_signbit(val))
result.negate();
return;
}
- typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, boost::long_long_type, boost::intmax_t>::type max_t;
+ using max_t = typename std::conditional<std::is_same<std::intmax_t, long>::value, long long, std::intmax_t>::type;
result = static_cast<max_t>(eval_ilogb(val));
}
template <class B, class A>
-inline void eval_scalbn(B& result, const B& val, A e)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbn(B& result, const B& val, A e)
{
- BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
+ static_assert(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
}
template <class B, class A>
-inline void eval_scalbln(B& result, const B& val, A e)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbln(B& result, const B& val, A e)
{
eval_scalbn(result, val, e);
}
template <class T>
-inline bool is_arg_nan(const T& val, mpl::true_ const&, const mpl::false_&)
+inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, std::integral_constant<bool, true> const&, const std::integral_constant<bool, false>&)
{
return eval_fpclassify(val) == FP_NAN;
}
template <class T>
-inline bool is_arg_nan(const T& val, mpl::false_ const&, const mpl::true_&)
+inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, std::integral_constant<bool, false> const&, const std::integral_constant<bool, true>&)
{
- return (boost::math::isnan)(val);
+ return BOOST_MP_ISNAN(val);
}
template <class T>
-inline bool is_arg_nan(const T&, mpl::false_ const&, const mpl::false_&)
+inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T&, std::integral_constant<bool, false> const&, const std::integral_constant<bool, false>&)
{
return false;
}
template <class T>
-inline bool is_arg_nan(const T& val)
+inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val)
{
- return is_arg_nan(val, mpl::bool_<boost::multiprecision::detail::is_backend<T>::value>(), is_floating_point<T>());
+ return is_arg_nan(val, std::integral_constant<bool, boost::multiprecision::detail::is_backend<T>::value>(), std::is_floating_point<T>());
}
template <class T, class U, class V>
-inline void eval_fmax(T& result, const U& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_fmax(T& result, const U& a, const V& b)
{
- if(is_arg_nan(a))
+ if (is_arg_nan(a))
result = number<T>::canonical_value(b);
- else if(is_arg_nan(b))
+ else if (is_arg_nan(b))
result = number<T>::canonical_value(a);
- else if(eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
+ else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
result = number<T>::canonical_value(b);
else
result = number<T>::canonical_value(a);
}
template <class T, class U, class V>
-inline void eval_fmin(T& result, const U& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_fmin(T& result, const U& a, const V& b)
{
- if(is_arg_nan(a))
+ if (is_arg_nan(a))
result = number<T>::canonical_value(b);
- else if(is_arg_nan(b))
+ else if (is_arg_nan(b))
result = number<T>::canonical_value(a);
- else if(eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
+ else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
result = number<T>::canonical_value(a);
else
result = number<T>::canonical_value(b);
}
template <class R, class T, class U>
-inline void eval_hypot(R& result, const T& a, const U& b)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_hypot(R& result, const T& a, const U& b)
{
//
// Normalize x and y, so that both are positive and x >= y:
@@ -1615,9 +1993,9 @@ inline void eval_hypot(R& result, const T& a, const U& b)
R x, y;
x = number<R>::canonical_value(a);
y = number<R>::canonical_value(b);
- if(eval_get_sign(x) < 0)
+ if (eval_get_sign(x) < 0)
x.negate();
- if(eval_get_sign(y) < 0)
+ if (eval_get_sign(y) < 0)
y.negate();
// Special case, see C99 Annex F.
@@ -1625,38 +2003,38 @@ inline void eval_hypot(R& result, const T& a, const U& b)
int c1 = eval_fpclassify(x);
int c2 = eval_fpclassify(y);
- if(c1 == FP_ZERO)
+ if (c1 == FP_ZERO)
{
result = y;
return;
}
- if(c2 == FP_ZERO)
+ if (c2 == FP_ZERO)
{
result = x;
return;
}
- if(c1 == FP_INFINITE)
+ if (c1 == FP_INFINITE)
{
result = x;
return;
}
- if((c2 == FP_INFINITE) || (c2 == FP_NAN))
+ if ((c2 == FP_INFINITE) || (c2 == FP_NAN))
{
result = y;
return;
}
- if(c1 == FP_NAN)
+ if (c1 == FP_NAN)
{
result = x;
return;
}
- if(eval_gt(y, x))
+ if (eval_gt(y, x))
x.swap(y);
eval_multiply(result, x, std::numeric_limits<number<R> >::epsilon().backend());
- if(eval_gt(result, y))
+ if (eval_gt(result, y))
{
result = x;
return;
@@ -1671,23 +2049,89 @@ inline void eval_hypot(R& result, const T& a, const U& b)
}
template <class R, class T>
-inline void eval_nearbyint(R& result, const T& a)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_nearbyint(R& result, const T& a)
{
eval_round(result, a);
}
template <class R, class T>
-inline void eval_rint(R& result, const T& a)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_rint(R& result, const T& a)
{
eval_nearbyint(result, a);
}
template <class T>
-inline int eval_signbit(const T& val)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val)
{
return eval_get_sign(val) < 0 ? 1 : 0;
}
//
+// Real and imaginary parts:
+//
+template <class To, class From>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_real(To& to, const From& from)
+{
+ to = from;
+}
+template <class To, class From>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_imag(To& to, const From&)
+{
+ using ui_type = typename std::tuple_element<0, typename To::unsigned_types>::type;
+ to = ui_type(0);
+}
+
+} // namespace default_ops
+namespace default_ops_adl {
+
+template <class To, class From>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real_imp(To& to, const From& from)
+{
+ using to_component_type = typename component_type<number<To> >::type;
+ typename to_component_type::backend_type to_component;
+ to_component = from;
+ eval_set_real(to, to_component);
+}
+template <class To, class From>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag_imp(To& to, const From& from)
+{
+ using to_component_type = typename component_type<number<To> >::type;
+ typename to_component_type::backend_type to_component;
+ to_component = from;
+ eval_set_imag(to, to_component);
+}
+
+} // namespace default_ops_adl
+namespace default_ops {
+
+template <class To, class From>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<To>::value == number_kind_complex>::type eval_set_real(To& to, const From& from)
+{
+ default_ops_adl::eval_set_real_imp(to, from);
+}
+template <class To, class From>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<To>::value != number_kind_complex>::type eval_set_real(To& to, const From& from)
+{
+ to = from;
+}
+
+template <class To, class From>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const From& from)
+{
+ default_ops_adl::eval_set_imag_imp(to, from);
+}
+
+template <class T>
+inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(T& to, const T& from)
+{
+ to = from;
+}
+template <class T>
+void BOOST_MP_CXX14_CONSTEXPR eval_set_imag(T&, const T&)
+{
+ static_assert(sizeof(T) == INT_MAX, "eval_set_imag needs to be specialised for each specific backend");
+}
+
+//
// These functions are implemented in separate files, but expanded inline here,
// DO NOT CHANGE THE ORDER OF THESE INCLUDES:
//
@@ -1695,600 +2139,849 @@ inline int eval_signbit(const T& val)
#include <boost/multiprecision/detail/functions/pow.hpp>
#include <boost/multiprecision/detail/functions/trig.hpp>
-}
+} // namespace default_ops
//
// Default versions of floating point classification routines:
//
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
using multiprecision::default_ops::eval_fpclassify;
return eval_fpclassify(arg.backend());
}
template <class tag, class A1, class A2, class A3, class A4>
-inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
int v = fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg);
- return (v != (int)FP_INFINITE) && (v != (int)FP_NAN);
+ return (v != static_cast<int>(FP_INFINITE)) && (v != static_cast<int>(FP_NAN));
}
template <class tag, class A1, class A2, class A3, class A4>
-inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
- return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NAN;
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_NAN);
}
template <class tag, class A1, class A2, class A3, class A4>
-inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
- return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_INFINITE;
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_INFINITE);
}
template <class tag, class A1, class A2, class A3, class A4>
-inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
- return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NORMAL;
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_NORMAL);
}
template <class tag, class A1, class A2, class A3, class A4>
-inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_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:
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
return arg.sign();
}
template <class tag, class A1, class A2, class A3, class A4>
-inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
using default_ops::eval_signbit;
- return eval_signbit(arg.backend());
+ return static_cast<bool>(eval_signbit(arg.backend()));
}
template <class tag, class A1, class A2, class A3, class A4>
-inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return static_cast<bool>(signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline multiprecision::number<Backend, ExpressionTemplates> changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
return -arg;
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
{
return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? (boost::multiprecision::changesign)(a) : a;
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
-inline multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
{
return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
}
template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
{
return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
}
template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
+}
+//
+// real and imag:
+//
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
+real(const multiprecision::number<Backend, ExpressionTemplates>& a)
+{
+ using default_ops::eval_real;
+ using result_type = typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type;
+ boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
+ result_type result;
+ eval_real(result.backend(), a.backend());
+ return result;
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
+imag(const multiprecision::number<Backend, ExpressionTemplates>& a)
+{
+ using default_ops::eval_imag;
+ using result_type = typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type;
+ boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
+ result_type result;
+ eval_imag(result.backend(), a.backend());
+ return result;
+}
+
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+real(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return real(value_type(arg));
+}
+
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+imag(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> 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:
+//
+#ifdef BOOST_MP_MATH_AVAILABLE
+template <class T, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates>>>::type::type
+abs(const number<T, ExpressionTemplates>& v)
+{
+ return std::move(boost::math::hypot(real(v), imag(v)));
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex, component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>>::type::type
+abs(const detail::expression<tag, A1, A2, A3, A4>& v)
+{
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return std::move(abs(static_cast<number_type>(v)));
+}
+
+template <class T, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
+arg(const number<T, ExpressionTemplates>& v)
+{
+ return std::move(atan2(imag(v), real(v)));
+}
+template <class T, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
+arg(const number<T, ExpressionTemplates>&)
+{
+ return 0;
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex || number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
+arg(const detail::expression<tag, A1, A2, A3, A4>& v)
+{
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return std::move(arg(static_cast<number_type>(v)));
+}
+#endif // BOOST_MP_MATH_AVAILABLE
+
+template <class T, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates>>>::type::type
+norm(const number<T, ExpressionTemplates>& v)
+{
+ typename component_type<number<T, ExpressionTemplates> >::type a(real(v)), b(imag(v));
+ return std::move(a * a + b * b);
+}
+template <class T, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value != number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
+norm(const number<T, ExpressionTemplates>& v)
+{
+ return v * v;
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+norm(const detail::expression<tag, A1, A2, A3, A4>& v)
+{
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return std::move(norm(static_cast<number_type>(v)));
+}
+
+template <class Backend, expression_template_option ExpressionTemplates>
+BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r, number<Backend, ExpressionTemplates> const& theta)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
+}
+
+template <class tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
+ typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
+polar(detail::expression<tag, A1, A2, A3, A4> const& r, number<Backend, ExpressionTemplates> const& theta)
+{
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
+}
+
+template <class Backend, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
+ typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
+polar(number<Backend, ExpressionTemplates> const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
+{
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
+}
+
+template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, typename detail::expression<tagb, A1b, A2b, A3b, A4b>::result_type>::value,
+ typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
+polar(detail::expression<tag, A1, A2, A3, A4> const& r, detail::expression<tagb, A1b, A2b, A3b, A4b> const& theta)
+{
+ using scalar_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return typename complex_result_from_scalar<scalar_type>::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):
+//
+template <class Scalar, class Backend, expression_template_option ExpressionTemplates>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<Scalar>::value, typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
+polar(Scalar const& r, number<Backend, ExpressionTemplates> const& theta)
+{
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
+}
+
+template <class tag, class A1, class A2, class A3, class A4, class Scalar>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<Scalar>::value,
+ typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
+polar(Scalar const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
+{
+ using scalar_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
+}
+//
+// Single argument overloads:
+//
+template <class Backend, expression_template_option ExpressionTemplates>
+BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r)
+{
+ return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(r);
+}
+
+template <class tag, class A1, class A2, class A3, class A4>
+BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+polar(detail::expression<tag, A1, A2, A3, A4> const& r)
+{
+ return typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::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;
+//
+// 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;
+
+#ifndef BOOST_MP_MATH_AVAILABLE
+namespace policies {
+
+template <typename... Args>
+class policy {};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void raise_rounding_error(T1, T2, T3, T4, T5)
+{
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Rounding error"));
}
-namespace multiprecision{
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void raise_overflow_error(T1, T2, T3, T4, T5)
+{
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Overflow error"));
+}
- 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 <typename T1, typename T2, typename T3, typename T4, typename T5>
+void raise_evaluation_error(T1, T2, T3, T4, T5)
+{
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Evaluation error"));
+}
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- return boost::math::asinh(arg, c99_error_policy());
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return asinh(value_type(arg));
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- return boost::math::acosh(arg, c99_error_policy());
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return acosh(value_type(arg));
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- return boost::math::atanh(arg, c99_error_policy());
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return atanh(value_type(arg));
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- return boost::math::cbrt(arg, c99_error_policy());
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return cbrt(value_type(arg));
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- return boost::math::erf(arg, c99_error_policy());
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return erf(value_type(arg));
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- return boost::math::erfc(arg, c99_error_policy());
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return erfc(value_type(arg));
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- return boost::math::expm1(arg, c99_error_policy());
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return expm1(value_type(arg));
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- multiprecision::number<Backend, ExpressionTemplates> result;
- result = boost::math::lgamma(arg, c99_error_policy());
- if((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg))
- {
- result = std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::infinity();
- errno = ERANGE;
- }
- return result;
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return lgamma(value_type(arg));
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- if((arg == 0) && std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::has_infinity)
- {
- errno = ERANGE;
- return 1 / arg;
- }
- return boost::math::tgamma(arg, c99_error_policy());
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return tgamma(value_type(arg));
- }
+template <typename T, typename... Args>
+struct is_policy
+{
+ static constexpr bool value = false;
+};
+
+template <typename... Args>
+struct is_policy<policy<Args...>>
+{
+ static constexpr bool value = true;
+};
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+} // namespace policies
+#endif
+
+} // namespace math
+
+namespace multiprecision {
+#ifdef BOOST_MP_MATH_AVAILABLE
+using c99_error_policy = ::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> >;
+
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
+ asinh
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ return boost::math::asinh(arg, c99_error_policy());
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+ asinh
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return asinh(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
+ acosh
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ return boost::math::acosh(arg, c99_error_policy());
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+ acosh
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return acosh(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
+ atanh
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ return boost::math::atanh(arg, c99_error_policy());
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+ atanh
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return atanh(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ return boost::math::cbrt(arg, c99_error_policy());
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return cbrt(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ return boost::math::erf(arg, c99_error_policy());
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return erf(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ return boost::math::erfc(arg, c99_error_policy());
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return erfc(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ return boost::math::expm1(arg, c99_error_policy());
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return expm1(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ multiprecision::number<Backend, ExpressionTemplates> result;
+ result = boost::math::lgamma(arg, c99_error_policy());
+ if ((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg))
{
- return lround(arg);
+ result = std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::infinity();
+ errno = ERANGE;
}
- template <class tag, class A1, class A2, class A3, class A4>
- inline long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+ return result;
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return lgamma(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ if ((arg == 0) && std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::has_infinity)
{
- return lround(arg);
+ errno = ERANGE;
+ return 1 / arg;
}
+ return boost::math::tgamma(arg, c99_error_policy());
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return tgamma(value_type(arg));
+}
+
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ return lround(arg);
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ return lround(arg);
+}
#ifndef BOOST_NO_LONG_LONG
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- return llround(arg);
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- return llround(arg);
- }
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR long long llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ return llround(arg);
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR long long llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ return llround(arg);
+}
#endif
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
- {
- return boost::math::log1p(arg, c99_error_policy());
- }
- template <class tag, class A1, class A2, class A3, class A4>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return log1p(value_type(arg));
- }
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
+ return boost::math::log1p(arg, c99_error_policy());
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(arg);
+ return log1p(value_type(arg));
+}
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
- {
- return boost::math::nextafter(a, b, c99_error_policy());
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
- inline multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
- {
- return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
- }
- template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
- {
- return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
- }
- template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
- {
- return boost::math::nextafter(a, b, c99_error_policy());
- }
- template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
- inline multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
- {
- return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
- }
- template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
- inline multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
- {
- return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
- }
- template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
- inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
- {
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
- return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
- }
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
+ return boost::math::nextafter(a, b, c99_error_policy());
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
+ return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
+}
+template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
+ return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
+}
+template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(a, b);
+ return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
+ return boost::math::nextafter(a, b, c99_error_policy());
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
+ return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
+}
+template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
+ return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
+}
+template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
+inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+{
+ using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<value_type> precision_guard(a, b);
+ return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
+}
+#endif // BOOST_MP_MATH_AVAILABLE
template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
-inline number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
+inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
{
- BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
- BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
+ static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
+ static_assert((std::is_convertible<B3, B1>::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 <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
-inline number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
+inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
{
- BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
- BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
+ static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
+ static_assert((std::is_convertible<B3, B1>::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 <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
-inline number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
+inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
{
- BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
- BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
+ static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
+ static_assert((std::is_convertible<B3, B1>::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 <class B, expression_template_option ET, class I>
-inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
- add(number<B, ET>& result, const I& a, const I& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
+add(number<B, ET>& result, const I& a, const I& b)
{
using default_ops::eval_add;
- typedef typename detail::canonical<I, B>::type canonical_type;
+ using canonical_type = typename detail::canonical<I, B>::type;
eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
return result;
}
template <class B, expression_template_option ET, class I>
-inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
- subtract(number<B, ET>& result, const I& a, const I& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
+subtract(number<B, ET>& result, const I& a, const I& b)
{
using default_ops::eval_subtract;
- typedef typename detail::canonical<I, B>::type canonical_type;
+ using canonical_type = typename detail::canonical<I, B>::type;
eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
return result;
}
template <class B, expression_template_option ET, class I>
-inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
- multiply(number<B, ET>& result, const I& a, const I& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
+multiply(number<B, ET>& result, const I& a, const I& b)
{
using default_ops::eval_multiply;
- typedef typename detail::canonical<I, B>::type canonical_type;
+ using canonical_type = typename detail::canonical<I, B>::type;
eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
return result;
}
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- return BOOST_MP_MOVE(trunc(number_type(v), pol));
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return std::move(trunc(number_type(v), pol));
}
template <class Backend, expression_template_option ExpressionTemplates, class Policy>
-inline number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
+inline BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
{
using default_ops::eval_trunc;
- number<Backend, ExpressionTemplates> result;
+ detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(v);
+ number<Backend, ExpressionTemplates> result;
eval_trunc(result.backend(), v.backend());
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- number_type r = trunc(v, pol);
- if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ number_type r(trunc(v, pol));
+ if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_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<int>();
}
template <class tag, class A1, class A2, class A3, class A4>
-inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
+inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
{
return itrunc(v, boost::math::policies::policy<>());
}
template <class Backend, expression_template_option ExpressionTemplates, class Policy>
-inline int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
{
- number<Backend, ExpressionTemplates> r = trunc(v, pol);
- if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
+ number<Backend, ExpressionTemplates> r(trunc(v, pol));
+ if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol);
return r.template convert_to<int>();
}
template <class Backend, expression_template_option ExpressionTemplates>
-inline int itrunc(const number<Backend, ExpressionTemplates>& v)
+inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v)
{
return itrunc(v, boost::math::policies::policy<>());
}
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- number_type r = trunc(v, pol);
- if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ number_type r(trunc(v, pol));
+ if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_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<long>();
}
template <class tag, class A1, class A2, class A3, class A4>
-inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
+inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
{
return ltrunc(v, boost::math::policies::policy<>());
}
template <class T, expression_template_option ExpressionTemplates, class Policy>
-inline long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
{
- number<T, ExpressionTemplates> r = trunc(v, pol);
- if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
+ number<T, ExpressionTemplates> r(trunc(v, pol));
+ if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol);
return r.template convert_to<long>();
}
template <class T, expression_template_option ExpressionTemplates>
-inline long ltrunc(const number<T, ExpressionTemplates>& v)
+inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v)
{
return ltrunc(v, boost::math::policies::policy<>());
}
#ifndef BOOST_NO_LONG_LONG
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- number_type r = trunc(v, pol);
- if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ number_type r(trunc(v, pol));
+ if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_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<boost::long_long_type>();
+ return r.template convert_to<long long>();
}
template <class tag, class A1, class A2, class A3, class A4>
-inline boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
+inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
{
return lltrunc(v, boost::math::policies::policy<>());
}
template <class T, expression_template_option ExpressionTemplates, class Policy>
-inline boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
{
- number<T, ExpressionTemplates> r = trunc(v, pol);
- if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
+ number<T, ExpressionTemplates> r(trunc(v, pol));
+ if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol);
- return r.template convert_to<boost::long_long_type>();
+ return r.template convert_to<long long>();
}
template <class T, expression_template_option ExpressionTemplates>
-inline boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v)
+inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const number<T, ExpressionTemplates>& v)
{
return lltrunc(v, boost::math::policies::policy<>());
}
#endif
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline typename detail::expression<tag, A1, A2, A3, A4>::result_type round(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type round(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- return BOOST_MP_MOVE(round(static_cast<number_type>(v), pol));
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return std::move(round(static_cast<number_type>(v), pol));
}
template <class T, expression_template_option ExpressionTemplates, class Policy>
-inline number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
+inline BOOST_MP_CXX14_CONSTEXPR number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
{
using default_ops::eval_round;
- number<T, ExpressionTemplates> result;
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
+ number<T, ExpressionTemplates> result;
eval_round(result.backend(), v.backend());
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- number_type r = round(v, pol);
- if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ number_type r(round(v, pol));
+ if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_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<int>();
}
template <class tag, class A1, class A2, class A3, class A4>
-inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
+inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
{
return iround(v, boost::math::policies::policy<>());
}
template <class T, expression_template_option ExpressionTemplates, class Policy>
-inline int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
{
- number<T, ExpressionTemplates> r = round(v, pol);
- if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
+ number<T, ExpressionTemplates> r(round(v, pol));
+ if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol);
return r.template convert_to<int>();
}
template <class T, expression_template_option ExpressionTemplates>
-inline int iround(const number<T, ExpressionTemplates>& v)
+inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v)
{
return iround(v, boost::math::policies::policy<>());
}
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- number_type r = round(v, pol);
- if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ number_type r(round(v, pol));
+ if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_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<long>();
}
template <class tag, class A1, class A2, class A3, class A4>
-inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
+inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
{
return lround(v, boost::math::policies::policy<>());
}
template <class T, expression_template_option ExpressionTemplates, class Policy>
-inline long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
{
- number<T, ExpressionTemplates> r = round(v, pol);
- if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
+ number<T, ExpressionTemplates> r(round(v, pol));
+ if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol);
return r.template convert_to<long>();
}
template <class T, expression_template_option ExpressionTemplates>
-inline long lround(const number<T, ExpressionTemplates>& v)
+inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v)
{
return lround(v, boost::math::policies::policy<>());
}
#ifndef BOOST_NO_LONG_LONG
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR long long llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- number_type r = round(v, pol);
- if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ number_type r(round(v, pol));
+ if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_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<boost::long_long_type>();
+ return r.template convert_to<long long>();
}
template <class tag, class A1, class A2, class A3, class A4>
-inline boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v)
+inline BOOST_MP_CXX14_CONSTEXPR long long llround(const detail::expression<tag, A1, A2, A3, A4>& v)
{
return llround(v, boost::math::policies::policy<>());
}
template <class T, expression_template_option ExpressionTemplates, class Policy>
-inline boost::long_long_type llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
+inline BOOST_MP_CXX14_CONSTEXPR long long llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
{
- number<T, ExpressionTemplates> r = round(v, pol);
- if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
+ number<T, ExpressionTemplates> r(round(v, pol));
+ if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol);
- return r.template convert_to<boost::long_long_type>();
+ return r.template convert_to<long long>();
}
template <class T, expression_template_option ExpressionTemplates>
-inline boost::long_long_type llround(const number<T, ExpressionTemplates>& v)
+inline BOOST_MP_CXX14_CONSTEXPR long long llround(const number<T, ExpressionTemplates>& v)
{
return llround(v, boost::math::policies::policy<>());
}
@@ -2299,64 +2992,68 @@ inline boost::long_long_type llround(const number<T, ExpressionTemplates>& v)
// not assigned to anything...
//
template <class T, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
{
using default_ops::eval_frexp;
- number<T, ExpressionTemplates> result;
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
+ number<T, ExpressionTemplates> result;
eval_frexp(result.backend(), v.backend(), pint);
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
- frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return std::move(frexp(static_cast<number_type>(v), pint));
}
template <class T, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
{
using default_ops::eval_frexp;
- number<T, ExpressionTemplates> result;
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
+ number<T, ExpressionTemplates> result;
eval_frexp(result.backend(), v.backend(), pint);
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
frexp(const detail::expression<tag, A1, A2, A3, A4>& v, int* pint)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return std::move(frexp(static_cast<number_type>(v), pint));
}
template <class T, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
{
using default_ops::eval_frexp;
- number<T, ExpressionTemplates> result;
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
+ number<T, ExpressionTemplates> result;
eval_frexp(result.backend(), v.backend(), pint);
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return std::move(frexp(static_cast<number_type>(v), pint));
}
template <class T, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, boost::long_long_type* pint)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long long* pint)
{
using default_ops::eval_frexp;
- number<T, ExpressionTemplates> result;
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
+ number<T, ExpressionTemplates> result;
eval_frexp(result.backend(), v.backend(), pint);
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
-frexp(const detail::expression<tag, A1, A2, A3, A4>& v, boost::long_long_type* pint)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long long* pint)
{
- typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
+ using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return std::move(frexp(static_cast<number_type>(v), pint));
}
//
// modf does not return an expression template since we require the
@@ -2364,755 +3061,778 @@ frexp(const detail::expression<tag, A1, A2, A3, A4>& v, boost::long_long_type* p
// not assigned to anything...
//
template <class T, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const number<T, ExpressionTemplates>& v, number<T, ExpressionTemplates>* pipart)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const number<T, ExpressionTemplates>& v, number<T, ExpressionTemplates>* pipart)
{
using default_ops::eval_modf;
- number<T, ExpressionTemplates> result;
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
+ number<T, ExpressionTemplates> result;
eval_modf(result.backend(), v.backend(), pipart ? &pipart->backend() : 0);
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class T, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const detail::expression<tag, A1, A2, A3, A4>& v, number<T, ExpressionTemplates>* pipart)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const detail::expression<tag, A1, A2, A3, A4>& v, number<T, ExpressionTemplates>* pipart)
{
using default_ops::eval_modf;
- number<T, ExpressionTemplates> result, arg(v);
+ detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
+ number<T, ExpressionTemplates> result, arg(v);
eval_modf(result.backend(), arg.backend(), pipart ? &pipart->backend() : 0);
- return BOOST_MP_MOVE(result);
+ return result;
}
//
// Integer square root:
//
template <class B, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
- sqrt(const number<B, ExpressionTemplates>& x)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
+sqrt(const number<B, ExpressionTemplates>& x)
{
using default_ops::eval_integer_sqrt;
number<B, ExpressionTemplates> s, r;
eval_integer_sqrt(s.backend(), r.backend(), x.backend());
return s;
}
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
+ sqrt(const detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ using default_ops::eval_integer_sqrt;
+ using result_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
+ detail::scoped_default_precision<result_type> precision_guard(arg);
+ result_type result, v(arg), r;
+ eval_integer_sqrt(result.backend(), r.backend(), v.backend());
+ return result;
+}
+
//
// fma:
//
namespace default_ops {
- struct fma_func
+struct fma_func
+{
+ template <class B, class T, class U, class V>
+ BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, const V& c) const
{
- template <class B, class T, class U, class V>
- void operator()(B& result, const T& a, const U& b, const V& c)const
- {
- eval_multiply_add(result, a, b, c);
- }
- };
-
+ eval_multiply_add(result, a, b, c);
+ }
+};
-}
+} // namespace default_ops
template <class Backend, class U, class V>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
- mpl::or_<
- is_number<U>,
- is_number_expression<U>,
- is_arithmetic<U>
- >,
- mpl::or_<
- is_number<V>,
- is_number_expression<V>,
- is_arithmetic<V>
- >
- >,
- detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
+ (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
+ detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V> >::type
fma(const number<Backend, et_on>& a, const U& b, const V& c)
{
return detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V>(
- default_ops::fma_func(), a, b, c);
+ default_ops::fma_func(), a, b, c);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U, class V>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point>,
- mpl::or_<
- is_number<U>,
- is_number_expression<U>,
- is_arithmetic<U>
- >,
- mpl::or_<
- is_number<V>,
- is_number_expression<V>,
- is_arithmetic<V>
- >
- >,
- detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
+ (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
+ detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V> >::type
fma(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, const V& c)
{
return detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V>(
- default_ops::fma_func(), a, b, c);
+ default_ops::fma_func(), a, b, c);
}
template <class Backend, class U, class V>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
- mpl::or_<
- is_number<U>,
- is_number_expression<U>,
- is_arithmetic<U>
- >,
- mpl::or_<
- is_number<V>,
- is_number_expression<V>,
- is_arithmetic<V>
- >
- >,
- number<Backend, et_off>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
+ (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
+ number<Backend, et_off> >::type
fma(const number<Backend, et_off>& a, const U& b, const V& c)
{
using default_ops::eval_multiply_add;
- number<Backend, et_off> result;
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
+ number<Backend, et_off> result;
eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class U, class Backend, class V>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
- is_arithmetic<U>,
- mpl::or_<
- is_number<V>,
- is_number_expression<V>,
- is_arithmetic<V>
- >
- >,
- detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
+ detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V> >::type
fma(const U& a, const number<Backend, et_on>& b, const V& c)
{
return detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V>(
- default_ops::fma_func(), a, b, c);
+ default_ops::fma_func(), a, b, c);
}
template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point>,
- is_arithmetic<U>,
- mpl::or_<
- is_number<V>,
- is_number_expression<V>,
- is_arithmetic<V>
- >
- >,
- detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
+ detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
fma(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, const V& c)
{
return detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(
- default_ops::fma_func(), a, b, c);
+ default_ops::fma_func(), a, b, c);
}
template <class U, class Backend, class V>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
- is_arithmetic<U>,
- mpl::or_<
- is_number<V>,
- is_number_expression<V>,
- is_arithmetic<V>
- >
- >,
- number<Backend, et_off>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
+ number<Backend, et_off> >::type
fma(const U& a, const number<Backend, et_off>& b, const V& c)
{
using default_ops::eval_multiply_add;
- number<Backend, et_off> result;
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
+ number<Backend, et_off> result;
eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class U, class V, class Backend>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
- is_arithmetic<U>,
- is_arithmetic<V>
- >,
- detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> >
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
+ boost::multiprecision::detail::is_arithmetic<V>::value,
+ detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> > >::type
fma(const U& a, const V& b, const number<Backend, et_on>& c)
{
return detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> >(
- default_ops::fma_func(), a, b, c);
+ default_ops::fma_func(), a, b, c);
}
template <class U, class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point>,
- is_arithmetic<U>,
- is_arithmetic<V>
- >,
- detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
+ boost::multiprecision::detail::is_arithmetic<V>::value,
+ detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
fma(const U& a, const V& b, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& c)
{
return detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(
- default_ops::fma_func(), a, b, c);
+ default_ops::fma_func(), a, b, c);
}
template <class U, class V, class Backend>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
- is_arithmetic<U>,
- is_arithmetic<V>
- >,
- number<Backend, et_off>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
+ boost::multiprecision::detail::is_arithmetic<U>::value &&
+ boost::multiprecision::detail::is_arithmetic<V>::value,
+ number<Backend, et_off> >::type
fma(const U& a, const V& b, const number<Backend, et_off>& c)
{
using default_ops::eval_multiply_add;
- number<Backend, et_off> result;
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
+ number<Backend, et_off> result;
eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
- return BOOST_MP_MOVE(result);
+ return result;
}
namespace default_ops {
- struct remquo_func
+struct remquo_func
+{
+ template <class B, class T, class U>
+ BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, int* pi) const
{
- template <class B, class T, class U>
- void operator()(B& result, const T& a, const U& b, int* pi)const
- {
- eval_remquo(result, a, b, pi);
- }
- };
+ eval_remquo(result, a, b, pi);
+ }
+};
-}
+} // namespace default_ops
template <class Backend, class U>
-inline typename enable_if_c<
- number_category<number<Backend, et_on> >::value == number_kind_floating_point,
- detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ number_category<number<Backend, et_on> >::value == number_kind_floating_point,
+ detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*> >::type
remquo(const number<Backend, et_on>& a, const U& b, int* pi)
{
return detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*>(
- default_ops::remquo_func(), a, b, pi);
+ default_ops::remquo_func(), a, b, pi);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U>
-inline typename enable_if_c<
- number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point,
- detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point,
+ detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*> >::type
remquo(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, int* pi)
{
return detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*>(
- default_ops::remquo_func(), a, b, pi);
+ default_ops::remquo_func(), a, b, pi);
}
template <class U, class Backend>
-inline typename enable_if_c<
- (number_category<number<Backend, et_on> >::value == number_kind_floating_point)
- && !is_number<U>::value && !is_number_expression<U>::value,
- detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
+ detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*> >::type
remquo(const U& a, const number<Backend, et_on>& b, int* pi)
{
return detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*>(
- default_ops::remquo_func(), a, b, pi);
+ default_ops::remquo_func(), a, b, pi);
}
template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<
- (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point)
- && !is_number<U>::value && !is_number_expression<U>::value,
- detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
+ detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*> >::type
remquo(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, int* pi)
{
return detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*>(
- default_ops::remquo_func(), a, b, pi);
+ default_ops::remquo_func(), a, b, pi);
}
template <class Backend, class U>
-inline typename enable_if_c<
- number_category<number<Backend, et_on> >::value == number_kind_floating_point,
- number<Backend, et_off>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ number_category<number<Backend, et_on> >::value == number_kind_floating_point,
+ number<Backend, et_off> >::type
remquo(const number<Backend, et_off>& a, const U& b, int* pi)
{
using default_ops::eval_remquo;
- number<Backend, et_off> result;
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
+ number<Backend, et_off> result;
eval_remquo(result.backend(), a.backend(), number<Backend, et_off>::canonical_value(b), pi);
- return BOOST_MP_MOVE(result);
+ return result;
}
template <class U, class Backend>
-inline typename enable_if_c<
-(number_category<number<Backend, et_on> >::value == number_kind_floating_point)
-&& !is_number<U>::value && !is_number_expression<U>::value,
-number<Backend, et_off>
->::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
+ number<Backend, et_off> >::type
remquo(const U& a, const number<Backend, et_off>& b, int* pi)
{
using default_ops::eval_remquo;
- number<Backend, et_off> result;
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
+ number<Backend, et_off> result;
eval_remquo(result.backend(), number<Backend, et_off>::canonical_value(a), b.backend(), pi);
- return BOOST_MP_MOVE(result);
+ return result;
}
-
template <class B, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
- sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
+sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
{
using default_ops::eval_integer_sqrt;
- number<B, ExpressionTemplates> s;
+ detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(x, r);
+ number<B, ExpressionTemplates> s;
+ eval_integer_sqrt(s.backend(), r.backend(), x.backend());
+ return s;
+}
+template <class B, expression_template_option ExpressionTemplates, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
+sqrt(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& arg, number<B, ExpressionTemplates>& r)
+{
+ using default_ops::eval_integer_sqrt;
+ detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(r);
+ number<B, ExpressionTemplates> s;
+ number<B, ExpressionTemplates> x(arg);
eval_integer_sqrt(s.backend(), r.backend(), x.backend());
return s;
}
-#define UNARY_OP_FUNCTOR(func, category)\
-namespace detail{\
-template <class Backend> \
-struct 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 <class tag, class A1, class A2, class A3, class A4> \
-inline typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category,\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , detail::expression<tag, A1, A2, A3, A4> > \
->::type \
-func(const detail::expression<tag, A1, A2, A3, A4>& arg)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , detail::expression<tag, A1, A2, A3, A4> \
-> (\
- detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
- , arg \
- );\
-}\
-template <class Backend> \
-inline typename enable_if_c<number_category<Backend>::value == category,\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> > \
->::type \
-func(const number<Backend, et_on>& arg)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> \
- >(\
- detail::BOOST_JOIN(func, _funct)<Backend>() \
- , arg \
- );\
-}\
-template <class Backend> \
-inline typename boost::enable_if_c<\
- boost::multiprecision::number_category<Backend>::value == category,\
- number<Backend, et_off> >::type \
-func(const number<Backend, et_off>& arg)\
-{\
- number<Backend, et_off> 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 <class Backend> \
-struct 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 <class Arithmetic> \
- void operator()(Backend& result, const Backend& arg, const Arithmetic& a)const\
- {\
- using default_ops:: BOOST_JOIN(eval_,func);\
- BOOST_JOIN(eval_,func)(result, arg, a);\
- }\
- template <class Arithmetic> \
- void operator()(Backend& result, const Arithmetic& arg, const Backend& a)const\
- {\
- using default_ops:: BOOST_JOIN(eval_,func);\
- BOOST_JOIN(eval_,func)(result, arg, a);\
+// clang-format off
+//
+// Regrettably, when the argument to a function is an rvalue we must return by value, and not return an
+// expression template, otherwise we can end up with dangling references.
+// See https://github.com/boostorg/multiprecision/issues/175.
+//
+#define UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> > ::type \
+ func(number<Backend, et_on>&& arg) \
+ { \
+ detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg); \
+ number<Backend, et_on> result; \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
+ return result; \
+ } \
+
+#define BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, const number<Backend, et_on>& a) \
+ { \
+ detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
+ number<Backend, et_on> result; \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
+ return result; \
+ } \
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(const number<Backend, et_on>& arg, number<Backend, et_on>&& a) \
+ { \
+ detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
+ number<Backend, et_on> result; \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
+ return result; \
+ } \
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, number<Backend, et_on>&& a) \
+ { \
+ detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
+ number<Backend, et_on> result; \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
+ return result; \
+ } \
+ template <class Backend, class tag, class A1, class A2, class A3, class A4> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
+ number<Backend, et_on> > ::type \
+ func(number<Backend, et_on>&& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
+ { \
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
+ } \
+ template <class tag, class A1, class A2, class A3, class A4, class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
+ number<Backend, et_on> > ::type \
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, number<Backend, et_on>&& a) \
+ { \
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
+ } \
+ template <class Backend, class Arithmetic> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
+ number<Backend, et_on> >::type \
+ func(number<Backend, et_on>&& arg, const Arithmetic& a) \
+ { \
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
+ number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
+ } \
+ template <class Backend, class Arithmetic> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
+ number<Backend, et_on> > ::type \
+ func(const Arithmetic& arg, number<Backend, et_on>&& a) \
+ { \
+ return detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
+ } \
+
+
+#define UNARY_OP_FUNCTOR(func, category) \
+ namespace detail { \
+ template <class Backend> \
+ struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
+ { \
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const \
+ { \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func) \
+ (result, arg); \
+ } \
+ template <class U> \
+ BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg) const \
+ { \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ Backend temp; \
+ BOOST_JOIN(eval_, func) \
+ (temp, arg); \
+ result = std::move(temp); \
+ } \
+ }; \
+ } \
+ \
+ template <class tag, class A1, class A2, class A3, class A4> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category, \
+ detail::expression<detail::function, \
+ detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ detail::expression<tag, A1, A2, A3, A4> > > ::type \
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg) \
+ { \
+ return detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg); \
+ } \
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, \
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, number<Backend, et_on> > > ::type \
+ func(const number<Backend, et_on>& arg) \
+ { \
+ return detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg); \
+ } \
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ boost::multiprecision::number_category<Backend>::value == category, \
+ number<Backend, et_off> >::type \
+ func(const number<Backend, et_off>& arg) \
+ { \
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
+ number<Backend, et_off> result; \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
+ return result; \
}\
-};\
-\
-}\
-template <class Backend> \
-inline typename enable_if_c<number_category<Backend>::value == category,\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> \
- , number<Backend, et_on> > \
->::type \
-func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> \
- , number<Backend, et_on> \
- >(\
- detail::BOOST_JOIN(func, _funct)<Backend>() \
- , arg,\
- a\
- );\
-}\
-template <class Backend, class tag, class A1, class A2, class A3, class A4> \
-inline typename enable_if_c<\
- (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> \
- , detail::expression<tag, A1, A2, A3, A4> > \
->::type \
-func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> \
- , detail::expression<tag, A1, A2, A3, A4> \
- >(\
- detail::BOOST_JOIN(func, _funct)<Backend>() \
- , arg,\
- a\
- );\
-}\
-template <class tag, class A1, class A2, class A3, class A4, class Backend> \
-inline typename enable_if_c<\
- (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , detail::expression<tag, A1, A2, A3, A4> \
- , number<Backend, et_on> > \
->::type \
-func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , detail::expression<tag, A1, A2, A3, A4> \
- , number<Backend, et_on> \
- >(\
- detail::BOOST_JOIN(func, _funct)<Backend>() \
- , arg,\
- a\
- );\
-}\
-template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
-inline typename enable_if_c<\
- (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category),\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , detail::expression<tag, A1, A2, A3, A4> \
- , detail::expression<tagb, A1b, A2b, A3b, A4b> > \
->::type \
-func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , detail::expression<tag, A1, A2, A3, A4> \
- , detail::expression<tagb, A1b, A2b, A3b, A4b> \
- >(\
- detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
- , arg,\
- a\
- );\
-}\
-template <class Backend, class Arithmetic> \
-inline typename enable_if_c<\
- is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> \
- , Arithmetic\
- > \
->::type \
-func(const number<Backend, et_on>& arg, const Arithmetic& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> \
- , Arithmetic\
- >(\
- detail::BOOST_JOIN(func, _funct)<Backend>() \
- , arg,\
- a\
- );\
-}\
-template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
-inline typename enable_if_c<\
- is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , detail::expression<tag, A1, A2, A3, A4> \
- , Arithmetic\
- > \
->::type \
-func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , detail::expression<tag, A1, A2, A3, A4> \
- , Arithmetic\
- >(\
- detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
- , arg,\
- a\
- );\
-}\
-template <class Backend, class Arithmetic> \
-inline typename enable_if_c<\
- is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , Arithmetic \
- , number<Backend, et_on> \
- > \
->::type \
-func(const Arithmetic& arg, const number<Backend, et_on>& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , Arithmetic \
- , number<Backend, et_on> \
- >(\
- detail::BOOST_JOIN(func, _funct)<Backend>() \
- , arg,\
- a\
- );\
-}\
-template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
-inline typename enable_if_c<\
- is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , Arithmetic \
- , detail::expression<tag, A1, A2, A3, A4> \
- > \
->::type \
-func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , Arithmetic \
- , detail::expression<tag, A1, A2, A3, A4> \
- >(\
- detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
- , arg,\
- a\
- );\
-}\
-template <class Backend> \
-inline typename enable_if_c<(number_category<Backend>::value == category),\
- number<Backend, et_off> >::type \
-func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a)\
-{\
- number<Backend, et_off> result;\
- using default_ops:: BOOST_JOIN(eval_,func);\
- BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a.backend());\
- return BOOST_MP_MOVE(result);\
-}\
-template <class Backend, class Arithmetic> \
-inline typename enable_if_c<\
- is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
- number<Backend, et_off> \
->::type \
-func(const number<Backend, et_off>& arg, const Arithmetic& a)\
-{\
- typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
- number<Backend, et_off> result;\
- using default_ops:: BOOST_JOIN(eval_,func);\
- BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), static_cast<canonical_type>(a));\
- return BOOST_MP_MOVE(result);\
-}\
-template <class Backend, class Arithmetic> \
-inline typename enable_if_c<\
- is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
- number<Backend, et_off> \
->::type \
-func(const Arithmetic& a, const number<Backend, et_off>& arg)\
-{\
- typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
- number<Backend, et_off> result;\
- using default_ops:: BOOST_JOIN(eval_,func);\
- BOOST_JOIN(eval_,func)(result.backend(), static_cast<canonical_type>(a), arg.backend());\
- return BOOST_MP_MOVE(result);\
-}\
-
-
-#define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)\
-template <class tag, class A1, class A2, class A3, class A4> \
-inline typename enable_if_c<\
- (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , detail::expression<tag, A1, A2, A3, A4> \
- , Arg2> \
->::type \
-func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
- , detail::expression<tag, A1, A2, A3, A4> \
- , Arg2\
- >(\
- detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
- , arg, a \
- );\
-}\
-template <class Backend> \
-inline typename enable_if_c<\
- (number_category<Backend>::value == category),\
- detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> \
- , Arg2> \
->::type \
-func(const number<Backend, et_on>& arg, Arg2 const& a)\
-{\
- return detail::expression<\
- detail::function\
- , detail::BOOST_JOIN(func, _funct)<Backend> \
- , number<Backend, et_on> \
- , Arg2\
- >(\
- detail::BOOST_JOIN(func, _funct)<Backend>() \
- , arg,\
- a\
- );\
-}\
-template <class Backend> \
-inline typename enable_if_c<\
- (number_category<Backend>::value == category),\
- number<Backend, et_off> >::type \
-func(const number<Backend, et_off>& arg, Arg2 const& a)\
-{\
- number<Backend, et_off> 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 <class Backend> \
-struct BOOST_JOIN(func, _funct)\
-{\
- template <class Arg>\
- void operator()(Backend& result, Backend const& arg, Arg a)const\
- {\
- using default_ops:: BOOST_JOIN(eval_,func);\
- BOOST_JOIN(eval_,func)(result, arg, a);\
+ UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
+
+#define BINARY_OP_FUNCTOR(func, category) \
+ namespace detail { \
+ template <class Backend> \
+ struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
+ { \
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Arithmetic> \
+ BOOST_MP_CXX14_CONSTEXPR 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<Backend>::canonical_value(a)); \
+ } \
+ template <class Arithmetic> \
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Arithmetic& arg, const Backend& a) const \
+ { \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func) \
+ (result, number<Backend>::canonical_value(arg), a); \
+ } \
+ template <class U> \
+ BOOST_MP_CXX14_CONSTEXPR 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 = std::move(r); \
+ } \
+ template <class U, class Arithmetic> \
+ BOOST_MP_CXX14_CONSTEXPR 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<Backend>::canonical_value(a)); \
+ result = std::move(r); \
+ } \
+ template <class U, class Arithmetic> \
+ BOOST_MP_CXX14_CONSTEXPR 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<Backend>::canonical_value(arg), a); \
+ result = std::move(r); \
+ } \
+ }; \
+ } \
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, detail::expression<detail::function, \
+ detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, number<Backend, et_on>, number<Backend, et_on> > > ::type \
+ func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a) \
+ { \
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ number<Backend, et_on>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
+ } \
+ template <class Backend, class tag, class A1, class A2, class A3, class A4> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > > ::type \
+ func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
+ { \
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
+ } \
+ template <class tag, class A1, class A2, class A3, class A4, class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > > ::type \
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a) \
+ { \
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
+ } \
+ template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category), \
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > > ::type \
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a) \
+ { \
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg, a); \
+ } \
+ template <class Backend, class Arithmetic> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
+ detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ number<Backend, et_on>, Arithmetic> > ::type \
+ func(const number<Backend, et_on>& arg, const Arithmetic& a) \
+ { \
+ return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
+ number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
+ } \
+ template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ is_compatible_arithmetic_type<Arithmetic, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
+ detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ detail::expression<tag, A1, A2, A3, A4>, Arithmetic> > ::type \
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a) \
+ { \
+ return detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ detail::expression<tag, A1, A2, A3, A4>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
+ } \
+ template <class Backend, class Arithmetic> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
+ detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ Arithmetic, number<Backend, et_on> > > ::type \
+ func(const Arithmetic& arg, const number<Backend, et_on>& a) \
+ { \
+ return detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
+ } \
+ template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ is_compatible_arithmetic_type<Arithmetic, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
+ detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ Arithmetic, detail::expression<tag, A1, A2, A3, A4> > > ::type \
+ func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
+ { \
+ return detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ Arithmetic, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
+ } \
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category), number<Backend, et_off> >::type \
+ func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a) \
+ { \
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
+ number<Backend, et_off> result; \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
+ return result; \
+ } \
+ template <class Backend, class Arithmetic> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
+ number<Backend, et_off> >::type \
+ func(const number<Backend, et_off>& arg, const Arithmetic& a) \
+ { \
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
+ number<Backend, et_off> result; \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func) \
+ (result.backend(), arg.backend(), number<Backend, et_off>::canonical_value(a)); \
+ return result; \
+ } \
+ template <class Backend, class Arithmetic> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
+ number<Backend, et_off> >::type \
+ func(const Arithmetic& a, const number<Backend, et_off>& arg) \
+ { \
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
+ number<Backend, et_off> result; \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func) \
+ (result.backend(), number<Backend, et_off>::canonical_value(a), arg.backend()); \
+ return result; \
}\
-};\
-\
-}\
-\
-HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
-
-namespace detail{
+ BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)
+
+#define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) \
+ template <class tag, class A1, class A2, class A3, class A4> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
+ detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ detail::expression<tag, A1, A2, A3, A4>, Arg2> > ::type \
+ func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a) \
+ { \
+ return detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
+ detail::expression<tag, A1, A2, A3, A4>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
+ } \
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ (number_category<Backend>::value == category), \
+ detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ number<Backend, et_on>, Arg2> > ::type \
+ func(const number<Backend, et_on>& arg, Arg2 const& a) \
+ { \
+ return detail::expression< \
+ detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
+ number<Backend, et_on>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
+ } \
+ template <class Backend> \
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
+ (number_category<Backend>::value == category), \
+ number<Backend, et_off> >::type \
+ func(const number<Backend, et_off>& arg, Arg2 const& a) \
+ { \
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
+ number<Backend, et_off> result; \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func) \
+ (result.backend(), arg.backend(), a); \
+ return result; \
+ }
+
+#define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category) \
+ namespace detail { \
+ template <class Backend> \
+ struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
+ { \
+ template <class Arg> \
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, Backend const& arg, Arg a) const \
+ { \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ BOOST_JOIN(eval_, func) \
+ (result, arg, a); \
+ } \
+ template <class U, class Arg> \
+ BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, Backend const& arg, Arg a) const \
+ { \
+ using default_ops::BOOST_JOIN(eval_, func); \
+ Backend temp; \
+ BOOST_JOIN(eval_, func) \
+ (temp, arg, a); \
+ result = std::move(temp); \
+ } \
+ }; \
+ } \
+ \
+ HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
+
+// clang-format on
+
+namespace detail {
template <class Backend>
struct abs_funct
{
- void operator()(Backend& result, const Backend& arg)const
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
{
using default_ops::eval_abs;
eval_abs(result, arg);
}
};
+template <class Backend>
+struct conj_funct
+{
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
+ {
+ using default_ops::eval_conj;
+ eval_conj(result, arg);
+ }
+};
+template <class Backend>
+struct proj_funct
+{
+ BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
+ {
+ using default_ops::eval_proj;
+ eval_proj(result, arg);
+ }
+};
-}
+} // namespace detail
template <class tag, class A1, class A2, class A3, class A4>
-inline detail::expression<
- detail::function
- , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
- , detail::expression<tag, A1, A2, A3, A4> >
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex,
+ detail::expression<
+ detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> > >::type
abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
{
- return detail::expression<
- detail::function
- , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
- , detail::expression<tag, A1, A2, A3, A4>
-> (
- detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>()
- , arg
- );
+ return detail::expression<
+ detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
+ detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
}
template <class Backend>
-inline detail::expression<
- detail::function
- , detail::abs_funct<Backend>
- , number<Backend, et_on> >
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex,
+ detail::expression<
+ detail::function, detail::abs_funct<Backend>, number<Backend, et_on> > >::type
abs(const number<Backend, et_on>& arg)
{
- return detail::expression<
- detail::function
- , detail::abs_funct<Backend>
- , number<Backend, et_on>
- >(
- detail::abs_funct<Backend>()
- , arg
- );
+ return detail::expression<
+ detail::function, detail::abs_funct<Backend>, number<Backend, et_on> >(
+ detail::abs_funct<Backend>(), arg);
}
template <class Backend>
-inline number<Backend, et_off>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, number<Backend, et_off> >::type
abs(const number<Backend, et_off>& arg)
{
- number<Backend, et_off> result;
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
+ number<Backend, et_off> result;
using default_ops::eval_abs;
eval_abs(result.backend(), arg.backend());
- return BOOST_MP_MOVE(result);
+ return result;
+}
+
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
+ detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
+conj(const detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ return detail::expression<
+ detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
+ detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
+}
+template <class Backend>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
+ detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >
+conj(const number<Backend, et_on>& arg)
+{
+ return detail::expression<
+ detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >(
+ detail::conj_funct<Backend>(), arg);
+}
+template <class Backend>
+inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
+conj(const number<Backend, et_off>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
+ number<Backend, et_off> result;
+ using default_ops::eval_conj;
+ eval_conj(result.backend(), arg.backend());
+ return result;
+}
+
+template <class tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
+ detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
+proj(const detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ return detail::expression<
+ detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
+ detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
+}
+template <class Backend>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
+ detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >
+proj(const number<Backend, et_on>& arg)
+{
+ return detail::expression<
+ detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >(
+ detail::proj_funct<Backend>(), arg);
+}
+template <class Backend>
+inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
+proj(const number<Backend, et_off>& arg)
+{
+ detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
+ number<Backend, et_off> result;
+ using default_ops::eval_proj;
+ eval_proj(result.backend(), arg.backend());
+ return result;
}
UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
@@ -3144,8 +3864,8 @@ 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(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(ldexp, long long, number_kind_floating_point)
+//HETERO_BINARY_OP_FUNCTOR_B(frexp, long long*, 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)
@@ -3162,15 +3882,36 @@ 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, long long, number_kind_floating_point)
+HETERO_BINARY_OP_FUNCTOR_B(scalbln, long long, number_kind_floating_point)
+
+//
+// Complex functions:
+//
+UNARY_OP_FUNCTOR(exp, number_kind_complex)
+UNARY_OP_FUNCTOR(log, number_kind_complex)
+UNARY_OP_FUNCTOR(log10, number_kind_complex)
+BINARY_OP_FUNCTOR(pow, number_kind_complex)
+UNARY_OP_FUNCTOR(sqrt, number_kind_complex)
+UNARY_OP_FUNCTOR(sin, number_kind_complex)
+UNARY_OP_FUNCTOR(cos, number_kind_complex)
+UNARY_OP_FUNCTOR(tan, number_kind_complex)
+UNARY_OP_FUNCTOR(asin, number_kind_complex)
+UNARY_OP_FUNCTOR(acos, number_kind_complex)
+UNARY_OP_FUNCTOR(atan, number_kind_complex)
+UNARY_OP_FUNCTOR(sinh, number_kind_complex)
+UNARY_OP_FUNCTOR(cosh, number_kind_complex)
+UNARY_OP_FUNCTOR(tanh, number_kind_complex)
+UNARY_OP_FUNCTOR(asinh, number_kind_complex)
+UNARY_OP_FUNCTOR(acosh, number_kind_complex)
+UNARY_OP_FUNCTOR(atanh, number_kind_complex)
//
// Integer functions:
//
BINARY_OP_FUNCTOR(gcd, number_kind_integer)
BINARY_OP_FUNCTOR(lcm, number_kind_integer)
-HETERO_BINARY_OP_FUNCTOR_B(pow, unsigned, number_kind_integer)
+HETERO_BINARY_OP_FUNCTOR(pow, unsigned, number_kind_integer)
#undef BINARY_OP_FUNCTOR
#undef UNARY_OP_FUNCTOR
@@ -3179,15 +3920,15 @@ HETERO_BINARY_OP_FUNCTOR_B(pow, unsigned, number_kind_integer)
// ilogb:
//
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
- ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
+ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
{
using default_ops::eval_ilogb;
return eval_ilogb(val.backend());
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == number_kind_floating_point, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type::backend_type::exponent_type>::type
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<detail::expression<tag, A1, A2, A3, A4> >::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<tag, A1, A2, A3, A4>& val)
{
using default_ops::eval_ilogb;
@@ -3197,36 +3938,42 @@ ilogb(const detail::expression<tag, A1, A2, A3, A4>& val)
} //namespace multiprecision
-namespace math{
+namespace math {
//
// Overload of Boost.Math functions that find the wrong overload when used with number:
//
-namespace detail{
- template <class T> T sinc_pi_imp(T);
- template <class T> T sinhc_pi_imp(T);
-}
+namespace detail {
+template <class T>
+T sinc_pi_imp(T);
+template <class T>
+T sinhc_pi_imp(T);
+} // namespace detail
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
{
- return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
+ boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
+ return std::move(detail::sinc_pi_imp(x));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
{
- return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
+ boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
+ return std::move(detail::sinc_pi_imp(x));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
{
- return BOOST_MP_MOVE(detail::sinhc_pi_imp(x));
+ boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
+ return std::move(detail::sinhc_pi_imp(x));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
{
- return BOOST_MP_MOVE(boost::math::sinhc_pi(x));
+ boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
+ return std::move(boost::math::sinhc_pi(x));
}
using boost::multiprecision::gcd;
@@ -3242,7 +3989,7 @@ namespace integer {
using boost::multiprecision::gcd;
using boost::multiprecision::lcm;
-}
+} // namespace integer
} // namespace boost
@@ -3257,4 +4004,3 @@ using boost::multiprecision::lcm;
#include <boost/multiprecision/detail/min_max.hpp>
#endif
-
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/digits.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/digits.hpp
new file mode 100644
index 0000000000..e942e081af
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/digits.hpp
@@ -0,0 +1,49 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2012 John Maddock. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_MP_DETAIL_DIGITS_HPP
+#define BOOST_MP_DETAIL_DIGITS_HPP
+
+namespace boost { namespace multiprecision { namespace detail {
+
+inline constexpr unsigned long digits10_2_2(unsigned long d10)
+{
+ return (d10 * 1000uL) / 301uL + ((d10 * 1000uL) % 301 ? 2u : 1u);
+}
+
+inline constexpr unsigned long digits2_2_10(unsigned long d2)
+{
+ return (d2 * 301uL) / 1000uL;
+}
+
+
+#if ULONG_MAX != SIZE_MAX
+
+inline constexpr std::size_t digits10_2_2(std::size_t d10)
+{
+ return (d10 * 1000uL) / 301uL + ((d10 * 1000uL) % 301 ? 2u : 1u);
+}
+
+inline constexpr std::size_t digits2_2_10(std::size_t d2)
+{
+ return (d2 * 301uL) / 1000uL;
+}
+
+template <class I>
+inline constexpr typename std::enable_if<sizeof(I) <= sizeof(unsigned long), unsigned long>::type digits10_2_2(I d10)
+{
+ return digits10_2_2(static_cast<unsigned long>(d10));
+}
+
+template <class I>
+inline constexpr typename std::enable_if<sizeof(I) <= sizeof(unsigned long), unsigned long>::type digits2_2_10(I d10)
+{
+ return digits2_2_10(static_cast<unsigned long>(d10));
+}
+#endif
+
+}}} // namespace boost::multiprecision::detail
+
+#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/empty_value.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/empty_value.hpp
new file mode 100644
index 0000000000..401e5eca83
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/empty_value.hpp
@@ -0,0 +1,87 @@
+/////////////////////////////////////////////////////////////////////
+// Copyright 2018 Glen Joseph Fernandes.
+// Copyright 2021 Matt Borland. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_MP_DETAIL_EMPTY_VALUE_HPP
+#define BOOST_MP_DETAIL_EMPTY_VALUE_HPP
+
+#include <utility>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40700)
+#define BOOST_DETAIL_EMPTY_VALUE_BASE
+#elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1800)
+#define BOOST_DETAIL_EMPTY_VALUE_BASE
+#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1800)
+#define BOOST_DETAIL_EMPTY_VALUE_BASE
+#elif defined(BOOST_CLANG) && !defined(__CUDACC__)
+#if __has_feature(is_empty) && __has_feature(is_final)
+#define BOOST_DETAIL_EMPTY_VALUE_BASE
+#endif
+#endif
+
+namespace boost { namespace multiprecision { namespace detail {
+
+template <typename T>
+struct use_empty_value_base
+{
+#if defined(BOOST_DETAIL_EMPTY_VALUE_BASE)
+ static constexpr bool value = __is_empty(T) && !__is_final(T);
+#else
+ static constexpr bool value = false;
+#endif
+};
+
+struct empty_init_t {};
+
+namespace empty_impl {
+
+template <typename T, unsigned N = 0,
+ bool E = boost::multiprecision::detail::use_empty_value_base<T>::value>
+class empty_value
+{
+private:
+ T value_;
+
+public:
+ using type = T;
+
+ empty_value() = default;
+ explicit empty_value(boost::multiprecision::detail::empty_init_t) : value_ {} {}
+
+ template <typename U, typename... Args>
+ empty_value(boost::multiprecision::detail::empty_init_t, U&& value, Args&&... args) :
+ value_ {std::forward<U>(value), std::forward<Args>(args)...} {}
+
+ const T& get() const noexcept { return value_; }
+ T& get() noexcept { return value_; }
+};
+
+template <typename T, unsigned N>
+class empty_value<T, N, true> : T
+{
+public:
+ using type = T;
+
+ empty_value() = default;
+ explicit empty_value(boost::multiprecision::detail::empty_init_t) : T{} {}
+
+ template <typename U, typename... Args>
+ empty_value(boost::multiprecision::detail::empty_init_t, U&& value, Args&&... args) :
+ T{std::forward<U>(value), std::forward<Args>(args)...} {}
+
+ const T& get() const noexcept { return *this; }
+ T& get() noexcept { return *this; }
+};
+
+} // Namespace empty impl
+
+using empty_impl::empty_value;
+
+BOOST_INLINE_CONSTEXPR empty_init_t empty_init = empty_init_t();
+
+}}} // Namespaces
+
+#endif // BOOST_MP_DETAIL_EMPTY_VALUE_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/endian.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/endian.hpp
new file mode 100644
index 0000000000..7732425682
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/endian.hpp
@@ -0,0 +1,35 @@
+////////////////////////////////////////////////////////////////
+// Copyright 2021 Matt Borland. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_MP_DETAIL_ENDIAN_HPP
+#define BOOST_MP_DETAIL_ENDIAN_HPP
+
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+#ifndef BOOST_MP_STANDALONE
+
+# include <boost/predef/other/endian.h>
+# define BOOST_MP_ENDIAN_BIG_BYTE BOOST_ENDIAN_BIG_BYTE
+# define BOOST_MP_ENDIAN_LITTLE_BYTE BOOST_ENDIAN_LITTLE_BYTE
+
+#elif defined(_WIN32)
+
+# define BOOST_MP_ENDIAN_BIG_BYTE 0
+# define BOOST_MP_ENDIAN_LITTLE_BYTE 1
+
+#elif defined(__BYTE_ORDER__)
+
+# define BOOST_MP_ENDIAN_BIG_BYTE (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+# define BOOST_MP_ENDIAN_LITTLE_BYTE (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+
+#else
+# error Could not determine endian type. Please disable standalone mode, and file an issue at https://github.com/boostorg/multiprecision
+#endif // Determine endianness
+
+static_assert((BOOST_MP_ENDIAN_BIG_BYTE || BOOST_MP_ENDIAN_LITTLE_BYTE)
+ && !(BOOST_MP_ENDIAN_BIG_BYTE && BOOST_MP_ENDIAN_LITTLE_BYTE),
+ "Inconsistent endianness detected. Please disable standalone mode, and file an issue at https://github.com/boostorg/multiprecision");
+
+#endif // BOOST_MP_DETAIL_ENDIAN_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/et_ops.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/et_ops.hpp
index 3778e01029..7511d9c145 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/et_ops.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/et_ops.hpp
@@ -6,10 +6,13 @@
#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:
+// Non-member operators for number which return expression templates.
+//
+// Note that operators taking rvalue-references DO NOT return expression templates
+// as this can lead to dangling references, see https://github.com/boostorg/multiprecision/issues/175.
//
// Unary operators first.
// Note that these *must* return by value, even though that's somewhat against
@@ -21,77 +24,181 @@ namespace boost{ namespace multiprecision{
// the reality is that no one ever uses unary operator+ anyway...!
//
template <class B, expression_template_option ExpressionTemplates>
-inline BOOST_CONSTEXPR const number<B, ExpressionTemplates> operator + (const number<B, ExpressionTemplates>& v) { return v; }
+inline constexpr const number<B, ExpressionTemplates> operator+(const number<B, ExpressionTemplates>& v) { return v; }
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline BOOST_CONSTEXPR const detail::expression<tag, Arg1, Arg2, Arg3, Arg4> operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return v; }
+inline constexpr const detail::expression<tag, Arg1, Arg2, Arg3, Arg4> operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return v; }
template <class B>
-inline detail::expression<detail::negate, number<B, et_on> > operator - (const number<B, et_on>& v)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, number<B, et_on> > operator-(const number<B, et_on>& v)
{
- BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
+ static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
return detail::expression<detail::negate, number<B, et_on> >(v);
}
+// rvalue ops:
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on> operator-(number<B, et_on>&& v)
+{
+ static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
+ v.backend().negate();
+ return std::move(v);
+}
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v)
{
- BOOST_STATIC_ASSERT_MSG((is_signed_number<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value), "Negating an unsigned type results in ill-defined behavior.");
+ static_assert((is_signed_number<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value), "Negating an unsigned type results in ill-defined behavior.");
return detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v);
}
template <class B>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::complement_immediates, number<B, et_on> > >::type
- operator ~ (const number<B, et_on>& v) { return detail::expression<detail::complement_immediates, number<B, et_on> >(v); }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::complement_immediates, number<B, et_on> > >::type
+operator~(const number<B, et_on>& v) { return detail::expression<detail::complement_immediates, number<B, et_on> >(v); }
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator~(number<B, et_on>&& v)
+{
+ using default_ops::eval_complement;
+ eval_complement(v.backend(), v.backend());
+ return std::move(v);
+}
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
- detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator ~ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
+ detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator~(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
//
// Then addition:
//
template <class B>
-inline detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
- operator + (const number<B, et_on>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
+operator+(const number<B, et_on>& a, const number<B, et_on>& b)
{
return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b);
}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator+(number<B, et_on>&& a, const number<B, et_on>& b)
+{
+ using default_ops::eval_add;
+ eval_add(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator+(const number<B, et_on>& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_add;
+ eval_add(b.backend(), a.backend());
+ return std::move(b);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator+(number<B, et_on>&& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_add;
+ eval_add(a.backend(), b.backend());
+ return std::move(a);
+}
+
+template <class B, class V>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::add_immediates, number<B, et_on>, V> >::type
+operator+(const number<B, et_on>& a, const V& b)
+{
+ return detail::expression<detail::add_immediates, number<B, et_on>, V>(a, b);
+}
+
template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::add_immediates, number<B, et_on>, V > >::type
- operator + (const number<B, et_on>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
+operator+(number<B, et_on>&& a, const V& b)
{
- return detail::expression<detail::add_immediates, number<B, et_on>, V >(a, b);
+ using default_ops::eval_add;
+ eval_add(a.backend(), number<B, et_on>::canonical_value(b));
+ return std::move(a);
}
+
template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
- operator + (const V& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
+operator+(const V& a, const number<B, et_on>& b)
{
return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b);
}
+
+template <class V, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
+operator+(const V& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_add;
+ eval_add(b.backend(), number<B, et_on>::canonical_value(a));
+ return std::move(b);
+}
+
+template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+operator+(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+
+template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET> >::value,
+ typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator+(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a += b;
+ return std::move(a);
+}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator + (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET> >::value,
+ typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator+(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
- operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
{
return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
}
+
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
+operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ b += a;
+ return std::move(b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
+operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
+}
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
{
return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
+operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
- return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+ return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
}
template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator + (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator+(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
@@ -99,110 +206,247 @@ inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expr
// Fused multiply add:
//
template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>,
- detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >::type
- operator + (const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
+ detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >::type
+operator+(const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V>(b.left(), b.right(), a);
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>,
- detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >::type
- operator + (const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
+ detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >::type
+operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V>(a.left(), a.right(), b);
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
- operator + (const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
+operator+(const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a);
+}
+
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
+operator+(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a += b;
+ return std::move(a);
+}
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
+operator+(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a);
}
+
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
- operator + (const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
+operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
{
return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
}
+
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
+operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ b += a;
+ return std::move(b);
+}
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
+operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
+}
+
//
// Fused multiply subtract:
//
template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>,
- detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> > >::type
- operator - (const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
+ detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> > >::type
+operator-(const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
{
- return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >
- (detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V>(b.left(), b.right(), a));
+ return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >(detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V>(b.left(), b.right(), a));
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>,
- detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >::type
- operator - (const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
+ detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >::type
+operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
return detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V>(a.left(), a.right(), b);
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >
- operator - (const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >
+operator-(const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
{
- return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >
- (detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a));
+ return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >(detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a));
}
+
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type>::type
+operator-(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a -= b;
+ return std::move(a);
+}
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type>::type
+operator-(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >(detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a));
+}
+
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
- operator - (const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
+operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
{
return detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
}
+
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type
+operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ return detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
+}
+
//
// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
//
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::minus, number<B, ET>, Arg1>
- operator + (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
+operator+(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
+}
+
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
+operator+(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a -= b.left_ref();
+ return std::move(a);
+}
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
+operator+(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
}
+
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
+operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
+}
+
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
+operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ b -= a.left_ref();
+ return std::move(b);
+}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::minus, number<B, ET>, Arg1>
- operator + (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
+operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
}
+
template <class B>
-inline detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
- operator + (const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
+operator+(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >::result_type
+operator+(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ using default_ops::eval_subtract;
+ eval_subtract(a.backend(), b.left_ref().backend());
+ return std::move(a);
+}
+
template <class B>
-inline detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
- operator + (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
+operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
{
return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref());
}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >::result_type
+operator+(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_subtract;
+ eval_subtract(b.backend(), a.left_ref().backend());
+ return std::move(b);
+}
+
template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
- operator + (const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
+operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
{
return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(b, a.left_ref());
}
template <class B, class B2, expression_template_option ET>
-inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
- operator + (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
+operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
+{
+ return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
+}
+
+template <class B, class B2, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
+operator+(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
{
return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
}
+
template <class B2, expression_template_option ET, class B>
-inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
- operator + (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
+operator+(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
}
+
+template <class B2, expression_template_option ET, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
+operator+(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
+}
+
template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
- operator + (const detail::expression<detail::negate, number<B, et_on> >& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
+operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b.left_ref()));
}
@@ -210,50 +454,137 @@ inline detail::expression<detail::negate, detail::expression<detail::add_immedia
// Subtraction:
//
template <class B>
-inline detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
- operator - (const number<B, et_on>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
+operator-(const number<B, et_on>& a, const number<B, et_on>& b)
{
return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b);
}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator-(number<B, et_on>&& a, const number<B, et_on>& b)
+{
+ using default_ops::eval_subtract;
+ eval_subtract(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator-(const number<B, et_on>& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_subtract;
+ eval_subtract(b.backend(), a.backend());
+ b.backend().negate();
+ return std::move(b);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator-(number<B, et_on>&& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_subtract;
+ eval_subtract(a.backend(), b.backend());
+ return std::move(a);
+}
+
template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::subtract_immediates, number<B, et_on>, V > >::type
- operator - (const number<B, et_on>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, number<B, et_on>, V> >::type
+operator-(const number<B, et_on>& a, const V& b)
{
- return detail::expression<detail::subtract_immediates, number<B, et_on>, V >(a, b);
+ return detail::expression<detail::subtract_immediates, number<B, et_on>, V>(a, b);
}
+
+template <class B, class V>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
+operator-(number<B, et_on>&& a, const V& b)
+{
+ using default_ops::eval_subtract;
+ eval_subtract(a.backend(), number<B, et_on>::canonical_value(b));
+ return std::move(a);
+}
+
template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
- operator - (const V& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
+operator-(const V& a, const number<B, et_on>& b)
{
return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(a, b);
}
+
+template <class V, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
+operator-(const V& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_subtract;
+ eval_subtract(b.backend(), number<B, et_on>::canonical_value(a));
+ b.backend().negate();
+ return std::move(b);
+}
+
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator - (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+operator-(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
+
+template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator-(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a -= b;
+ return std::move(a);
+}
+template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator-(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
+}
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
- operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
+operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ b -= a;
+ b.backend().negate();
+ return std::move(b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
+operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
}
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
{
return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
+operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
- return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+ return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
}
template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator - (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator-(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
@@ -261,103 +592,274 @@ inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expr
// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
//
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::plus, number<B, ET>, Arg1>
- operator - (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, number<B, ET>, Arg1>
+operator-(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
}
+
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type>::type
+operator-(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a += b.left_ref();
+ return std::move(a);
+}
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type>::type
+operator-(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
+}
+
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >
- operator - (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >
+operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
{
return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(
- detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
+ detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
+}
+
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type>::type
+operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ b += a.left_ref();
+ b.backend().negate();
+ return std::move(b);
+}
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type>::type
+operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
}
+
template <class B>
-inline detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
- operator - (const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
+operator-(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >::result_type
+operator-(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ using default_ops::eval_add;
+ eval_add(a.backend(), b.left_ref().backend());
+ return std::move(a);
+}
+
template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
- operator - (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
+operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
{
return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
- detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
+ detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
+operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_add;
+ eval_add(b.backend(), a.left_ref().backend());
+ b.backend().negate();
+ return std::move(b);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
+operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
+ detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
+}
+
template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, V > > >::type
- operator - (const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, V> > >::type
+operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
{
- return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, V > >(detail::expression<detail::add_immediates, number<B, et_on>, V >(a.left_ref(), b));
+ return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, V> >(detail::expression<detail::add_immediates, number<B, et_on>, V>(a.left_ref(), b));
}
template <class B, class B2, expression_template_option ET>
-inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > > >::type
- operator - (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > > >::type
+operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > >(detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
+}
+
+template <class B, class B2, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
+operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
{
return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > >(detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
}
+
template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
- operator - (const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
+operator-(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b.left_ref());
}
template <class B2, expression_template_option ET, class B>
-inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> > >::type
- operator - (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> > >::type
+operator-(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
}
+
+template <class B2, expression_template_option ET, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
+operator-(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
+}
+
//
// Multiplication:
//
template <class B>
-inline detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >
- operator * (const number<B, et_on>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >
+operator*(const number<B, et_on>& a, const number<B, et_on>& b)
{
return detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b);
}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator*(number<B, et_on>&& a, const number<B, et_on>& b)
+{
+ using default_ops::eval_multiply;
+ eval_multiply(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator*(const number<B, et_on>& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_multiply;
+ eval_multiply(b.backend(), a.backend());
+ return std::move(b);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator*(number<B, et_on>&& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_multiply;
+ eval_multiply(a.backend(), b.backend());
+ return std::move(a);
+}
+
+template <class B, class V>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >::type
+operator*(const number<B, et_on>& a, const V& b)
+{
+ return detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a, b);
+}
+
template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::multiply_immediates, number<B, et_on>, V > >::type
- operator * (const number<B, et_on>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
+operator*(number<B, et_on>&& a, const V& b)
{
- return detail::expression<detail::multiply_immediates, number<B, et_on>, V >(a, b);
+ using default_ops::eval_multiply;
+ eval_multiply(a.backend(), number<B, et_on>::canonical_value(b));
+ return std::move(a);
}
+
template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::multiply_immediates, V, number<B, et_on> > >::type
- operator * (const V& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::multiply_immediates, V, number<B, et_on> > >::type
+operator*(const V& a, const number<B, et_on>& b)
{
return detail::expression<detail::multiply_immediates, V, number<B, et_on> >(a, b);
}
+
+template <class V, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
+operator*(const V& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_multiply;
+ eval_multiply(b.backend(), number<B, et_on>::canonical_value(a));
+ return std::move(b);
+}
+
+template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+operator*(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+
+template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator*(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a *= b;
+ return std::move(a);
+}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator * (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator*(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
- operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
{
return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
}
+
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
+operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ b *= a;
+ return std::move(b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
+operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
+}
+
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
{
return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
+operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
- return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+ return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
}
template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator * (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator*(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
@@ -365,109 +867,246 @@ inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expr
// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
//
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
- operator * (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
+operator*(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
- detail::expression<detail::multiplies, number<B, ET>, Arg1> (a, b.left_ref()));
+ detail::expression<detail::multiplies, number<B, ET>, Arg1>(a, b.left_ref()));
}
+
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >::result_type
+operator*(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
+ detail::expression<detail::multiplies, number<B, ET>, Arg1>(a, b.left_ref()));
+}
+
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
+operator*(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
+ detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
+}
+
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
- operator * (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >::result_type
+operator*(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
- detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
+ detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
+}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
+operator*(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
+ detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
+}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
+operator*(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ a *= b.left_ref();
+ a.backend().negate();
+ return std::move(a);
}
template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
- operator * (const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
+operator*(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
- detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
+ detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
}
+
template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
- operator * (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
+operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
{
return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
- detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
+ detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
+}
+
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
+operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
+{
+ b *= a.left_ref();
+ b.backend().negate();
+ return std::move(b);
}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
+operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
+ detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
+}
+
template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V > > >::type
- operator * (const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> > >::type
+operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
{
- return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V > > (
- detail::expression<detail::multiply_immediates, number<B, et_on>, V >(a.left_ref(), b));
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
+ detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a.left_ref(), b));
}
template <class B, class B2, expression_template_option ET>
-inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
- operator * (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
+operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
{
- return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > (
- detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
+ detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
}
+
+template <class B, class B2, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
+operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
+ detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
+}
+
template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V > > >::type
- operator * (const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> > >::type
+operator*(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
+ detail::expression<detail::multiply_immediates, number<B, et_on>, V>(b.left_ref(), a));
+}
+template <class B2, expression_template_option ET, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
+operator*(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
- return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V > >(
- detail::expression<detail::multiply_immediates, number<B, et_on>, V >(b.left_ref(), a));
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
+ detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
}
+
template <class B2, expression_template_option ET, class B>
-inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
- operator * (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
+operator*(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
- detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
+ detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
}
+
//
// Division:
//
template <class B>
-inline detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >
- operator / (const number<B, et_on>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >
+operator/(const number<B, et_on>& a, const number<B, et_on>& b)
{
return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator/(number<B, et_on>&& a, const number<B, et_on>& b)
+{
+ using default_ops::eval_divide;
+ eval_divide(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator/(const number<B, et_on>& a, number<B, et_on>&& b)
+{
+ return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
+operator/(number<B, et_on>&& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_divide;
+ eval_divide(a.backend(), b.backend());
+ return std::move(a);
+}
template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::divide_immediates, number<B, et_on>, V > >::type
- operator / (const number<B, et_on>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::divide_immediates, number<B, et_on>, V> >::type
+operator/(const number<B, et_on>& a, const V& b)
{
- return detail::expression<detail::divide_immediates, number<B, et_on>, V >(a, b);
+ return detail::expression<detail::divide_immediates, number<B, et_on>, V>(a, b);
+}
+template <class B, class V>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
+operator/(number<B, et_on>&& a, const V& b)
+{
+ using default_ops::eval_divide;
+ eval_divide(a.backend(), number<B, et_on>::canonical_value(b));
+ return std::move(a);
}
template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::divide_immediates, V, number<B, et_on> > >::type
- operator / (const V& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::divide_immediates, V, number<B, et_on> > >::type
+operator/(const V& a, const number<B, et_on>& b)
+{
+ return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
+}
+template <class V, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
+operator/(const V& a, number<B, et_on>&& b)
{
return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator / (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+operator/(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
+template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator/(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a /= b;
+ return std::move(a);
+}
+template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator/(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
+}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
- operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
+operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
{
return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
+operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
- return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+ return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
}
template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator / (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator/(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
@@ -475,119 +1114,239 @@ inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expr
// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
//
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >
- operator / (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >
+operator/(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
- detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
+ detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
+}
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename std::enable_if<
+ std::is_same<typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type>::type
+operator/(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a /= b.left_ref();
+ a.backend().negate();
+ return std::move(a);
+}
+template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
+ typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type>::type
+operator/(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
+ detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >
- operator / (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >
+operator/(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
{
return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
- detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
+ detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
+}
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >::result_type
+operator/(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
+ detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
+operator/(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
+ detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
}
template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
- operator / (const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >::result_type
+operator/(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ a /= b.left_ref();
+ a.backend().negate();
+ return std::move(a);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
+operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
{
return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
- detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
+ detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
}
template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
- operator / (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >::result_type
+operator/(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
{
return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
- detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
+ detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
}
template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V > > >::type
- operator / (const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V> > >::type
+operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V> >(
+ detail::expression<detail::divide_immediates, number<B, et_on>, V>(a.left_ref(), b));
+}
+template <class B, class B2, expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > > >::type
+operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
{
- return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V > >(
- detail::expression<detail::divide_immediates, number<B, et_on>, V>(a.left_ref(), b));
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
+ detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
}
template <class B, class B2, expression_template_option ET>
-inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > > >::type
- operator / (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
+operator/(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
{
return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
- detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
+ detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
}
template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > > >::type
- operator / (const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > > >::type
+operator/(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > >(
- detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b.left_ref()));
+ detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b.left_ref()));
+}
+template <class B2, expression_template_option ET, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > > >::type
+operator/(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
+ detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
}
template <class B2, expression_template_option ET, class B>
-inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > > >::type
- operator / (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >::result_type>::value, number<B, et_on> >::type
+operator/(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
- detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
+ detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
}
//
// Modulus:
//
template <class B>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> > >::type
- operator % (const number<B, et_on>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> > >::type
+operator%(const number<B, et_on>& a, const number<B, et_on>& b)
+{
+ return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator%(number<B, et_on>&& a, const number<B, et_on>& b)
+{
+ using default_ops::eval_modulus;
+ eval_modulus(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator%(const number<B, et_on>& a, number<B, et_on>&& b)
{
return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator%(number<B, et_on>&& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_modulus;
+ eval_modulus(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B, class V>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, number<B, et_on> >::value,
+ detail::expression<detail::modulus_immediates, number<B, et_on>, V> >::type
+operator%(const number<B, et_on>& a, const V& b)
+{
+ return detail::expression<detail::modulus_immediates, number<B, et_on>, V>(a, b);
+}
template <class B, class V>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
- detail::expression<detail::modulus_immediates, number<B, et_on>, V > >::type
- operator % (const number<B, et_on>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, number<B, et_on> >::value,
+ number<B, et_on> >::type
+operator%(number<B, et_on>&& a, const V& b)
{
- return detail::expression<detail::modulus_immediates, number<B, et_on>, V >(a, b);
+ using default_ops::eval_modulus;
+ eval_modulus(a.backend(), number<B, et_on>::canonical_value(b));
+ return std::move(a);
}
template <class V, class B>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
- detail::expression<detail::modulus_immediates, V, number<B, et_on> > >::type
- operator % (const V& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ detail::expression<detail::modulus_immediates, V, number<B, et_on> > >::type
+operator%(const V& a, const number<B, et_on>& b)
+{
+ return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
+}
+template <class V, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ number<B, et_on> >::type
+operator%(const V& a, number<B, et_on>&& b)
{
return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator % (const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator%(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
+operator%(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a %= b;
+ return std::move(a);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
+operator%(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
- operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
+operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
+{
+ return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
+operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
- detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
- operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
+ detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
+operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
{
return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
- && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
- detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
+ detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
+operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
- return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+ return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
}
template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
- && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
- detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator % (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
+ detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator%(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
@@ -595,15 +1354,23 @@ inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::ex
// Left shift:
//
template <class B, class I>
-inline typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), detail::expression<detail::shift_left, number<B, et_on>, I > >::type
- operator << (const number<B, et_on>& a, const I& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), detail::expression<detail::shift_left, number<B, et_on>, I> >::type
+operator<<(const number<B, et_on>& a, const I& b)
{
return detail::expression<detail::shift_left, number<B, et_on>, I>(a, b);
}
+template <class B, class I>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_on> >::type
+operator<<(number<B, et_on>&& a, const I& b)
+{
+ using default_ops::eval_left_shift;
+ eval_left_shift(a.backend(), b);
+ return std::move(a);
+}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
-inline typename enable_if_c<is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
- detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
- operator << (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
+ detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
+operator<<(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
{
return detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
}
@@ -611,17 +1378,25 @@ inline typename enable_if_c<is_integral<I>::value && (number_category<typename d
// Right shift:
//
template <class B, class I>
-inline typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer),
- detail::expression<detail::shift_right, number<B, et_on>, I > >::type
- operator >> (const number<B, et_on>& a, const I& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer),
+ detail::expression<detail::shift_right, number<B, et_on>, I> >::type
+operator>>(const number<B, et_on>& a, const I& b)
{
return detail::expression<detail::shift_right, number<B, et_on>, I>(a, b);
}
+template <class B, class I>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer),
+ number<B, et_on> >::type
+operator>>(number<B, et_on>&& a, const I& b)
+{
+ using default_ops::eval_right_shift;
+ eval_right_shift(a.backend(), b);
+ return std::move(a);
+}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
-inline typename enable_if_c<is_integral<I>::value
- && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
- detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
- operator >> (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
+ detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
+operator>>(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
{
return detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
}
@@ -629,62 +1404,141 @@ inline typename enable_if_c<is_integral<I>::value
// Bitwise AND:
//
template <class B>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> > >::type
- operator & (const number<B, et_on>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> > >::type
+operator&(const number<B, et_on>& a, const number<B, et_on>& b)
{
return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> >(a, b);
}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator&(number<B, et_on>&& a, const number<B, et_on>& b)
+{
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator&(const number<B, et_on>& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(b.backend(), a.backend());
+ return std::move(b);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator&(number<B, et_on>&& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(a.backend(), b.backend());
+ return std::move(a);
+}
template <class B, class V>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
- && (number_category<B>::value == number_kind_integer),
- detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V > >::type
- operator & (const number<B, et_on>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V> >::type
+operator&(const number<B, et_on>& a, const V& b)
{
- return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V >(a, b);
+ return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V>(a, b);
+}
+template <class B, class V>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ number<B, et_on> >::type
+operator&(number<B, et_on>&& a, const V& b)
+{
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(a.backend(), number<B, et_on>::canonical_value(b));
+ return std::move(a);
}
template <class V, class B>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
- && (number_category<B>::value == number_kind_integer),
- detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> > >::type
- operator & (const V& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> > >::type
+operator&(const V& a, const number<B, et_on>& b)
{
return detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> >(a, b);
}
+template <class V, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ number<B, et_on> >::type
+operator&(const V& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(b.backend(), number<B, et_on>::canonical_value(a));
+ return std::move(b);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator&(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator & (const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
+operator&(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a &= b;
+ return std::move(a);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
+operator&(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
- operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
+operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
+{
+ return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
+operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
+{
+ b &= a;
+ return std::move(b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
+operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
- detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
- operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
+ detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
+operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
{
return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
- && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
- detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
+ detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
+operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
- return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+ return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
}
template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
- && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
- detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator & (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
+ detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator&(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
@@ -692,62 +1546,141 @@ inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::ex
// Bitwise OR:
//
template <class B>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> > >::type
- operator| (const number<B, et_on>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> > >::type
+operator|(const number<B, et_on>& a, const number<B, et_on>& b)
{
return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> >(a, b);
}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator|(number<B, et_on>&& a, const number<B, et_on>& b)
+{
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator|(const number<B, et_on>& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(b.backend(), a.backend());
+ return std::move(b);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator|(number<B, et_on>&& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(a.backend(), b.backend());
+ return std::move(a);
+}
template <class B, class V>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
- && (number_category<B>::value == number_kind_integer),
- detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V > >::type
- operator| (const number<B, et_on>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V> >::type
+operator|(const number<B, et_on>& a, const V& b)
{
- return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V >(a, b);
+ return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V>(a, b);
+}
+template <class B, class V>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ number<B, et_on> >::type
+operator|(number<B, et_on>&& a, const V& b)
+{
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(a.backend(), number<B, et_on>::canonical_value(b));
+ return std::move(a);
}
template <class V, class B>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
- && (number_category<B>::value == number_kind_integer),
- detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> > >::type
- operator| (const V& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> > >::type
+operator|(const V& a, const number<B, et_on>& b)
{
return detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> >(a, b);
}
+template <class V, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ number<B, et_on> >::type
+operator|(const V& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(b.backend(), number<B, et_on>::canonical_value(a));
+ return std::move(b);
+}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator| (const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator|(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator|(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a |= b;
+ return std::move(a);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator|(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
+operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
+{
+ return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
+}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
- operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
+operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
+{
+ b |= a;
+ return std::move(b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
+operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
- detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
- operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
+ detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
+operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
{
return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
- && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
- detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
+ detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
+operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
- return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+ return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
}
template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
- && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
- detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator| (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
+ detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator|(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
@@ -755,65 +1688,144 @@ inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::ex
// Bitwise XOR:
//
template <class B>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> > >::type
- operator^ (const number<B, et_on>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> > >::type
+operator^(const number<B, et_on>& a, const number<B, et_on>& b)
{
return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> >(a, b);
}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator^(number<B, et_on>&& a, const number<B, et_on>& b)
+{
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator^(const number<B, et_on>& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(b.backend(), a.backend());
+ return std::move(b);
+}
+template <class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ number<B, et_on> >::type
+operator^(number<B, et_on>&& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(a.backend(), b.backend());
+ return std::move(a);
+}
+template <class B, class V>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V> >::type
+operator^(const number<B, et_on>& a, const V& b)
+{
+ return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V>(a, b);
+}
template <class B, class V>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
- && (number_category<B>::value == number_kind_integer),
- detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V > >::type
- operator^ (const number<B, et_on>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ number<B, et_on> >::type
+operator^(number<B, et_on>&& a, const V& b)
{
- return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V >(a, b);
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(a.backend(), number<B, et_on>::canonical_value(b));
+ return std::move(a);
}
template <class V, class B>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
- && (number_category<B>::value == number_kind_integer),
- detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> > >::type
- operator^ (const V& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> > >::type
+operator^(const V& a, const number<B, et_on>& b)
{
return detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> >(a, b);
}
+template <class V, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
+ number<B, et_on> >::type
+operator^(const V& a, number<B, et_on>&& b)
+{
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(b.backend(), number<B, et_on>::canonical_value(a));
+ return std::move(b);
+}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator^ (const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator^(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator^(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ a ^= b;
+ return std::move(a);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
+operator^(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
+ detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
+operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
+{
+ return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ std::is_same<typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
+operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
+{
+ b ^= a;
+ return std::move(b);
+}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline typename enable_if_c<number_category<B>::value == number_kind_integer,
- detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
- operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ !std::is_same<typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
+ && number_category<B>::value == number_kind_integer,
+ typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
+operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
- detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
- operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
+ detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
+operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
{
return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
- && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
- detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
+ detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
+operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
{
- return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+ return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
}
template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
- && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer), detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator^ (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer), detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+operator^(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
-}} // namespaces
+}} // namespace boost::multiprecision
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/float128_functions.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/float128_functions.hpp
new file mode 100644
index 0000000000..cf0e9be1e6
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/float128_functions.hpp
@@ -0,0 +1,93 @@
+// (C) Copyright John Maddock 2021.
+// Use, modification and distribution are subject to 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)
+//
+// We deliberately use assert in here:
+//
+
+#ifndef BOOST_MP_DETAIL_FLOAT128_FUNCTIONS_HPP
+#define BOOST_MP_DETAIL_FLOAT128_FUNCTIONS_HPP
+
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+#ifndef BOOST_MP_STANDALONE
+#include <boost/cstdfloat.hpp>
+#if defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+# define BOOST_MP_HAVE_CSTDFLOAT
+#endif
+#endif
+
+#if defined(BOOST_HAS_FLOAT128)
+
+namespace boost
+{
+namespace multiprecision
+{
+namespace float128_procs
+{
+extern "C" __float128 ldexpq(__float128, int) throw();
+extern "C" __float128 frexpq(__float128, int*) throw();
+extern "C" __float128 floorq(__float128) throw();
+extern "C" __float128 nextafterq(__float128, __float128) throw();
+extern "C" int isinfq(__float128) throw();
+extern "C" int isnanq(__float128) throw();
+extern "C" __float128 strtoflt128(const char*, char**) throw();
+
+#ifdef BOOST_MP_HAVE_CSTDFLOAT
+using std::ldexp;
+using std::frexp;
+using std::floor;
+#else
+inline __float128 ldexp(__float128 f, int i) throw() { return ldexpq(f, i); }
+inline __float128 frexp(__float128 f, int* p) throw() { return frexpq(f, p); }
+inline __float128 floor(__float128 f) throw() { return floorq(f); }
+#endif
+}
+
+namespace detail {
+
+template <class T>
+struct is_float128 : public std::is_same<__float128, T>
+{};
+
+}
+}
+}
+
+namespace boost {
+namespace math {
+
+ inline __float128 float_next(const __float128& f)
+ {
+ return boost::multiprecision::float128_procs::nextafterq(f, 2 * f);
+ }
+ inline int (isinf)(const __float128& f)
+ {
+ return boost::multiprecision::float128_procs::isinfq(f);
+ }
+ inline int (isnan)(const __float128& f)
+ {
+ return boost::multiprecision::float128_procs::isnanq(f);
+ }
+
+}}
+
+#define BOOST_MP_FLOAT128_USING using boost::multiprecision::float128_procs::ldexp; using boost::multiprecision::float128_procs::frexp; using boost::multiprecision::float128_procs::floor; using boost::math::isinf; using boost::math::isnan;
+
+#else
+#define BOOST_MP_FLOAT128_USING
+
+namespace boost {
+namespace multiprecision {
+namespace detail {
+
+template <class T>
+struct is_float128 : public std::false_type
+{};
+
+}}} // namespace boost::multiprecision::detail
+
+#endif
+
+#endif // BOOST_MP_DETAIL_FLOAT128_FUNCTIONS_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/fpclassify.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/fpclassify.hpp
new file mode 100644
index 0000000000..2ca9833e23
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/fpclassify.hpp
@@ -0,0 +1,101 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2022 Matt Borland. 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_MP_DETAIL_FPCLASSIFY_HPP
+#define BOOST_MP_DETAIL_FPCLASSIFY_HPP
+
+#include <cmath>
+#include <limits>
+#include <type_traits>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/float128_functions.hpp>
+
+#ifdef BOOST_MP_MATH_AVAILABLE
+#include <boost/math/special_functions/fpclassify.hpp>
+
+#define BOOST_MP_ISNAN(x) (boost::math::isnan)(x)
+#define BOOST_MP_ISINF(x) (boost::math::isinf)(x)
+#define BOOST_MP_FPCLASSIFY(x) (boost::math::fpclassify)(x)
+#define BOOST_MP_ISFINITE(x) (!(boost::math::isnan)(x) && !(boost::math::isinf)(x))
+
+#else
+
+namespace boost { namespace multiprecision { namespace detail {
+
+template <typename T, typename std::enable_if<std::is_floating_point<T>::value
+ #ifdef BOOST_HAS_FLOAT128
+ || std::is_same<T, float128_type>::value
+ #endif
+ , bool>::type = true>
+inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
+{
+ BOOST_MP_FLOAT128_USING;
+ using std::isnan;
+ return static_cast<bool>((isnan)(x));
+}
+
+template <typename T, typename std::enable_if<!std::is_floating_point<T>::value
+ #ifdef BOOST_HAS_FLOAT128
+ && !std::is_same<T, float128_type>::value
+ #endif
+ , bool>::type = true>
+inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
+{
+ return x != x;
+}
+
+template <typename T, typename std::enable_if<std::is_floating_point<T>::value
+ #ifdef BOOST_HAS_FLOAT128
+ || std::is_same<T, float128_type>::value
+ #endif
+ , bool>::type = true>
+inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
+{
+ BOOST_MP_FLOAT128_USING;
+ using std::isinf;
+ return static_cast<bool>((isinf)(x));
+}
+
+template <typename T, typename std::enable_if<!std::is_floating_point<T>::value
+ #ifdef BOOST_HAS_FLOAT128
+ && !std::is_same<T, float128_type>::value
+ #endif
+ , bool>::type = true>
+inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
+{
+ return x == std::numeric_limits<T>::infinity() || x == -std::numeric_limits<T>::infinity();
+}
+
+template <typename T, typename std::enable_if<std::is_floating_point<T>::value, bool>::type = true>
+inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
+{
+ using std::fpclassify;
+ return fpclassify(x);
+}
+
+template <typename T, typename std::enable_if<!std::is_floating_point<T>::value, bool>::type = true>
+inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
+{
+ BOOST_MP_FLOAT128_USING;
+ using std::isnan;
+ using std::isinf;
+ using std::abs;
+
+ return (isnan)(x) ? FP_NAN :
+ (isinf)(x) ? FP_INFINITE :
+ abs(x) == T(0) ? FP_ZERO :
+ abs(x) > 0 && abs(x) < (std::numeric_limits<T>::min)() ? FP_SUBNORMAL : FP_NORMAL;
+}
+
+}}} // Namespace boost::multiprecision::detail
+
+#define BOOST_MP_ISNAN(x) (boost::multiprecision::detail::isnan)(x)
+#define BOOST_MP_ISINF(x) (boost::multiprecision::detail::isinf)(x)
+#define BOOST_MP_FPCLASSIFY(x) (boost::multiprecision::detail::fpclassify)(x)
+#define BOOST_MP_ISFINITE(x) (!(boost::multiprecision::detail::isnan)(x) && !(boost::multiprecision::detail::isinf)(x))
+
+#endif
+
+#endif // BOOST_MP_DETAIL_FPCLASSIFY_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/constants.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/constants.hpp
index 48b4a5c29a..56aa069f38 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/constants.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/constants.hpp
@@ -1,36 +1,36 @@
-// Copyright 2011 John Maddock. Distributed under the Boost
+// Copyright 2011 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)
//
// This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp
-//
+//
template <class T>
void calc_log2(T& num, unsigned digits)
{
- typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
- typedef typename mpl::front<typename T::signed_types>::type si_type;
+ using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
+ using si_type = typename std::tuple_element<0, typename T::signed_types>::type ;
//
// String value with 1100 digits:
//
static const char* string_val = "0."
- "6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875"
- "4200148102057068573368552023575813055703267075163507596193072757082837143519030703862389167347112335"
- "0115364497955239120475172681574932065155524734139525882950453007095326366642654104239157814952043740"
- "4303855008019441706416715186447128399681717845469570262716310645461502572074024816377733896385506952"
- "6066834113727387372292895649354702576265209885969320196505855476470330679365443254763274495125040606"
- "9438147104689946506220167720424524529612687946546193165174681392672504103802546259656869144192871608"
- "2938031727143677826548775664850856740776484514644399404614226031930967354025744460703080960850474866"
- "3852313818167675143866747664789088143714198549423151997354880375165861275352916610007105355824987941"
- "4729509293113897155998205654392871700072180857610252368892132449713893203784393530887748259701715591"
- "0708823683627589842589185353024363421436706118923678919237231467232172053401649256872747782344535347"
- "6481149418642386776774406069562657379600867076257199184734022651462837904883062033061144630073719489";
+ "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
+ if (digits < 3640) // 3640 binary digits ~ 1100 decimal digits
{
num = string_val;
return;
@@ -40,7 +40,7 @@ void calc_log2(T& num, unsigned digits)
//
// ln(2) = 3/4 SUM[n>=0] ((-1)^n * N!^2 / (2^n(2n+1)!))
//
- // Numerator and denominator are calculated separately and then
+ // 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.
//
@@ -49,13 +49,13 @@ void calc_log2(T& num, unsigned digits)
//
num = static_cast<ui_type>(1180509120uL);
T denom, next_term, temp;
- denom = static_cast<ui_type>(1277337600uL);
- next_term = static_cast<ui_type>(120uL);
+ denom = static_cast<ui_type>(1277337600uL);
+ next_term = static_cast<ui_type>(120uL);
si_type sign = -1;
ui_type limit = digits / 3 + 1;
- for(ui_type n = 6; n < limit; ++n)
+ for (ui_type n = 6; n < limit; ++n)
{
temp = static_cast<ui_type>(2);
eval_multiply(temp, ui_type(2 * n));
@@ -65,7 +65,7 @@ void calc_log2(T& num, unsigned digits)
sign = -sign;
eval_multiply(next_term, n);
eval_multiply(temp, next_term, next_term);
- if(sign < 0)
+ if (sign < 0)
temp.negate();
eval_add(num, temp);
}
@@ -80,26 +80,26 @@ void calc_log2(T& num, unsigned digits)
template <class T>
void calc_e(T& result, unsigned digits)
{
- typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
//
// 1100 digits in string form:
//
const char* string_val = "2."
- "7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274"
- "2746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901"
- "1573834187930702154089149934884167509244761460668082264800168477411853742345442437107539077744992069"
- "5517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416"
- "9283681902551510865746377211125238978442505695369677078544996996794686445490598793163688923009879312"
- "7736178215424999229576351482208269895193668033182528869398496465105820939239829488793320362509443117"
- "3012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509"
- "9618188159304169035159888851934580727386673858942287922849989208680582574927961048419844436346324496"
- "8487560233624827041978623209002160990235304369941849146314093431738143640546253152096183690888707016"
- "7683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354"
- "0212340784981933432106817012100562788023519303322474501585390473041995777709350366041699732972508869";
+ "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
+ if (digits < 3640) // 3640 binary digits ~ 1100 decimal digits
{
result = string_val;
return;
@@ -114,41 +114,42 @@ void calc_e(T& result, unsigned digits)
//
result = ui_type(2);
T denom;
- denom = ui_type(1);
+ denom = ui_type(1);
ui_type i = 2;
- do{
+ do
+ {
eval_multiply(denom, i);
eval_multiply(result, i);
eval_add(result, ui_type(1));
++i;
- }while(denom.compare(lim) <= 0);
+ } while (denom.compare(lim) <= 0);
eval_divide(result, denom);
}
template <class T>
void calc_pi(T& result, unsigned digits)
{
- typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
- typedef typename mpl::front<typename T::float_types>::type real_type;
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
+ using real_type = typename std::tuple_element<0, typename T::float_types>::type ;
//
// 1100 digits in string form:
//
const char* string_val = "3."
- "1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
- "8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196"
- "4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273"
- "7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094"
- "3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912"
- "9833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132"
- "0005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235"
- "4201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859"
- "5024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303"
- "5982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"
- "3809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913152";
+ "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
+ if (digits < 3640) // 3640 binary digits ~ 1100 decimal digits
{
result = string_val;
return;
@@ -165,7 +166,7 @@ void calc_pi(T& result, unsigned digits)
T lim;
lim = ui_type(1);
- eval_ldexp(lim, lim, -(int)digits);
+ eval_ldexp(lim, lim, -static_cast<int>(digits));
//
// This algorithm is from:
@@ -200,115 +201,88 @@ void calc_pi(T& result, unsigned digits)
eval_ldexp(B, B, 1);
eval_subtract(result, A, B);
bool neg = eval_get_sign(result) < 0;
- if(neg)
+ if (neg)
result.negate();
- if(result.compare(lim) <= 0)
+ if (result.compare(lim) <= 0)
break;
- if(neg)
+ if (neg)
result.negate();
eval_ldexp(result, result, k - 1);
eval_subtract(D, result);
++k;
eval_ldexp(lim, lim, 1);
- }
- while(true);
+ } while (true);
eval_divide(result, B, D);
}
-template <class T, const T& (*F)(void)>
-struct constant_initializer
-{
- static void do_nothing()
- {
- init.do_nothing();
- }
-private:
- struct initializer
- {
- initializer()
- {
- F();
- }
- void do_nothing()const{}
- };
- static const initializer init;
-};
-
-template <class T, const T& (*F)(void)>
-typename constant_initializer<T, F>::initializer const constant_initializer<T, F>::init;
-
template <class T>
const T& get_constant_ln2()
{
- static BOOST_MP_THREAD_LOCAL T result;
- static BOOST_MP_THREAD_LOCAL bool b = false;
- static BOOST_MP_THREAD_LOCAL long digits = boost::multiprecision::detail::digits2<number<T> >::value();
- if(!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
+ static BOOST_MP_THREAD_LOCAL T result;
+ static BOOST_MP_THREAD_LOCAL long digits = 0;
+ if ((digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
+ boost::multiprecision::detail::maybe_promote_precision(&result);
calc_log2(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value());
- b = true;
digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
- constant_initializer<T, &get_constant_ln2<T> >::do_nothing();
-
return result;
}
-#ifndef BOOST_MP_THREAD_LOCAL
-#error 1
-#endif
template <class T>
const T& get_constant_e()
{
- static BOOST_MP_THREAD_LOCAL T result;
- static BOOST_MP_THREAD_LOCAL bool b = false;
- static BOOST_MP_THREAD_LOCAL long digits = boost::multiprecision::detail::digits2<number<T> >::value();
- if(!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
+ static BOOST_MP_THREAD_LOCAL T result;
+ static BOOST_MP_THREAD_LOCAL long digits = 0;
+ if ((digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
+ boost::multiprecision::detail::maybe_promote_precision(&result);
calc_e(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value());
- b = true;
digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
- constant_initializer<T, &get_constant_e<T> >::do_nothing();
-
return result;
}
template <class T>
const T& get_constant_pi()
{
- static BOOST_MP_THREAD_LOCAL T result;
- static BOOST_MP_THREAD_LOCAL bool b = false;
- static BOOST_MP_THREAD_LOCAL long digits = boost::multiprecision::detail::digits2<number<T> >::value();
- if(!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
+ static BOOST_MP_THREAD_LOCAL T result;
+ static BOOST_MP_THREAD_LOCAL long digits = 0;
+ if ((digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
+ boost::multiprecision::detail::maybe_promote_precision(&result);
calc_pi(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value());
- b = true;
digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
- constant_initializer<T, &get_constant_pi<T> >::do_nothing();
-
return result;
}
-
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
template <class T>
const T& get_constant_one_over_epsilon()
{
- static const bool is_init = false;
- static T result;
- if (is_init == false)
+ static BOOST_MP_THREAD_LOCAL T result;
+ static BOOST_MP_THREAD_LOCAL long digits = 0;
+ if ((digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
- typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
+ boost::multiprecision::detail::maybe_promote_precision(&result);
result = static_cast<ui_type>(1u);
- eval_divide(result, std::numeric_limits<number<T> >::epsilon().backend());
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<T> >::is_specialized)
+ eval_divide(result, std::numeric_limits<number<T> >::epsilon().backend());
+ else
+ eval_ldexp(result, result, boost::multiprecision::detail::digits2<number<T> >::value() - 1);
+ digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
- constant_initializer<T, &get_constant_one_over_epsilon<T> >::do_nothing();
-
return result;
}
-
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/pow.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/pow.hpp
index 179e37f400..36ea0e4024 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/pow.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/pow.hpp
@@ -1,6 +1,6 @@
// Copyright Christopher Kormanyos 2002 - 2013.
-// Copyright 2011 - 2013 John Maddock. Distributed under the Boost
+// Copyright 2011 - 2013 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)
@@ -10,17 +10,22 @@
// 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
+#pragma warning(disable : 4127) // conditional expression is constant
#endif
-namespace detail{
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+
+namespace detail {
-template<typename T, typename U>
-inline void pow_imp(T& result, const T& t, const U& p, const mpl::false_&)
+template <typename T, typename U>
+inline void pow_imp(T& result, const T& t, const U& p, const std::integral_constant<bool, false>&)
{
// Compute the pure power of typename T t^p.
// Use the S-and-X binary method, as described in
@@ -28,18 +33,18 @@ inline void pow_imp(T& result, const T& t, const U& p, const mpl::false_&)
// Section 4.6.3 . The resulting computational complexity
// is order log2[abs(p)].
- typedef typename boost::multiprecision::detail::canonical<U, T>::type int_type;
+ using int_type = typename boost::multiprecision::detail::canonical<U, T>::type;
- if(&result == &t)
+ if (&result == &t)
{
T temp;
- pow_imp(temp, t, p, mpl::false_());
+ pow_imp(temp, t, p, std::integral_constant<bool, false>());
result = temp;
return;
}
// This will store the result.
- if(U(p % U(2)) != U(0))
+ if (U(p % U(2)) != U(0))
{
result = t;
}
@@ -51,14 +56,14 @@ inline void pow_imp(T& result, const T& t, const U& p, const mpl::false_&)
// The variable x stores the binary powers of t.
T x(t);
- while(U(p2 /= 2) != U(0))
+ while (U(p2 /= 2) != U(0))
{
// Square x for each binary power.
eval_multiply(x, x);
const bool has_binary_power = (U(p2 % U(2)) != U(0));
- if(has_binary_power)
+ if (has_binary_power)
{
// Multiply the result with each binary power contained in the exponent.
eval_multiply(result, x);
@@ -66,31 +71,31 @@ inline void pow_imp(T& result, const T& t, const U& p, const mpl::false_&)
}
}
-template<typename T, typename U>
-inline void pow_imp(T& result, const T& t, const U& p, const mpl::true_&)
+template <typename T, typename U>
+inline void pow_imp(T& result, const T& t, const U& p, const std::integral_constant<bool, true>&)
{
// Signed integer power, just take care of the sign then call the unsigned version:
- typedef typename boost::multiprecision::detail::canonical<U, T>::type int_type;
- typedef typename make_unsigned<U>::type ui_type;
+ using int_type = typename boost::multiprecision::detail::canonical<U, T>::type;
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<U>::type ;
- if(p < 0)
+ if (p < 0)
{
T temp;
temp = static_cast<int_type>(1);
T denom;
- pow_imp(denom, t, static_cast<ui_type>(-p), mpl::false_());
+ pow_imp(denom, t, static_cast<ui_type>(-p), std::integral_constant<bool, false>());
eval_divide(result, temp, denom);
return;
}
- pow_imp(result, t, static_cast<ui_type>(p), mpl::false_());
+ pow_imp(result, t, static_cast<ui_type>(p), std::integral_constant<bool, false>());
}
} // namespace detail
-template<typename T, typename U>
-inline typename enable_if<is_integral<U> >::type eval_pow(T& result, const T& t, const U& p)
+template <typename T, typename U>
+inline typename std::enable_if<boost::multiprecision::detail::is_integral<U>::value>::type eval_pow(T& result, const T& t, const U& p)
{
- detail::pow_imp(result, t, p, boost::is_signed<U>());
+ detail::pow_imp(result, t, p, boost::multiprecision::detail::is_signed<U>());
}
template <class T>
@@ -100,11 +105,11 @@ void hyp0F0(T& H0F0, const T& x)
// http://functions.wolfram.com/HypergeometricFunctions/Hypergeometric0F0/06/01/
// There are no checks on input range or parameter boundaries.
- typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
+ using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
- BOOST_ASSERT(&H0F0 != &x);
+ BOOST_MP_ASSERT(&H0F0 != &x);
long tol = boost::multiprecision::detail::digits2<number<T, et_on> >::value();
- T t;
+ T t;
T x_pow_n_div_n_fact(x);
@@ -112,30 +117,31 @@ void hyp0F0(T& H0F0, const T& x)
T lim;
eval_ldexp(lim, H0F0, 1 - tol);
- if(eval_get_sign(lim) < 0)
+ if (eval_get_sign(lim) < 0)
lim.negate();
ui_type n;
- const unsigned series_limit =
- boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
- ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
+ const unsigned series_limit =
+ boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
+ ? 100
+ : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
// Series expansion of hyperg_0f0(; ; 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);
eval_add(H0F0, x_pow_n_div_n_fact);
bool neg = eval_get_sign(x_pow_n_div_n_fact) < 0;
- if(neg)
+ if (neg)
x_pow_n_div_n_fact.negate();
- if(lim.compare(x_pow_n_div_n_fact) > 0)
+ if (lim.compare(x_pow_n_div_n_fact) > 0)
break;
- if(neg)
+ if (neg)
x_pow_n_div_n_fact.negate();
}
- if(n >= series_limit)
- BOOST_THROW_EXCEPTION(std::runtime_error("H0F0 failed to converge"));
+ if (n >= series_limit)
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("H0F0 failed to converge"));
}
template <class T>
@@ -146,30 +152,31 @@ void hyp1F0(T& H1F0, const T& a, const T& x)
// and also see the corresponding section for the power function (i.e. x^a).
// There are no checks on input range or parameter boundaries.
- typedef typename boost::multiprecision::detail::canonical<int, T>::type si_type;
+ using si_type = typename boost::multiprecision::detail::canonical<int, T>::type;
- BOOST_ASSERT(&H1F0 != &x);
- BOOST_ASSERT(&H1F0 != &a);
+ BOOST_MP_ASSERT(&H1F0 != &x);
+ BOOST_MP_ASSERT(&H1F0 != &a);
T x_pow_n_div_n_fact(x);
- T pochham_a (a);
- T ap (a);
+ T pochham_a(a);
+ T ap(a);
eval_multiply(H1F0, pochham_a, x_pow_n_div_n_fact);
eval_add(H1F0, si_type(1));
T lim;
eval_ldexp(lim, H1F0, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
- if(eval_get_sign(lim) < 0)
+ if (eval_get_sign(lim) < 0)
lim.negate();
si_type n;
- T term, part;
+ T term, part;
const si_type series_limit =
- boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
- ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
+ boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
+ ? 100
+ : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
// Series expansion of hyperg_1f0(a; ; 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);
@@ -177,49 +184,49 @@ void hyp1F0(T& H1F0, const T& a, const T& x)
eval_multiply(pochham_a, ap);
eval_multiply(term, pochham_a, x_pow_n_div_n_fact);
eval_add(H1F0, 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)
- BOOST_THROW_EXCEPTION(std::runtime_error("H1F0 failed to converge"));
+ if (n >= series_limit)
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("H1F0 failed to converge"));
}
template <class T>
void eval_exp(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The exp function is only valid for floating point types.");
- if(&x == &result)
+ static_assert(number_category<T>::value == number_kind_floating_point, "The exp function is only valid for floating point types.");
+ if (&x == &result)
{
T temp;
eval_exp(temp, x);
result = temp;
return;
}
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- typedef typename boost::multiprecision::detail::canonical<int, T>::type si_type;
- typedef typename T::exponent_type exp_type;
- typedef typename boost::multiprecision::detail::canonical<exp_type, T>::type canonical_exp_type;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ using si_type = typename boost::multiprecision::detail::canonical<int, T>::type ;
+ using exp_type = typename T::exponent_type ;
+ using canonical_exp_type = typename boost::multiprecision::detail::canonical<exp_type, T>::type;
// Handle special arguments.
- int type = eval_fpclassify(x);
+ int type = eval_fpclassify(x);
bool isneg = eval_get_sign(x) < 0;
- if(type == (int)FP_NAN)
+ if (type == static_cast<int>(FP_NAN))
{
result = x;
- errno = EDOM;
+ errno = EDOM;
return;
}
- else if(type == (int)FP_INFINITE)
+ else if (type == static_cast<int>(FP_INFINITE))
{
- if(isneg)
+ if (isneg)
result = ui_type(0u);
- else
+ else
result = x;
return;
}
- else if(type == (int)FP_ZERO)
+ else if (type == static_cast<int>(FP_ZERO))
{
result = ui_type(1);
return;
@@ -228,17 +235,17 @@ void eval_exp(T& result, const T& x)
// Get local copy of argument and force it to be positive.
T xx = x;
T exp_series;
- if(isneg)
+ if (isneg)
xx.negate();
// Check the range of the argument.
- if(xx.compare(si_type(1)) <= 0)
+ if (xx.compare(si_type(1)) <= 0)
{
//
// Use series for exp(x) - 1:
//
T lim;
- if(std::numeric_limits<number<T, et_on> >::is_specialized)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::is_specialized)
lim = std::numeric_limits<number<T, et_on> >::epsilon().backend();
else
{
@@ -247,20 +254,20 @@ void eval_exp(T& result, const T& x)
}
unsigned k = 2;
exp_series = xx;
- result = si_type(1);
- if(isneg)
+ result = si_type(1);
+ if (isneg)
eval_subtract(result, exp_series);
else
eval_add(result, exp_series);
eval_multiply(exp_series, xx);
eval_divide(exp_series, ui_type(k));
eval_add(result, exp_series);
- while(exp_series.compare(lim) > 0)
+ while (exp_series.compare(lim) > 0)
{
++k;
eval_multiply(exp_series, xx);
eval_divide(exp_series, ui_type(k));
- if(isneg && (k&1))
+ if (isneg && (k & 1))
eval_subtract(result, exp_series);
else
eval_add(result, exp_series);
@@ -269,20 +276,20 @@ void eval_exp(T& result, const T& x)
}
// Check for pure-integer arguments which can be either signed or unsigned.
- typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type ll;
+ typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type ll;
eval_trunc(exp_series, x);
eval_convert_to(&ll, exp_series);
- if(x.compare(ll) == 0)
+ if (x.compare(ll) == 0)
{
- detail::pow_imp(result, get_constant_e<T>(), ll, mpl::true_());
+ detail::pow_imp(result, get_constant_e<T>(), ll, std::integral_constant<bool, true>());
return;
}
- else if(exp_series.compare(x) == 0)
+ else if (exp_series.compare(x) == 0)
{
- // We have a value that has no fractional part, but is too large to fit
+ // We have a value that has no fractional part, but is too large to fit
// in a long long, in this situation the code below will fail, so
// we're just going to assume that this will overflow:
- if(isneg)
+ if (isneg)
result = ui_type(0);
else
result = std::numeric_limits<number<T> >::has_infinity ? std::numeric_limits<number<T> >::infinity().backend() : (std::numeric_limits<number<T> >::max)().backend();
@@ -322,12 +329,12 @@ void eval_exp(T& result, const T& x)
exp_series.negate();
hyp0F0(result, exp_series);
- detail::pow_imp(exp_series, result, p2, mpl::true_());
+ detail::pow_imp(exp_series, result, p2, std::integral_constant<bool, true>());
result = ui_type(1);
eval_ldexp(result, result, n);
eval_multiply(exp_series, result);
- if(isneg)
+ if (isneg)
eval_divide(result, ui_type(1), exp_series);
else
result = exp_series;
@@ -336,26 +343,27 @@ void eval_exp(T& result, const T& x)
template <class T>
void eval_log(T& result, const T& arg)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The log function is only valid for floating point types.");
+ static_assert(number_category<T>::value == number_kind_floating_point, "The log function is only valid for floating point types.");
//
// We use a variation of http://dlmf.nist.gov/4.45#i
// using frexp to reduce the argument to x * 2^n,
// then let y = x - 1 and compute:
// log(x) = log(2) * n + log1p(1 + y)
//
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- typedef typename T::exponent_type exp_type;
- typedef typename boost::multiprecision::detail::canonical<exp_type, T>::type canonical_exp_type;
- typedef typename mpl::front<typename T::float_types>::type fp_type;
- int s = eval_signbit(arg);
- switch(eval_fpclassify(arg))
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ using exp_type = typename T::exponent_type ;
+ using canonical_exp_type = typename boost::multiprecision::detail::canonical<exp_type, T>::type;
+ using fp_type = typename std::tuple_element<0, typename T::float_types>::type ;
+ int s = eval_signbit(arg);
+ switch (eval_fpclassify(arg))
{
case FP_NAN:
result = arg;
- errno = EDOM;
+ errno = EDOM;
return;
case FP_INFINITE:
- if(s) break;
+ if (s)
+ break;
result = arg;
return;
case FP_ZERO:
@@ -364,44 +372,44 @@ void eval_log(T& result, const T& arg)
errno = ERANGE;
return;
}
- if(s)
+ if (s)
{
result = std::numeric_limits<number<T> >::quiet_NaN().backend();
- errno = EDOM;
+ errno = EDOM;
return;
}
exp_type e;
- T t;
+ T t;
eval_frexp(t, arg, &e);
bool alternate = false;
- if(t.compare(fp_type(2) / fp_type(3)) <= 0)
+ if (t.compare(fp_type(2) / fp_type(3)) <= 0)
{
alternate = true;
eval_ldexp(t, t, 1);
--e;
}
-
+
eval_multiply(result, get_constant_ln2<T>(), canonical_exp_type(e));
INSTRUMENT_BACKEND(result);
eval_subtract(t, ui_type(1)); /* -0.3 <= t <= 0.3 */
- if(!alternate)
+ if (!alternate)
t.negate(); /* 0 <= t <= 0.33333 */
T pow = t;
T lim;
T t2;
- if(alternate)
+ if (alternate)
eval_add(result, t);
else
eval_subtract(result, t);
- if(std::numeric_limits<number<T, et_on> >::is_specialized)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::is_specialized)
eval_multiply(lim, result, std::numeric_limits<number<T, et_on> >::epsilon().backend());
else
eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
- if(eval_get_sign(lim) < 0)
+ if (eval_get_sign(lim) < 0)
lim.negate();
INSTRUMENT_BACKEND(lim);
@@ -412,39 +420,35 @@ void eval_log(T& result, const T& arg)
eval_multiply(pow, t);
eval_divide(t2, pow, k);
INSTRUMENT_BACKEND(t2);
- if(alternate && ((k & 1) != 0))
+ if (alternate && ((k & 1) != 0))
eval_add(result, t2);
else
eval_subtract(result, t2);
INSTRUMENT_BACKEND(result);
- }while(lim.compare(t2) < 0);
+ } while (lim.compare(t2) < 0);
}
template <class T>
const T& get_constant_log10()
{
- static BOOST_MP_THREAD_LOCAL T result;
- static BOOST_MP_THREAD_LOCAL bool b = false;
- static BOOST_MP_THREAD_LOCAL long digits = boost::multiprecision::detail::digits2<number<T> >::value();
- if(!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
+ static BOOST_MP_THREAD_LOCAL T result;
+ static BOOST_MP_THREAD_LOCAL long digits = 0;
+ if ((digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- T ten;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ T ten;
ten = ui_type(10u);
eval_log(result, ten);
- b = true;
digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
- constant_initializer<T, &get_constant_log10<T> >::do_nothing();
-
return result;
}
template <class T>
void eval_log10(T& result, const T& arg)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The log10 function is only valid for floating point types.");
+ static_assert(number_category<T>::value == number_kind_floating_point, "The log10 function is only valid for floating point types.");
eval_log(result, arg);
eval_divide(result, get_constant_log10<T>());
}
@@ -456,14 +460,14 @@ inline void eval_log2(R& result, const T& a)
eval_divide(result, get_constant_ln2<R>());
}
-template<typename T>
+template <typename T>
inline void eval_pow(T& result, const T& x, const T& a)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The pow function is only valid for floating point types.");
- typedef typename boost::multiprecision::detail::canonical<int, T>::type si_type;
- typedef typename mpl::front<typename T::float_types>::type fp_type;
+ static_assert(number_category<T>::value == number_kind_floating_point, "The pow function is only valid for floating point types.");
+ using si_type = typename boost::multiprecision::detail::canonical<int, T>::type;
+ using fp_type = typename std::tuple_element<0, typename T::float_types>::type ;
- if((&result == &x) || (&result == &a))
+ if ((&result == &x) || (&result == &a))
{
T t;
eval_pow(t, x, a);
@@ -471,12 +475,12 @@ inline void eval_pow(T& result, const T& x, const T& a)
return;
}
- if((a.compare(si_type(1)) == 0) || (x.compare(si_type(1)) == 0))
+ if ((a.compare(si_type(1)) == 0) || (x.compare(si_type(1)) == 0))
{
result = x;
return;
}
- if(a.compare(si_type(0)) == 0)
+ if (a.compare(si_type(0)) == 0)
{
result = si_type(1);
return;
@@ -484,10 +488,10 @@ inline void eval_pow(T& result, const T& x, const T& a)
int type = eval_fpclassify(x);
- switch(type)
+ switch (type)
{
case FP_ZERO:
- switch(eval_fpclassify(a))
+ switch (eval_fpclassify(a))
{
case FP_ZERO:
result = si_type(1);
@@ -495,31 +499,30 @@ inline void eval_pow(T& result, const T& x, const T& a)
case FP_NAN:
result = a;
break;
- case FP_NORMAL:
- {
+ case FP_NORMAL: {
// Need to check for a an odd integer as a special case:
- try
+ BOOST_MP_TRY
{
- typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type i;
+ typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type i;
eval_convert_to(&i, a);
- if(a.compare(i) == 0)
+ if (a.compare(i) == 0)
{
- if(eval_signbit(a))
+ if (eval_signbit(a))
{
- if(i & 1)
+ if (i & 1)
{
result = std::numeric_limits<number<T> >::infinity().backend();
- if(eval_signbit(x))
+ if (eval_signbit(x))
result.negate();
errno = ERANGE;
}
else
{
result = std::numeric_limits<number<T> >::infinity().backend();
- errno = ERANGE;
+ errno = ERANGE;
}
}
- else if(i & 1)
+ else if (i & 1)
{
result = x;
}
@@ -528,16 +531,18 @@ inline void eval_pow(T& result, const T& x, const T& a)
return;
}
}
- catch(const std::exception&)
+ BOOST_MP_CATCH(const std::exception&)
{
// fallthrough..
}
+ BOOST_MP_CATCH_END
+ BOOST_FALLTHROUGH;
}
default:
- if(eval_signbit(a))
+ if (eval_signbit(a))
{
result = std::numeric_limits<number<T> >::infinity().backend();
- errno = ERANGE;
+ errno = ERANGE;
}
else
result = x;
@@ -546,19 +551,19 @@ inline void eval_pow(T& result, const T& x, const T& a)
return;
case FP_NAN:
result = x;
- errno = ERANGE;
+ errno = ERANGE;
return;
- default: ;
+ default:;
}
int s = eval_get_sign(a);
- if(s == 0)
+ if (s == 0)
{
result = si_type(1);
return;
}
- if(s < 0)
+ if (s < 0)
{
T t, da;
t = a;
@@ -567,71 +572,61 @@ inline void eval_pow(T& result, const T& x, const T& a)
eval_divide(result, si_type(1), da);
return;
}
-
- typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type an;
- typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type max_an =
- std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::is_specialized ?
- (std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::max)() :
- static_cast<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>(1) << (sizeof(typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type) * CHAR_BIT - 2);
- typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type min_an =
- std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::is_specialized ?
- (std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::min)() :
- -min_an;
+ typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type an;
+ typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type max_an =
+ std::numeric_limits<typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type>::is_specialized ? (std::numeric_limits<typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type>::max)() : static_cast<typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type>(1) << (sizeof(typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type) * CHAR_BIT - 2);
+ typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type min_an =
+ std::numeric_limits<typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type>::is_specialized ? (std::numeric_limits<typename boost::multiprecision::detail::canonical<std::intmax_t, T>::type>::min)() : -min_an;
T fa;
-#ifndef BOOST_NO_EXCEPTIONS
- try
+ BOOST_MP_TRY
{
-#endif
eval_convert_to(&an, a);
- if(a.compare(an) == 0)
+ if (a.compare(an) == 0)
{
- detail::pow_imp(result, x, an, mpl::true_());
+ detail::pow_imp(result, x, an, std::integral_constant<bool, true>());
return;
}
-#ifndef BOOST_NO_EXCEPTIONS
}
- catch(const std::exception&)
+ BOOST_MP_CATCH(const std::exception&)
{
// conversion failed, just fall through, value is not an integer.
- an = (std::numeric_limits<boost::intmax_t>::max)();
+ an = (std::numeric_limits<std::intmax_t>::max)();
}
-#endif
- if((eval_get_sign(x) < 0))
+ BOOST_MP_CATCH_END
+ if ((eval_get_sign(x) < 0))
{
- typename boost::multiprecision::detail::canonical<boost::uintmax_t, T>::type aun;
-#ifndef BOOST_NO_EXCEPTIONS
- try
+ typename boost::multiprecision::detail::canonical<std::uintmax_t, T>::type aun;
+ BOOST_MP_TRY
{
-#endif
eval_convert_to(&aun, a);
- if(a.compare(aun) == 0)
+ if (a.compare(aun) == 0)
{
fa = x;
fa.negate();
eval_pow(result, fa, a);
- if(aun & 1u)
+ if (aun & 1u)
result.negate();
return;
}
-#ifndef BOOST_NO_EXCEPTIONS
}
- catch(const std::exception&)
+ BOOST_MP_CATCH(const std::exception&)
{
// conversion failed, just fall through, value is not an integer.
}
-#endif
+ BOOST_MP_CATCH_END
+
eval_floor(result, a);
// -1^INF is a special case in C99:
- if((x.compare(si_type(-1)) == 0) && (eval_fpclassify(a) == FP_INFINITE))
+ if ((x.compare(si_type(-1)) == 0) && (eval_fpclassify(a) == FP_INFINITE))
{
result = si_type(1);
}
- else if(a.compare(result) == 0)
+ else if (a.compare(result) == 0)
{
// exponent is so large we have no fractional part:
- if(x.compare(si_type(-1)) < 0)
+ if (x.compare(si_type(-1)) < 0)
{
result = std::numeric_limits<number<T, et_on> >::infinity().backend();
}
@@ -640,18 +635,18 @@ inline void eval_pow(T& result, const T& x, const T& a)
result = si_type(0);
}
}
- else if(type == FP_INFINITE)
+ else if (type == FP_INFINITE)
{
result = std::numeric_limits<number<T, et_on> >::infinity().backend();
}
- else if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ else BOOST_IF_CONSTEXPR (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
{
result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
- errno = EDOM;
+ errno = EDOM;
}
else
{
- BOOST_THROW_EXCEPTION(std::domain_error("Result of pow is undefined or non-real and there is no NaN for this number type."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Result of pow is undefined or non-real and there is no NaN for this number type."));
}
return;
}
@@ -660,9 +655,9 @@ inline void eval_pow(T& result, const T& x, const T& a)
eval_subtract(da, a, an);
- if((x.compare(fp_type(0.5)) >= 0) && (x.compare(fp_type(0.9)) < 0) && (an < max_an) && (an > min_an))
+ if ((x.compare(fp_type(0.5)) >= 0) && (x.compare(fp_type(0.9)) < 0) && (an < max_an) && (an > min_an))
{
- if(a.compare(fp_type(1e-5f)) <= 0)
+ if (a.compare(fp_type(1e-5f)) <= 0)
{
// Series expansion for small a.
eval_log(t, x);
@@ -674,13 +669,13 @@ inline void eval_pow(T& result, const T& x, const T& a)
{
// Series expansion for moderately sized x. Note that for large power of a,
// the power of the integer part of a is calculated using the pown function.
- if(an)
+ if (an)
{
da.negate();
t = si_type(1);
eval_subtract(t, x);
hyp1F0(result, da, t);
- detail::pow_imp(t, x, an, mpl::true_());
+ detail::pow_imp(t, x, an, std::integral_constant<bool, true>());
eval_multiply(result, t);
}
else
@@ -697,12 +692,12 @@ inline void eval_pow(T& result, const T& x, const T& a)
{
// Series expansion for pow(x, a). Note that for large power of a, the power
// of the integer part of a is calculated using the pown function.
- if(an)
+ if (an)
{
eval_log(t, x);
eval_multiply(t, da);
eval_exp(result, t);
- detail::pow_imp(t, x, an, mpl::true_());
+ detail::pow_imp(t, x, an, std::integral_constant<bool, true>());
eval_multiply(result, t);
}
else
@@ -714,24 +709,34 @@ inline void eval_pow(T& result, const T& x, const T& a)
}
}
-template<class T, class A>
-inline typename enable_if<is_floating_point<A>, void>::type eval_pow(T& result, const T& x, const A& a)
+template <class T, class A>
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+inline typename std::enable_if<!boost::multiprecision::detail::is_integral<A>::value, void>::type
+#else
+inline typename std::enable_if<is_compatible_arithmetic_type<A, number<T> >::value && !boost::multiprecision::detail::is_integral<A>::value, void>::type
+#endif
+eval_pow(T& result, const T& x, const A& a)
{
// Note this one is restricted to float arguments since pow.hpp already has a version for
// integer powers....
- typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
- typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
- cast_type c;
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
+ cast_type c;
c = a;
eval_pow(result, x, c);
}
-template<class T, class A>
-inline typename enable_if<is_arithmetic<A>, void>::type eval_pow(T& result, const A& x, const T& a)
+template <class T, class A>
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+inline void
+#else
+inline typename std::enable_if<is_compatible_arithmetic_type<A, number<T> >::value, void>::type
+#endif
+eval_pow(T& result, const A& x, const T& a)
{
- typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
- typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
- cast_type c;
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
+ cast_type c;
c = x;
eval_pow(result, c, a);
}
@@ -739,154 +744,160 @@ inline typename enable_if<is_arithmetic<A>, void>::type eval_pow(T& result, cons
template <class T>
void eval_exp2(T& result, const T& arg)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The log function is only valid for floating point types.");
+ static_assert(number_category<T>::value == number_kind_floating_point, "The log function is only valid for floating point types.");
// Check for pure-integer arguments which can be either signed or unsigned.
typename boost::multiprecision::detail::canonical<typename T::exponent_type, T>::type i;
- T temp;
- try {
+ T temp;
+ BOOST_MP_TRY
+ {
eval_trunc(temp, arg);
eval_convert_to(&i, temp);
- if(arg.compare(i) == 0)
+ if (arg.compare(i) == 0)
{
- temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(1u);
+ temp = static_cast<typename std::tuple_element<0, typename T::unsigned_types>::type>(1u);
eval_ldexp(result, temp, i);
return;
}
}
- catch(const boost::math::rounding_error&)
- { /* Fallthrough */ }
- catch(const std::runtime_error&)
- { /* Fallthrough */ }
+ #ifdef BOOST_MP_MATH_AVAILABLE
+ BOOST_MP_CATCH(const boost::math::rounding_error&)
+ { /* Fallthrough */
+ }
+ #endif
+ BOOST_MP_CATCH(const std::runtime_error&)
+ { /* Fallthrough */
+ }
+ BOOST_MP_CATCH_END
- temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(2u);
+ temp = static_cast<typename std::tuple_element<0, typename T::unsigned_types>::type>(2u);
eval_pow(result, temp, arg);
}
-namespace detail{
+namespace detail {
- template <class T>
- void small_sinh_series(T x, T& result)
+template <class T>
+void small_sinh_series(T x, T& result)
+{
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ bool neg = eval_get_sign(x) < 0;
+ if (neg)
+ x.negate();
+ T p(x);
+ T mult(x);
+ eval_multiply(mult, x);
+ result = x;
+ ui_type k = 1;
+
+ T lim(x);
+ eval_ldexp(lim, lim, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
+
+ do
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- bool neg = eval_get_sign(x) < 0;
- if(neg)
- x.negate();
- T p(x);
- T mult(x);
- eval_multiply(mult, x);
- result = x;
- ui_type k = 1;
+ eval_multiply(p, mult);
+ eval_divide(p, ++k);
+ eval_divide(p, ++k);
+ eval_add(result, p);
+ } while (p.compare(lim) >= 0);
+ if (neg)
+ result.negate();
+}
- T lim(x);
- eval_ldexp(lim, lim, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
+template <class T>
+void sinhcosh(const T& x, T* p_sinh, T* p_cosh)
+{
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
+ using fp_type = typename std::tuple_element<0, typename T::float_types>::type ;
- do
+ switch (eval_fpclassify(x))
+ {
+ case FP_NAN:
+ errno = EDOM;
+ // fallthrough...
+ case FP_INFINITE:
+ if (p_sinh)
+ *p_sinh = x;
+ if (p_cosh)
{
- eval_multiply(p, mult);
- eval_divide(p, ++k);
- eval_divide(p, ++k);
- eval_add(result, p);
- }while(p.compare(lim) >= 0);
- if(neg)
- result.negate();
+ *p_cosh = x;
+ if (eval_get_sign(x) < 0)
+ p_cosh->negate();
+ }
+ return;
+ case FP_ZERO:
+ if (p_sinh)
+ *p_sinh = x;
+ if (p_cosh)
+ *p_cosh = ui_type(1);
+ return;
+ default:;
}
- template <class T>
- void sinhcosh(const T& x, T* p_sinh, T* p_cosh)
+ bool small_sinh = eval_get_sign(x) < 0 ? x.compare(fp_type(-0.5)) > 0 : x.compare(fp_type(0.5)) < 0;
+
+ if (p_cosh || !small_sinh)
{
- typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
- typedef typename mpl::front<typename T::float_types>::type fp_type;
+ T e_px, e_mx;
+ eval_exp(e_px, x);
+ eval_divide(e_mx, ui_type(1), e_px);
+ if (eval_signbit(e_mx) != eval_signbit(e_px))
+ e_mx.negate(); // Handles lack of signed zero in some types
- switch(eval_fpclassify(x))
+ if (p_sinh)
{
- case FP_NAN:
- errno = EDOM;
- // fallthrough...
- case FP_INFINITE:
- if(p_sinh)
- *p_sinh = x;
- if(p_cosh)
+ if (small_sinh)
{
- *p_cosh = x;
- if(eval_get_sign(x) < 0)
- p_cosh->negate();
+ small_sinh_series(x, *p_sinh);
}
- return;
- case FP_ZERO:
- if(p_sinh)
- *p_sinh = x;
- if(p_cosh)
- *p_cosh = ui_type(1);
- return;
- default: ;
- }
-
- bool small_sinh = eval_get_sign(x) < 0 ? x.compare(fp_type(-0.5)) > 0 : x.compare(fp_type(0.5)) < 0;
-
- if(p_cosh || !small_sinh)
- {
- T e_px, e_mx;
- eval_exp(e_px, x);
- eval_divide(e_mx, ui_type(1), e_px);
- if(eval_signbit(e_mx) != eval_signbit(e_px))
- e_mx.negate(); // Handles lack of signed zero in some types
-
- if(p_sinh)
- {
- if(small_sinh)
- {
- small_sinh_series(x, *p_sinh);
- }
- else
- {
- eval_subtract(*p_sinh, e_px, e_mx);
- eval_ldexp(*p_sinh, *p_sinh, -1);
- }
- }
- if(p_cosh)
- {
- eval_add(*p_cosh, e_px, e_mx);
- eval_ldexp(*p_cosh, *p_cosh, -1);
+ else
+ {
+ eval_subtract(*p_sinh, e_px, e_mx);
+ eval_ldexp(*p_sinh, *p_sinh, -1);
}
}
- else
+ if (p_cosh)
{
- small_sinh_series(x, *p_sinh);
+ eval_add(*p_cosh, e_px, e_mx);
+ eval_ldexp(*p_cosh, *p_cosh, -1);
}
}
+ else
+ {
+ small_sinh_series(x, *p_sinh);
+ }
+}
} // namespace detail
template <class T>
inline void eval_sinh(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The sinh function is only valid for floating point types.");
+ static_assert(number_category<T>::value == number_kind_floating_point, "The sinh function is only valid for floating point types.");
detail::sinhcosh(x, &result, static_cast<T*>(0));
}
template <class T>
inline void eval_cosh(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The cosh function is only valid for floating point types.");
+ static_assert(number_category<T>::value == number_kind_floating_point, "The cosh function is only valid for floating point types.");
detail::sinhcosh(x, static_cast<T*>(0), &result);
}
template <class T>
inline void eval_tanh(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The tanh function is only valid for floating point types.");
- T c;
- detail::sinhcosh(x, &result, &c);
- if((eval_fpclassify(result) == FP_INFINITE) && (eval_fpclassify(c) == FP_INFINITE))
- {
- bool s = eval_signbit(result) != eval_signbit(c);
- result = static_cast<typename mpl::front<typename T::unsigned_types>::type>(1u);
- if(s)
- result.negate();
- return;
- }
- eval_divide(result, c);
+ static_assert(number_category<T>::value == number_kind_floating_point, "The tanh function is only valid for floating point types.");
+ T c;
+ detail::sinhcosh(x, &result, &c);
+ if ((eval_fpclassify(result) == FP_INFINITE) && (eval_fpclassify(c) == FP_INFINITE))
+ {
+ bool s = eval_signbit(result) != eval_signbit(c);
+ result = static_cast<typename std::tuple_element<0, typename T::unsigned_types>::type>(1u);
+ if (s)
+ result.negate();
+ return;
+ }
+ eval_divide(result, c);
}
#ifdef BOOST_MSVC
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/trig.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/trig.hpp
index c001f955c9..56476c5517 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/trig.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/trig.hpp
@@ -1,6 +1,6 @@
// Copyright Christopher Kormanyos 2002 - 2011.
-// Copyright 2011 John Maddock. Distributed under the Boost
+// Copyright 2011 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)
@@ -10,26 +10,31 @@
// 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
-//
+//
+
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
-#pragma warning(disable:6326) // comparison of two constants
+#pragma warning(disable : 6326) // comparison of two constants
+#pragma warning(disable : 4127) // conditional expression is constant
#endif
template <class T>
void hyp0F1(T& result, const T& b, const T& x)
{
- typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
- typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
+ using si_type = typename boost::multiprecision::detail::canonical<std::int32_t, T>::type ;
+ using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
// Compute the series representation of Hypergeometric0F1 taken from
// http://functions.wolfram.com/HypergeometricFunctions/Hypergeometric0F1/06/01/01/
// 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 +45,16 @@ void hyp0F1(T& result, const T& b, const T& x)
tol = ui_type(1);
eval_ldexp(tol, tol, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::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<number<T, et_on> >::value() < 100
- ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
+ const int series_limit =
+ boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
+ ? 100
+ : boost::multiprecision::detail::digits2<number<T, et_on> >::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 +65,102 @@ 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)
- BOOST_THROW_EXCEPTION(std::runtime_error("H0F1 Failed to Converge"));
+ if (n >= series_limit)
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("H0F1 Failed to Converge"));
}
+template <class T, unsigned N, bool b = boost::multiprecision::detail::is_variable_precision<boost::multiprecision::number<T> >::value>
+struct scoped_N_precision
+{
+ template <class U>
+ scoped_N_precision(U const&) {}
+ template <class U>
+ void reduce(U&) {}
+};
+
+template <class T, unsigned N>
+struct scoped_N_precision<T, N, true>
+{
+ unsigned old_precision, old_arg_precision;
+ scoped_N_precision(T& arg)
+ {
+ old_precision = T::thread_default_precision();
+ old_arg_precision = arg.precision();
+ T::thread_default_precision(old_arg_precision * N);
+ arg.precision(old_arg_precision * N);
+ }
+ ~scoped_N_precision()
+ {
+ T::thread_default_precision(old_precision);
+ }
+ void reduce(T& arg)
+ {
+ arg.precision(old_arg_precision);
+ }
+};
+
+template <class T>
+void reduce_n_half_pi(T& arg, const T& n, bool go_down)
+{
+ //
+ // We need to perform argument reduction at 3 times the precision of arg
+ // in order to ensure a correct result up to arg = 1/epsilon. Beyond that
+ // the value of n will have been incorrectly calculated anyway since it will
+ // have a value greater than 1/epsilon and no longer be an exact integer value.
+ //
+ // More information in ARGUMENT REDUCTION FOR HUGE ARGUMENTS. K C Ng.
+ //
+ // There are two mutually exclusive ways to achieve this, both of which are
+ // supported here:
+ // 1) To define a fixed precision type with 3 times the precision for the calculation.
+ // 2) To dynamically increase the precision of the variables.
+ //
+ using reduction_type = typename boost::multiprecision::detail::transcendental_reduction_type<T>::type;
+ //
+ // Make a copy of the arg at higher precision:
+ //
+ reduction_type big_arg(arg);
+ //
+ // Dynamically increase precision when supported, this increases the default
+ // and ups the precision of big_arg to match:
+ //
+ scoped_N_precision<T, 3> scoped_precision(big_arg);
+ //
+ // High precision PI:
+ //
+ reduction_type reduction = get_constant_pi<reduction_type>();
+ eval_ldexp(reduction, reduction, -1); // divide by 2
+ eval_multiply(reduction, n);
+
+ BOOST_MATH_INSTRUMENT_CODE(big_arg.str(10, std::ios_base::scientific));
+ BOOST_MATH_INSTRUMENT_CODE(reduction.str(10, std::ios_base::scientific));
+
+ if (go_down)
+ eval_subtract(big_arg, reduction, big_arg);
+ else
+ eval_subtract(big_arg, reduction);
+ arg = T(big_arg);
+ //
+ // If arg is a variable precision type, then we have just copied the
+ // precision of big_arg s well it's value. Reduce the precision now:
+ //
+ scoped_precision.reduce(arg);
+ BOOST_MATH_INSTRUMENT_CODE(big_arg.str(10, std::ios_base::scientific));
+ BOOST_MATH_INSTRUMENT_CODE(arg.str(10, std::ios_base::scientific));
+}
template <class T>
void eval_sin(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The sin function is only valid for floating point types.");
- if(&result == &x)
+ static_assert(number_category<T>::value == number_kind_floating_point, "The sin function is only valid for floating point types.");
+ BOOST_MATH_INSTRUMENT_CODE(x.str(0, std::ios_base::scientific));
+ if (&result == &x)
{
T temp;
eval_sin(temp, x);
@@ -82,26 +168,26 @@ void eval_sin(T& result, const T& x)
return;
}
- typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
- typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
- typedef typename mpl::front<typename T::float_types>::type fp_type;
+ using si_type = typename boost::multiprecision::detail::canonical<std::int32_t, T>::type ;
+ using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
+ using fp_type = typename std::tuple_element<0, typename T::float_types>::type ;
- switch(eval_fpclassify(x))
+ switch (eval_fpclassify(x))
{
case FP_INFINITE:
case FP_NAN:
- if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
{
result = std::numeric_limits<number<T, et_on> >::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."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
case FP_ZERO:
result = x;
return;
- default: ;
+ default:;
}
// Local copy of the argument
@@ -112,65 +198,101 @@ 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;
}
T n_pi, t;
- // Remove even multiples of pi.
- if(xx.compare(get_constant_pi<T>()) > 0)
+ T half_pi = get_constant_pi<T>();
+ eval_ldexp(half_pi, half_pi, -1); // divide by 2
+ // Remove multiples of pi/2.
+ if (xx.compare(half_pi) > 0)
{
- eval_divide(n_pi, xx, get_constant_pi<T>());
+ eval_divide(n_pi, xx, half_pi);
eval_trunc(n_pi, n_pi);
- t = ui_type(2);
+ t = ui_type(4);
eval_fmod(t, n_pi, t);
- const bool b_n_pi_is_even = eval_get_sign(t) == 0;
- eval_multiply(n_pi, get_constant_pi<T>());
+ bool b_go_down = false;
+ if (t.compare(ui_type(1)) == 0)
+ {
+ b_go_down = true;
+ }
+ else if (t.compare(ui_type(2)) == 0)
+ {
+ b_negate_sin = !b_negate_sin;
+ }
+ else if (t.compare(ui_type(3)) == 0)
+ {
+ b_negate_sin = !b_negate_sin;
+ b_go_down = true;
+ }
+
+ if (b_go_down)
+ eval_increment(n_pi);
+ //
+ // If n_pi is > 1/epsilon, then it is no longer an exact integer value
+ // but an approximation. As a result we can no longer reliably reduce
+ // xx to 0 <= xx < pi/2, nor can we tell the sign of the result as we need
+ // n_pi % 4 for that, but that will always be zero in this situation.
+ // We could use a higher precision type for n_pi, along with division at
+ // higher precision, but that's rather expensive. So for now we do not support
+ // this, and will see if anyone complains and has a legitimate use case.
+ //
if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0)
{
result = ui_type(0);
return;
}
- else
- eval_subtract(xx, n_pi);
-
- BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
- 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)
+ reduce_n_half_pi(xx, n_pi, b_go_down);
+ //
+ // Post reduction we may be a few ulp below zero or above pi/2
+ // given that n_pi was calculated at working precision and not
+ // at the higher precision used for reduction. Correct that now:
+ //
+ if (eval_get_sign(xx) < 0)
{
+ xx.negate();
b_negate_sin = !b_negate_sin;
}
- }
+ if (xx.compare(half_pi) > 0)
+ {
+ eval_ldexp(half_pi, half_pi, 1);
+ eval_subtract(xx, half_pi, xx);
+ eval_ldexp(half_pi, half_pi, -1);
+ b_go_down = !b_go_down;
+ }
- // Reduce the argument to 0 <= xx <= pi/2.
- eval_ldexp(t, get_constant_pi<T>(), -1);
- if(xx.compare(t) > 0)
- {
- eval_subtract(xx, get_constant_pi<T>(), xx);
BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
+ BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific));
+ BOOST_MP_ASSERT(xx.compare(half_pi) <= 0);
+ BOOST_MP_ASSERT(xx.compare(ui_type(0)) >= 0);
}
+ t = half_pi;
eval_subtract(t, xx);
+
const bool b_zero = eval_get_sign(xx) == 0;
const bool b_pi_half = eval_get_sign(t) == 0;
+ BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
+ BOOST_MATH_INSTRUMENT_CODE(t.str(0, std::ios_base::scientific));
+
// 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 +302,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,8 +318,8 @@ 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_three_pow_scale = static_cast<si_type>(19683L);
+ constexpr si_type n_scale = 9;
+ constexpr si_type n_three_pow_scale = static_cast<si_type>(19683L);
eval_divide(xx, n_three_pow_scale);
@@ -211,7 +333,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<boost::int32_t>(0); k < n_scale; k++)
+ for (std::int32_t k = static_cast<std::int32_t>(0); k < n_scale; k++)
{
// Rescale the cosine value using the multiple angle identity.
eval_multiply(t2, result, ui_type(3));
@@ -222,15 +344,16 @@ void eval_sin(T& result, const T& x)
}
}
- if(b_negate_sin)
+ if (b_negate_sin)
result.negate();
+ BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific));
}
template <class T>
void eval_cos(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The cos function is only valid for floating point types.");
- if(&result == &x)
+ static_assert(number_category<T>::value == number_kind_floating_point, "The cos function is only valid for floating point types.");
+ if (&result == &x)
{
T temp;
eval_cos(temp, x);
@@ -238,26 +361,25 @@ void eval_cos(T& result, const T& x)
return;
}
- typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
- typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
- typedef typename mpl::front<typename T::float_types>::type fp_type;
+ using si_type = typename boost::multiprecision::detail::canonical<std::int32_t, T>::type ;
+ using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
- switch(eval_fpclassify(x))
+ switch (eval_fpclassify(x))
{
case FP_INFINITE:
case FP_NAN:
- if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
{
result = std::numeric_limits<number<T, et_on> >::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."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
case FP_ZERO:
result = ui_type(1);
return;
- default: ;
+ default:;
}
// Local copy of the argument
@@ -268,93 +390,106 @@ 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();
}
+ BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
T n_pi, t;
+ T half_pi = get_constant_pi<T>();
+ eval_ldexp(half_pi, half_pi, -1); // divide by 2
// Remove even multiples of pi.
- if(xx.compare(get_constant_pi<T>()) > 0)
+ if (xx.compare(half_pi) > 0)
{
- eval_divide(t, xx, get_constant_pi<T>());
+ eval_divide(t, xx, half_pi);
eval_trunc(n_pi, t);
- BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific));
- eval_multiply(t, n_pi, get_constant_pi<T>());
- BOOST_MATH_INSTRUMENT_CODE(t.str(0, std::ios_base::scientific));
//
- // If t is so large that all digits cancel the result of this subtraction
- // is completely meaningless, just assume the result is zero for now...
- //
- // TODO We should of course do much better, see:
- // "ARGUMENT REDUCTION FOR HUGE ARGUMENTS" K C Ng 1992
+ // If n_pi is > 1/epsilon, then it is no longer an exact integer value
+ // but an approximation. As a result we can no longer reliably reduce
+ // xx to 0 <= xx < pi/2, nor can we tell the sign of the result as we need
+ // n_pi % 4 for that, but that will always be zero in this situation.
+ // We could use a higher precision type for n_pi, along with division at
+ // higher precision, but that's rather expensive. So for now we do not support
+ // this, and will see if anyone complains and has a legitimate use case.
//
if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0)
{
result = ui_type(1);
return;
}
+ BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific));
+ t = ui_type(4);
+ eval_fmod(t, n_pi, t);
+
+ bool b_go_down = false;
+ if (t.compare(ui_type(0)) == 0)
+ {
+ b_go_down = true;
+ }
+ else if (t.compare(ui_type(1)) == 0)
+ {
+ b_negate_cos = true;
+ }
+ else if (t.compare(ui_type(2)) == 0)
+ {
+ b_go_down = true;
+ b_negate_cos = true;
+ }
else
- eval_subtract(xx, t);
- BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
+ {
+ BOOST_MP_ASSERT(t.compare(ui_type(3)) == 0);
+ }
- // Adjust signs if the multiple of pi is not even.
- t = ui_type(2);
- eval_fmod(t, n_pi, t);
- const bool b_n_pi_is_even = eval_get_sign(t) == 0;
+ if (b_go_down)
+ eval_increment(n_pi);
- if(!b_n_pi_is_even)
+ reduce_n_half_pi(xx, n_pi, b_go_down);
+ //
+ // Post reduction we may be a few ulp below zero or above pi/2
+ // given that n_pi was calculated at working precision and not
+ // at the higher precision used for reduction. Correct that now:
+ //
+ if (eval_get_sign(xx) < 0)
{
+ xx.negate();
b_negate_cos = !b_negate_cos;
}
+ if (xx.compare(half_pi) > 0)
+ {
+ eval_ldexp(half_pi, half_pi, 1);
+ eval_subtract(xx, half_pi, xx);
+ eval_ldexp(half_pi, half_pi, -1);
+ }
+ BOOST_MP_ASSERT(xx.compare(half_pi) <= 0);
+ BOOST_MP_ASSERT(xx.compare(ui_type(0)) >= 0);
}
-
- // Reduce the argument to 0 <= xx <= pi/2.
- eval_ldexp(t, get_constant_pi<T>(), -1);
- int com = xx.compare(t);
- if(com > 0)
+ else
{
- eval_subtract(xx, get_constant_pi<T>(), xx);
- b_negate_cos = !b_negate_cos;
- BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
+ n_pi = ui_type(1);
+ reduce_n_half_pi(xx, n_pi, true);
}
- const bool b_zero = eval_get_sign(xx) == 0;
- 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_zero = eval_get_sign(xx) == 0;
- if(b_zero)
- {
- result = si_type(1);
- }
- else if(b_pi_half)
+ if (b_zero)
{
result = si_type(0);
}
- else if(b_near_zero)
- {
- eval_multiply(t, xx, xx);
- eval_divide(t, si_type(-4));
- n_pi = fp_type(0.5f);
- hyp0F1(result, n_pi, t);
- BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific));
- }
else
{
- eval_subtract(t, xx);
- eval_sin(result, t);
+ eval_sin(result, xx);
}
- if(b_negate_cos)
+ if (b_negate_cos)
result.negate();
+ BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific));
}
template <class T>
void eval_tan(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The tan function is only valid for floating point types.");
- if(&result == &x)
+ static_assert(number_category<T>::value == number_kind_floating_point, "The tan function is only valid for floating point types.");
+ if (&result == &x)
{
T temp;
eval_tan(temp, x);
@@ -370,19 +505,19 @@ void eval_tan(T& result, const T& x)
template <class T>
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<boost::uint32_t, T>::type ui_type;
+ using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::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 +527,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<number<T, et_on> >::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<number<T, et_on> >::value() < 100
- ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
+ const unsigned series_limit =
+ boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
+ ? 100
+ : boost::multiprecision::detail::digits2<number<T, et_on> >::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,75 +555,75 @@ 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)
- BOOST_THROW_EXCEPTION(std::runtime_error("H2F1 failed to converge."));
+ if (n > series_limit)
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("H2F1 failed to converge."));
}
template <class T>
void eval_asin(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The asin function is only valid for floating point types.");
- typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
- typedef typename mpl::front<typename T::float_types>::type fp_type;
+ static_assert(number_category<T>::value == number_kind_floating_point, "The asin function is only valid for floating point types.");
+ using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
+ using fp_type = typename std::tuple_element<0, typename T::float_types>::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<number<T, et_on> >::has_quiet_NaN)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
{
result = std::numeric_limits<number<T, et_on> >::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."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
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<number<T, et_on> >::has_quiet_NaN)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
{
result = std::numeric_limits<number<T, et_on> >::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."));
+ BOOST_MP_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<T>();
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-3)) < 0)
{
// http://functions.wolfram.com/ElementaryFunctions/ArcSin/26/01/01/
eval_multiply(xx, xx);
@@ -498,8 +634,11 @@ 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 - 5e-2f)) > 0)
{
+ // http://functions.wolfram.com/ElementaryFunctions/ArcSin/26/01/01/
+ // This branch is simlilar in complexity to Newton iterations down to
+ // the above limit. It is *much* more accurate.
T dx1;
T t1, t2;
eval_subtract(dx1, ui_type(1), xx);
@@ -513,14 +652,14 @@ void eval_asin(T& result, const T& x)
eval_ldexp(t1, get_constant_pi<T>(), -1);
result.negate();
eval_add(result, t1);
- if(b_neg)
+ if (b_neg)
result.negate();
return;
}
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
- typedef typename boost::multiprecision::detail::canonical<long double, T>::type guess_type;
+ using guess_type = typename boost::multiprecision::detail::canonical<long double, T>::type;
#else
- typedef fp_type guess_type;
+ using guess_type = fp_type;
#endif
// Get initial estimate using standard math function asin.
guess_type dd;
@@ -528,16 +667,18 @@ 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<number<T> >::digits * 2) / 3;
+ std::intmax_t current_precision = eval_ilogb(result);
+ std::intmax_t target_precision = std::numeric_limits<number<T> >::is_specialized ?
+ current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3
+ : current_precision - 1 - (boost::multiprecision::detail::digits2<number<T> >::value() * 2) / 3;
// Newton-Raphson iteration
- while(current_precision > target_precision)
+ while (current_precision > target_precision)
{
T sine, cosine;
eval_sin(sine, result);
@@ -546,30 +687,30 @@ 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<typename T::exponent_type>::min)() + 1)
+ if (current_precision <= (std::numeric_limits<typename T::exponent_type>::min)() + 1)
break;
}
- if(b_neg)
+ if (b_neg)
result.negate();
}
template <class T>
inline void eval_acos(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The acos function is only valid for floating point types.");
- typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
+ static_assert(number_category<T>::value == number_kind_floating_point, "The acos function is only valid for floating point types.");
+ using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
- switch(eval_fpclassify(x))
+ switch (eval_fpclassify(x))
{
case FP_NAN:
case FP_INFINITE:
- if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
{
result = std::numeric_limits<number<T, et_on> >::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."));
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
case FP_ZERO:
result = get_constant_pi<T>();
@@ -577,55 +718,127 @@ inline void eval_acos(T& result, const T& x)
return;
}
- eval_abs(result, x);
- int c = result.compare(ui_type(1));
+ T xx;
+ eval_abs(xx, x);
+ int c = xx.compare(ui_type(1));
- if(c > 0)
+ if (c > 0)
{
- if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
{
result = std::numeric_limits<number<T, et_on> >::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."));
+ BOOST_MP_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<T>();
else
result = ui_type(0);
return;
}
- eval_asin(result, x);
- T t;
- eval_ldexp(t, get_constant_pi<T>(), -1);
- eval_subtract(result, t);
- result.negate();
+ using fp_type = typename std::tuple_element<0, typename T::float_types>::type;
+
+ if (xx.compare(fp_type(1e-3)) < 0)
+ {
+ // https://functions.wolfram.com/ElementaryFunctions/ArcCos/26/01/01/
+ eval_multiply(xx, xx);
+ T t1, t2;
+ t1 = fp_type(0.5f);
+ t2 = fp_type(1.5f);
+ hyp2F1(result, t1, t1, t2, xx);
+ eval_multiply(result, x);
+ eval_ldexp(t1, get_constant_pi<T>(), -1);
+ result.negate();
+ eval_add(result, t1);
+ return;
+ }
+ if (eval_get_sign(x) < 0)
+ {
+ eval_acos(result, xx);
+ result.negate();
+ eval_add(result, get_constant_pi<T>());
+ return;
+ }
+ else if (xx.compare(fp_type(0.85)) > 0)
+ {
+ // https://functions.wolfram.com/ElementaryFunctions/ArcCos/26/01/01/
+ // This branch is simlilar in complexity to Newton iterations down to
+ // the above limit. It is *much* more accurate.
+ T dx1;
+ T t1, t2;
+ eval_subtract(dx1, ui_type(1), xx);
+ t1 = fp_type(0.5f);
+ t2 = fp_type(1.5f);
+ eval_ldexp(dx1, dx1, -1);
+ hyp2F1(result, t1, t1, t2, dx1);
+ eval_ldexp(dx1, dx1, 2);
+ eval_sqrt(t1, dx1);
+ eval_multiply(result, t1);
+ return;
+ }
+
+#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
+ using guess_type = typename boost::multiprecision::detail::canonical<long double, T>::type;
+#else
+ using guess_type = fp_type;
+#endif
+ // Get initial estimate using standard math function asin.
+ guess_type dd;
+ eval_convert_to(&dd, xx);
+
+ result = (guess_type)(std::acos(dd));
+
+ // 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
+ // we've just added will finish the job...
+
+ std::intmax_t current_precision = eval_ilogb(result);
+ std::intmax_t target_precision = std::numeric_limits<number<T> >::is_specialized ?
+ current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3
+ : current_precision - 1 - (boost::multiprecision::detail::digits2<number<T> >::value() * 2) / 3;
+
+ // Newton-Raphson iteration
+ while (current_precision > target_precision)
+ {
+ T sine, cosine;
+ eval_sin(sine, result);
+ eval_cos(cosine, result);
+ eval_subtract(cosine, xx);
+ cosine.negate();
+ eval_divide(cosine, sine);
+ eval_subtract(result, cosine);
+ current_precision = eval_ilogb(cosine);
+ if (current_precision <= (std::numeric_limits<typename T::exponent_type>::min)() + 1)
+ break;
+ }
}
template <class T>
void eval_atan(T& result, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The atan function is only valid for floating point types.");
- typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
- typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
- typedef typename mpl::front<typename T::float_types>::type fp_type;
+ static_assert(number_category<T>::value == number_kind_floating_point, "The atan function is only valid for floating point types.");
+ using si_type = typename boost::multiprecision::detail::canonical<std::int32_t, T>::type ;
+ using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
+ using fp_type = typename std::tuple_element<0, typename T::float_types>::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<T>(), -1);
result.negate();
@@ -633,16 +846,16 @@ void eval_atan(T& result, const T& x)
else
eval_ldexp(result, get_constant_pi<T>(), -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 +868,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 +878,32 @@ 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<T>(), -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<number<T> >::digits * 2) / 3;
+ std::intmax_t current_precision = eval_ilogb(result);
+ std::intmax_t target_precision = std::numeric_limits<number<T> >::is_specialized ?
+ current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3
+ : current_precision - 1 - (boost::multiprecision::detail::digits2<number<T> >::value() * 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,108 +912,108 @@ 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<typename T::exponent_type>::min)() + 1)
+ if (current_precision <= (std::numeric_limits<typename T::exponent_type>::min)() + 1)
break;
}
- if(b_neg)
+ if (b_neg)
result.negate();
}
template <class T>
void eval_atan2(T& result, const T& y, const T& x)
{
- BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The atan2 function is only valid for floating point types.");
- if(&result == &y)
+ static_assert(number_category<T>::value == number_kind_floating_point, "The atan2 function is only valid for floating point types.");
+ 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);
return;
}
- typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
+ using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::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<T>();
- 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<T>();
+ 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<T>(), -2);
- eval_subtract(result, get_constant_pi<T>());
- if(eval_get_sign(y) >= 0)
- result.negate();
- }
- else
- {
- // Pi/4
- eval_ldexp(result, get_constant_pi<T>(), -2);
- if(eval_get_sign(y) < 0)
- result.negate();
- }
+ // 3Pi/4
+ eval_ldexp(result, get_constant_pi<T>(), -2);
+ eval_subtract(result, get_constant_pi<T>());
+ if (eval_get_sign(y) >= 0)
+ result.negate();
}
else
{
- eval_ldexp(result, get_constant_pi<T>(), -1);
- if(eval_get_sign(y) < 0)
+ // Pi/4
+ eval_ldexp(result, get_constant_pi<T>(), -2);
+ if (eval_get_sign(y) < 0)
result.negate();
}
- return;
}
+ else
+ {
+ eval_ldexp(result, get_constant_pi<T>(), -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<T>(), -1);
- if(eval_get_sign(y) < 0)
- result.negate();
- return;
- }
+ {
+ eval_ldexp(result, get_constant_pi<T>(), -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<T>();
- 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 +1022,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<T>());
else
eval_add(result, get_constant_pi<T>());
}
}
-template<class T, class A>
-inline typename enable_if<is_arithmetic<A>, void>::type eval_atan2(T& result, const T& x, const A& a)
+template <class T, class A>
+inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_atan2(T& result, const T& x, const A& a)
{
- typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
- typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
- cast_type c;
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
+ cast_type c;
c = a;
eval_atan2(result, x, c);
}
-template<class T, class A>
-inline typename enable_if<is_arithmetic<A>, void>::type eval_atan2(T& result, const A& x, const T& a)
+template <class T, class A>
+inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_atan2(T& result, const A& x, const T& a)
{
- typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
- typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
- cast_type c;
+ using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
+ using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
+ cast_type c;
c = x;
eval_atan2(result, c, a);
}
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/trunc.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/trunc.hpp
new file mode 100644
index 0000000000..ce440314fd
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/functions/trunc.hpp
@@ -0,0 +1,76 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2022 Matt Borland. 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_MP_DETAIL_FUNCTIONS_TRUNC_HPP
+#define BOOST_MP_DETAIL_FUNCTIONS_TRUNC_HPP
+
+#include <cmath>
+#include <limits>
+#include <stdexcept>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+
+#ifdef BOOST_MP_MATH_AVAILABLE
+#include <boost/math/special_functions/trunc.hpp>
+#endif
+
+namespace boost { namespace multiprecision { namespace detail {
+
+namespace impl {
+
+template <typename T>
+inline T trunc BOOST_PREVENT_MACRO_SUBSTITUTION (const T arg)
+{
+ using std::floor;
+ using std::ceil;
+
+ return (arg > 0) ? floor(arg) : ceil(arg);
+}
+
+} // namespace impl
+
+#ifdef BOOST_MP_MATH_AVAILABLE
+
+template <typename T>
+inline long long lltrunc BOOST_PREVENT_MACRO_SUBSTITUTION (const T arg)
+{
+ return boost::math::lltrunc(arg);
+}
+
+template <typename T>
+inline int itrunc BOOST_PREVENT_MACRO_SUBSTITUTION (const T arg)
+{
+ return boost::math::itrunc(arg);
+}
+
+#else
+
+template <typename T>
+inline long long lltrunc BOOST_PREVENT_MACRO_SUBSTITUTION (const T arg)
+{
+ if (arg > LLONG_MAX)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("arg cannot be converted into a long long"));
+ }
+
+ return static_cast<long long>(boost::multiprecision::detail::impl::trunc(arg));
+}
+
+template <typename T>
+inline int itrunc BOOST_PREVENT_MACRO_SUBSTITUTION (const T arg)
+{
+ if (arg > static_cast<T>(INT_MAX))
+ {
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("arg cannot be converted into an int"));
+ }
+
+ return static_cast<int>(boost::multiprecision::detail::impl::trunc(arg));
+}
+
+#endif
+
+}}} // Namespaces
+
+#endif // BOOST_MP_DETAIL_FUNCTIONS_TRUNC_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/generic_interconvert.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/generic_interconvert.hpp
index ac3fe6640b..61a9ffbda5 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/generic_interconvert.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/generic_interconvert.hpp
@@ -6,17 +6,23 @@
#ifndef BOOST_MP_GENERIC_INTERCONVERT_HPP
#define BOOST_MP_GENERIC_INTERCONVERT_HPP
+#include <cmath>
+#include <limits>
+#include <boost/multiprecision/detail/standalone_config.hpp>
#include <boost/multiprecision/detail/default_ops.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+#include <boost/multiprecision/detail/functions/trunc.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
-#pragma warning(disable:4127 6326)
+#pragma warning(disable : 4127 6326)
#endif
-namespace boost{ namespace multiprecision{ namespace detail{
+namespace boost { namespace multiprecision { namespace detail {
template <class To, class From>
-inline To do_cast(const From & from)
+inline To do_cast(const From& from)
{
return static_cast<To>(from);
}
@@ -27,27 +33,27 @@ inline To do_cast(const number<B, et>& from)
}
template <class To, class From>
-void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/)
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/)
{
- using default_ops::eval_get_sign;
+ using default_ops::eval_add;
using default_ops::eval_bitwise_and;
using default_ops::eval_convert_to;
- using default_ops::eval_right_shift;
- using default_ops::eval_ldexp;
- using default_ops::eval_add;
+ using default_ops::eval_get_sign;
using default_ops::eval_is_zero;
+ using default_ops::eval_ldexp;
+ using default_ops::eval_right_shift;
// smallest unsigned type handled natively by "From" is likely to be it's limb_type:
- typedef typename canonical<unsigned char, From>::type l_limb_type;
+ using l_limb_type = typename canonical<unsigned char, From>::type;
// get the corresponding type that we can assign to "To":
- typedef typename canonical<l_limb_type, To>::type to_type;
- From t(from);
- bool is_neg = eval_get_sign(t) < 0;
- if(is_neg)
+ using to_type = typename canonical<l_limb_type, To>::type;
+ From t(from);
+ bool is_neg = eval_get_sign(t) < 0;
+ if (is_neg)
t.negate();
// Pick off the first limb:
l_limb_type limb;
l_limb_type mask = static_cast<l_limb_type>(~static_cast<l_limb_type>(0));
- From fl;
+ From fl;
eval_bitwise_and(fl, t, mask);
eval_convert_to(&limb, fl);
to = static_cast<to_type>(limb);
@@ -55,9 +61,9 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
//
// Then keep picking off more limbs until "t" is zero:
//
- To l;
+ To l;
unsigned shift = std::numeric_limits<l_limb_type>::digits;
- while(!eval_is_zero(t))
+ while (!eval_is_zero(t))
{
eval_bitwise_and(fl, t, mask);
eval_convert_to(&limb, fl);
@@ -70,32 +76,32 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
//
// Finish off by setting the sign:
//
- if(is_neg)
+ if (is_neg)
to.negate();
}
template <class To, class From>
-void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/)
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/)
{
- using default_ops::eval_get_sign;
using default_ops::eval_bitwise_and;
- using default_ops::eval_convert_to;
- using default_ops::eval_right_shift;
- using default_ops::eval_left_shift;
using default_ops::eval_bitwise_or;
+ using default_ops::eval_convert_to;
+ using default_ops::eval_get_sign;
using default_ops::eval_is_zero;
+ using default_ops::eval_left_shift;
+ using default_ops::eval_right_shift;
// smallest unsigned type handled natively by "From" is likely to be it's limb_type:
- typedef typename canonical<unsigned char, From>::type limb_type;
+ using limb_type = typename canonical<unsigned char, From>::type;
// get the corresponding type that we can assign to "To":
- typedef typename canonical<limb_type, To>::type to_type;
- From t(from);
- bool is_neg = eval_get_sign(t) < 0;
- if(is_neg)
+ using to_type = typename canonical<limb_type, To>::type;
+ From t(from);
+ bool is_neg = eval_get_sign(t) < 0;
+ if (is_neg)
t.negate();
// Pick off the first limb:
limb_type limb;
limb_type mask = static_cast<limb_type>(~static_cast<limb_type>(0));
- From fl;
+ From fl;
eval_bitwise_and(fl, t, mask);
eval_convert_to(&limb, fl);
to = static_cast<to_type>(limb);
@@ -103,9 +109,9 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
//
// Then keep picking off more limbs until "t" is zero:
//
- To l;
+ To l;
unsigned shift = std::numeric_limits<limb_type>::digits;
- while(!eval_is_zero(t))
+ while (!eval_is_zero(t))
{
eval_bitwise_and(fl, t, mask);
eval_convert_to(&limb, fl);
@@ -118,140 +124,157 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
//
// Finish off by setting the sign:
//
- if(is_neg)
+ if (is_neg)
to.negate();
}
template <class To, class From>
-void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/)
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/)
{
#ifdef BOOST_MSVC
#pragma warning(push)
-#pragma warning(disable:4127)
+//#pragma warning(disable : 4127)
#endif
//
// The code here only works when the radix of "From" is 2, we could try shifting by other
// radixes but it would complicate things.... use a string conversion when the radix is other
// than 2:
//
- if(std::numeric_limits<number<From> >::radix != 2)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<number<From> >::radix != 2)
{
to = from.str(0, std::ios_base::fmtflags()).c_str();
return;
}
+ else
+ {
+ using ui_type = typename canonical<unsigned char, To>::type;
+ using default_ops::eval_add;
+ using default_ops::eval_convert_to;
+ using default_ops::eval_fpclassify;
+ using default_ops::eval_get_sign;
+ using default_ops::eval_is_zero;
+ using default_ops::eval_subtract;
- typedef typename canonical<unsigned char, To>::type ui_type;
-
- using default_ops::eval_fpclassify;
- using default_ops::eval_add;
- using default_ops::eval_subtract;
- using default_ops::eval_convert_to;
- using default_ops::eval_get_sign;
- using default_ops::eval_is_zero;
+ //
+ // First classify the input, then handle the special cases:
+ //
+ int c = eval_fpclassify(from);
- //
- // First classify the input, then handle the special cases:
- //
- int c = eval_fpclassify(from);
+ if (c == static_cast<int>(FP_ZERO))
+ {
+ to = ui_type(0);
+ return;
+ }
+ else if (c == static_cast<int>(FP_NAN))
+ {
+ to = static_cast<const char*>("nan");
+ return;
+ }
+ else if (c == static_cast<int>(FP_INFINITE))
+ {
+ to = static_cast<const char*>("inf");
+ if (eval_get_sign(from) < 0)
+ to.negate();
+ return;
+ }
- if(c == (int)FP_ZERO)
- {
+ typename From::exponent_type e;
+ From f, term;
to = ui_type(0);
- return;
- }
- else if(c == (int)FP_NAN)
- {
- to = static_cast<const char*>("nan");
- return;
- }
- else if(c == (int)FP_INFINITE)
- {
- to = static_cast<const char*>("inf");
- if(eval_get_sign(from) < 0)
- to.negate();
- return;
- }
- typename From::exponent_type e;
- From f, term;
- to = ui_type(0);
-
- eval_frexp(f, from, &e);
+ eval_frexp(f, from, &e);
- static const int shift = std::numeric_limits<boost::intmax_t>::digits - 1;
+ constexpr int shift = std::numeric_limits<std::intmax_t>::digits - 1;
- while(!eval_is_zero(f))
- {
- // extract int sized bits from f:
- eval_ldexp(f, f, shift);
- eval_floor(term, f);
- e -= shift;
- eval_ldexp(to, to, shift);
- typename boost::multiprecision::detail::canonical<boost::intmax_t, To>::type ll;
- eval_convert_to(&ll, term);
- eval_add(to, ll);
- eval_subtract(f, term);
- }
- typedef typename To::exponent_type to_exponent;
- if((e > (std::numeric_limits<to_exponent>::max)()) || (e < (std::numeric_limits<to_exponent>::min)()))
- {
- to = static_cast<const char*>("inf");
- if(eval_get_sign(from) < 0)
- to.negate();
- return;
+ while (!eval_is_zero(f))
+ {
+ // extract int sized bits from f:
+ eval_ldexp(f, f, shift);
+ eval_floor(term, f);
+ e -= shift;
+ eval_ldexp(to, to, shift);
+ typename boost::multiprecision::detail::canonical<std::intmax_t, To>::type ll;
+ eval_convert_to(&ll, term);
+ eval_add(to, ll);
+ eval_subtract(f, term);
+ }
+ using to_exponent = typename To::exponent_type;
+ if (e > (std::numeric_limits<to_exponent>::max)())
+ {
+ to = static_cast<const char*>("inf");
+ if (eval_get_sign(from) < 0)
+ to.negate();
+ return;
+ }
+ if (e < (std::numeric_limits<to_exponent>::min)())
+ {
+ to = ui_type(0);
+ if (eval_get_sign(from) < 0)
+ to.negate();
+ return;
+ }
+ eval_ldexp(to, to, static_cast<to_exponent>(e));
}
- eval_ldexp(to, to, static_cast<to_exponent>(e));
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template <class To, class From>
-void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/)
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/)
{
- typedef typename component_type<number<To> >::type to_component_type;
+ using to_component_type = typename component_type<number<To> >::type;
- number<From> t(from);
+ number<From> t(from);
to_component_type n(numerator(t)), d(denominator(t));
using default_ops::assign_components;
assign_components(to, n.backend(), d.backend());
}
template <class To, class From>
-void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/)
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/)
{
- typedef typename component_type<number<To> >::type to_component_type;
+ using to_component_type = typename component_type<number<To> >::type;
- number<From> t(from);
+ number<From> t(from);
to_component_type n(t), d(1);
using default_ops::assign_components;
assign_components(to, n.backend(), d.backend());
}
+template <class LargeInteger>
+inline typename std::enable_if<is_signed_number<LargeInteger>::value>::type make_positive(LargeInteger& val)
+{
+ if (val.sign() < 0)
+ val = -val;
+}
+template <class LargeInteger>
+inline typename std::enable_if<!is_signed_number<LargeInteger>::value>::type make_positive(LargeInteger&){}
+
template <class R, class LargeInteger>
R safe_convert_to_float(const LargeInteger& i)
{
- using std::ldexp;
- if(!i)
+ if (!i)
return R(0);
- if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::max_exponent)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::max_exponent)
{
+ using std::ldexp;
+
LargeInteger val(i);
- if(val.sign() < 0)
- val = -val;
- unsigned mb = msb(val);
- if(mb >= std::numeric_limits<R>::max_exponent)
+ make_positive(val);
+ std::size_t mb = msb(val);
+ if (mb >= std::numeric_limits<R>::max_exponent)
{
- int scale_factor = (int)mb + 1 - std::numeric_limits<R>::max_exponent;
- BOOST_ASSERT(scale_factor >= 1);
+ int scale_factor = static_cast<int>(mb) + 1 - std::numeric_limits<R>::max_exponent;
+ BOOST_MP_ASSERT(scale_factor >= 1);
val >>= scale_factor;
R result = val.template convert_to<R>();
- if(std::numeric_limits<R>::digits == 0 || std::numeric_limits<R>::digits >= std::numeric_limits<R>::max_exponent)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::digits == 0 || std::numeric_limits<R>::digits >= std::numeric_limits<R>::max_exponent)
{
//
// Calculate and add on the remainder, only if there are more
- // digits in the mantissa that the size of the exponent, in
+ // digits in the mantissa that the size of the exponent, in
// other words if we are dropping digits in the conversion
// otherwise:
//
@@ -266,8 +289,8 @@ R safe_convert_to_float(const LargeInteger& i)
}
template <class To, class Integer>
-inline typename disable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
- generic_convert_rational_to_float_imp(To& result, const Integer& n, const Integer& d, const mpl::true_&)
+inline typename std::enable_if<!(is_number<To>::value || std::is_floating_point<To>::value)>::type
+generic_convert_rational_to_float_imp(To& result, const Integer& n, const Integer& d, const std::integral_constant<bool, true>&)
{
//
// If we get here, then there's something about one type or the other
@@ -279,8 +302,8 @@ inline typename disable_if_c<is_number<To>::value || is_floating_point<To>::valu
eval_divide(result, fn.backend(), fd.backend());
}
template <class To, class Integer>
-inline typename enable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
- generic_convert_rational_to_float_imp(To& result, const Integer& n, const Integer& d, const mpl::true_&)
+inline typename std::enable_if<is_number<To>::value || std::is_floating_point<To>::value>::type
+generic_convert_rational_to_float_imp(To& result, const Integer& n, const Integer& d, const std::integral_constant<bool, true>&)
{
//
// If we get here, then there's something about one type or the other
@@ -293,69 +316,69 @@ inline typename enable_if_c<is_number<To>::value || is_floating_point<To>::value
}
template <class To, class Integer>
-typename enable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
- generic_convert_rational_to_float_imp(To& result, Integer& num, Integer& denom, const mpl::false_&)
+typename std::enable_if<is_number<To>::value || std::is_floating_point<To>::value>::type
+generic_convert_rational_to_float_imp(To& result, Integer& num, Integer& denom, const std::integral_constant<bool, false>&)
{
//
// If we get here, then the precision of type To is known, and the integer type is unbounded
// so we can use integer division plus manipulation of the remainder to get an exactly
// rounded result.
//
- if(num == 0)
+ if (num == 0)
{
result = 0;
return;
}
bool s = false;
- if(num < 0)
+ if (num < 0)
{
- s = true;
+ s = true;
num = -num;
}
- int denom_bits = msb(denom);
- int shift = std::numeric_limits<To>::digits + denom_bits - msb(num);
- if(shift > 0)
+ std::ptrdiff_t denom_bits = msb(denom);
+ std::ptrdiff_t shift = std::numeric_limits<To>::digits + denom_bits - msb(num);
+ if (shift > 0)
num <<= shift;
- else if(shift < 0)
+ else if (shift < 0)
denom <<= boost::multiprecision::detail::unsigned_abs(shift);
Integer q, r;
divide_qr(num, denom, q, r);
- int q_bits = msb(q);
- if(q_bits == std::numeric_limits<To>::digits - 1)
+ std::ptrdiff_t q_bits = msb(q);
+ if (q_bits == std::numeric_limits<To>::digits - 1)
{
//
// Round up if 2 * r > denom:
//
r <<= 1;
int c = r.compare(denom);
- if(c > 0)
+ if (c > 0)
++q;
- else if((c == 0) && (q & 1u))
+ else if ((c == 0) && (q & 1u))
{
++q;
}
}
else
{
- BOOST_ASSERT(q_bits == std::numeric_limits<To>::digits);
+ BOOST_MP_ASSERT(q_bits == std::numeric_limits<To>::digits);
//
// We basically already have the rounding info:
//
- if(q & 1u)
+ if (q & 1u)
{
- if(r || (q & 2u))
+ if (r || (q & 2u))
++q;
}
}
using std::ldexp;
result = do_cast<To>(q);
- result = ldexp(result, -shift);
- if(s)
+ result = ldexp(result, static_cast<int>(-shift));
+ if (s)
result = -result;
}
template <class To, class Integer>
-inline typename disable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
- generic_convert_rational_to_float_imp(To& result, Integer& num, Integer& denom, const mpl::false_& tag)
+inline typename std::enable_if<!(is_number<To>::value || std::is_floating_point<To>::value)>::type
+generic_convert_rational_to_float_imp(To& result, Integer& num, Integer& denom, const std::integral_constant<bool, false>& tag)
{
number<To> t;
generic_convert_rational_to_float_imp(t, num, denom, tag);
@@ -372,62 +395,64 @@ inline void generic_convert_rational_to_float(To& result, const From& f)
// that way we can call this from generic conversions, and
// from specific conversions to built in types.
//
- typedef typename mpl::if_c<is_number<From>::value, From, number<From> >::type actual_from_type;
- typedef typename mpl::if_c<is_number<To>::value || is_floating_point<To>::value, To, number<To> >::type actual_to_type;
- typedef typename component_type<actual_from_type>::type integer_type;
- typedef mpl::bool_<!std::numeric_limits<integer_type>::is_specialized
- || std::numeric_limits<integer_type>::is_bounded
- || !std::numeric_limits<actual_to_type>::is_specialized
- || !std::numeric_limits<actual_to_type>::is_bounded
- || (std::numeric_limits<actual_to_type>::radix != 2)> dispatch_tag;
+ using actual_from_type = typename std::conditional<is_number<From>::value, From, number<From> >::type ;
+ using actual_to_type = typename std::conditional<is_number<To>::value || std::is_floating_point<To>::value, To, number<To> >::type ;
+ using integer_type = typename component_type<actual_from_type>::type ;
+ using dispatch_tag = std::integral_constant<bool, !std::numeric_limits<integer_type>::is_specialized || std::numeric_limits<integer_type>::is_bounded || !std::numeric_limits<actual_to_type>::is_specialized || !std::numeric_limits<actual_to_type>::is_bounded || (std::numeric_limits<actual_to_type>::radix != 2)>;
integer_type n(numerator(static_cast<actual_from_type>(f))), d(denominator(static_cast<actual_from_type>(f)));
generic_convert_rational_to_float_imp(result, n, d, dispatch_tag());
}
template <class To, class From>
-inline void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/)
+inline void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/)
{
generic_convert_rational_to_float(to, from);
}
template <class To, class From>
-void generic_interconvert_float2rational(To& to, const From& from, const mpl::int_<2>& /*radix*/)
+void generic_interconvert_float2rational(To& to, const From& from, const std::integral_constant<int, 2>& /*radix*/)
{
- typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
- static const int shift = std::numeric_limits<boost::long_long_type>::digits;
+ using std::ldexp;
+ using std::frexp;
+ using ui_type = typename std::tuple_element<0, typename To::unsigned_types>::type;
+ constexpr int shift = std::numeric_limits<long long>::digits;
typename From::exponent_type e;
- typename component_type<number<To> >::type num, denom;
+ typename component_type<number<To>>::type num, denom;
number<From> val(from);
val = frexp(val, &e);
- while(val)
+ while (val)
{
val = ldexp(val, shift);
e -= shift;
- boost::long_long_type ll = boost::math::lltrunc(val);
+ long long ll = boost::multiprecision::detail::lltrunc(val);
val -= ll;
num <<= shift;
num += ll;
}
denom = ui_type(1u);
- if(e < 0)
+ if (e < 0)
denom <<= -e;
- else if(e > 0)
+ else if (e > 0)
num <<= e;
assign_components(to, num.backend(), denom.backend());
}
template <class To, class From, int Radix>
-void generic_interconvert_float2rational(To& to, const From& from, const mpl::int_<Radix>& /*radix*/)
+void generic_interconvert_float2rational(To& to, const From& from, const std::integral_constant<int, Radix>& /*radix*/)
{
+ using std::ilogb;
+ using std::scalbn;
+ using std::pow;
+ using std::abs;
//
// This is almost the same as the binary case above, but we have to use
// scalbn and ilogb rather than ldexp and frexp, we also only extract
// one Radix digit at a time which is terribly inefficient!
//
- typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
+ using ui_type = typename std::tuple_element<0, typename To::unsigned_types>::type;
typename From::exponent_type e;
- typename component_type<number<To> >::type num, denom;
+ typename component_type<number<To>>::type num, denom;
number<From> val(from);
if (!val)
@@ -436,11 +461,11 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in
return;
}
- e = ilogb(val);
+ e = ilogb(val);
val = scalbn(val, -e);
- while(val)
+ while (val)
{
- boost::long_long_type ll = boost::math::lltrunc(val);
+ long long ll = boost::multiprecision::detail::lltrunc(val);
val -= ll;
val = scalbn(val, 1);
num *= Radix;
@@ -450,7 +475,7 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in
++e;
denom = ui_type(Radix);
denom = pow(denom, abs(e));
- if(e > 0)
+ if (e > 0)
{
num *= denom;
denom = 1;
@@ -459,57 +484,70 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in
}
template <class To, class From>
-void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/)
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/)
{
- generic_interconvert_float2rational(to, from, mpl::int_<std::numeric_limits<number<From> >::radix>());
+ generic_interconvert_float2rational(to, from, std::integral_constant<int, std::numeric_limits<number<From> >::is_specialized ? std::numeric_limits<number<From> >::radix : 2>());
}
template <class To, class From>
-void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/)
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/)
{
number<From> t(from);
- number<To> result(numerator(t) / denominator(t));
+ number<To> result(numerator(t) / denominator(t));
to = result.backend();
}
template <class To, class From>
-void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<2>& /*radix*/)
+void generic_interconvert_float2int(To& to, const From& from, const std::integral_constant<int, 2>& /*radix*/)
{
- typedef typename From::exponent_type exponent_type;
- static const exponent_type shift = std::numeric_limits<boost::long_long_type>::digits;
- exponent_type e;
- number<To> num(0u);
- number<From> val(from);
- val = frexp(val, &e);
- while(e > 0)
+ using std::frexp;
+ using std::ldexp;
+
+ using exponent_type = typename From::exponent_type;
+ constexpr exponent_type shift = std::numeric_limits<long long>::digits;
+ exponent_type e;
+ number<To> num(0u);
+ number<From> val(from);
+ val = frexp(val, &e);
+ bool neg = false;
+ if (val.sign() < 0)
{
- int s = (std::min)(e, shift);
- val = ldexp(val, s);
+ val.backend().negate();
+ neg = true;
+ }
+ while (e > 0)
+ {
+ exponent_type s = (std::min)(e, shift);
+ val = ldexp(val, s);
e -= s;
- boost::long_long_type ll = boost::math::lltrunc(val);
+ long long ll = boost::multiprecision::detail::lltrunc(val);
val -= ll;
num <<= s;
num += ll;
}
to = num.backend();
+ if (neg)
+ to.negate();
}
template <class To, class From, int Radix>
-void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<Radix>& /*radix*/)
+void generic_interconvert_float2int(To& to, const From& from, const std::integral_constant<int, Radix>& /*radix*/)
{
+ using std::ilogb;
+ using std::scalbn;
//
// This is almost the same as the binary case above, but we have to use
// scalbn and ilogb rather than ldexp and frexp, we also only extract
// one Radix digit at a time which is terribly inefficient!
//
typename From::exponent_type e;
- number<To> num(0u);
- number<From> val(from);
- e = ilogb(val);
+ number<To> num(0u);
+ number<From> val(from);
+ e = ilogb(val);
val = scalbn(val, -e);
- while(e >= 0)
+ while (e >= 0)
{
- boost::long_long_type ll = boost::math::lltrunc(val);
+ long long ll = boost::multiprecision::detail::lltrunc(val);
val -= ll;
val = scalbn(val, 1);
num *= Radix;
@@ -520,18 +558,130 @@ void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<Ra
}
template <class To, class From>
-void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/)
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/)
{
- generic_interconvert_float2int(to, from, mpl::int_<std::numeric_limits<number<From> >::radix>());
+ generic_interconvert_float2int(to, from, std::integral_constant<int, (std::numeric_limits<number<From> >::is_specialized ? std::numeric_limits<number<From> >::radix : 2)>());
}
+template <class To, class From, class tag>
+void generic_interconvert_complex_to_scalar(To& to, const From& from, const std::integral_constant<bool, true>&, const tag&)
+{
+ // We just want the real part, and "to" is the correct type already:
+ eval_real(to, from);
+
+ To im;
+ eval_imag(im, from);
+ if (!eval_is_zero(im))
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
+}
+template <class To, class From>
+void generic_interconvert_complex_to_scalar(To& to, const From& from, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
+{
+ using component_number = typename component_type<number<From> >::type;
+ using component_backend = typename component_number::backend_type ;
+ //
+ // Get the real part and copy-construct the result from it:
+ //
+ scoped_precision_options<component_number> scope(from);
+ component_backend r;
+ generic_interconvert_complex_to_scalar(r, from, std::integral_constant<bool, true>(), std::integral_constant<bool, true>());
+ to = r;
}
+template <class To, class From>
+void generic_interconvert_complex_to_scalar(To& to, const From& from, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&)
+{
+ using component_number = typename component_type<number<From> >::type;
+ using component_backend = typename component_number::backend_type;
+ //
+ // Get the real part and use a generic_interconvert to type To:
+ //
+ scoped_precision_options<component_number> scope(from);
+ component_backend r;
+ generic_interconvert_complex_to_scalar(r, from, std::integral_constant<bool, true>(), std::integral_constant<bool, true>());
+ generic_interconvert(to, r, std::integral_constant<int, number_category<To>::value>(), std::integral_constant<int, number_category<component_backend>::value>());
}
-} // namespaces
+
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_complex>& /*from_type*/)
+{
+ using component_number = typename component_type<number<From> >::type;
+ using component_backend = typename component_number::backend_type ;
+
+ generic_interconvert_complex_to_scalar(to, from, std::integral_constant<bool, std::is_same<component_backend, To>::value>(), std::integral_constant<bool, std::is_constructible<To, const component_backend&>::value>());
+}
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_complex>& /*from_type*/)
+{
+ using component_number = typename component_type<number<From> >::type;
+ using component_backend = typename component_number::backend_type ;
+
+ generic_interconvert_complex_to_scalar(to, from, std::integral_constant<bool, std::is_same<component_backend, To>::value>(), std::integral_constant<bool, std::is_constructible<To, const component_backend&>::value>());
+}
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_complex>& /*from_type*/)
+{
+ using component_number = typename component_type<number<From> >::type;
+ using component_backend = typename component_number::backend_type ;
+
+ generic_interconvert_complex_to_scalar(to, from, std::integral_constant<bool, std::is_same<component_backend, To>::value>(), std::integral_constant<bool, std::is_constructible<To, const component_backend&>::value>());
+}
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_complex>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/)
+{
+ using component_number = typename component_type<number<To> >::type;
+
+ scoped_source_precision<number<From> > scope1;
+ scoped_precision_options<component_number> scope2(number<To>::thread_default_precision(), number<To>::thread_default_variable_precision_options());
+ (void)scope1;
+ (void)scope2;
+
+ number<From> f(from);
+ component_number scalar(f);
+ number<To> result(scalar);
+ to = result.backend();
+}
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_complex>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/)
+{
+ using component_number = typename component_type<number<To> >::type;
+
+ scoped_source_precision<number<From> > scope1;
+ scoped_precision_options<component_number> scope2(number<To>::thread_default_precision(), number<To>::thread_default_variable_precision_options());
+ (void)scope1;
+ (void)scope2;
+
+ number<From> f(from);
+ component_number scalar(f);
+ number<To> result(scalar);
+ to = result.backend();
+}
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_complex>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/)
+{
+ using component_number = typename component_type<number<To> >::type;
+
+ scoped_source_precision<number<From> > scope1;
+ scoped_precision_options<component_number> scope2(number<To>::thread_default_precision(), number<To>::thread_default_variable_precision_options());
+ (void)scope1;
+ (void)scope2;
+
+ number<From> f(from);
+ component_number scalar(f);
+ number<To> result(scalar);
+ to = result.backend();
+}
+template <class To, class From, int Tag1, int Tag2>
+void generic_interconvert(To& /*to*/, const From& /*from*/, const std::integral_constant<int, Tag1>& /*to_type*/, const std::integral_constant<int, Tag2>& /*from_type*/)
+{
+ static_assert(sizeof(To) == 0, "Sorry, you asked for a conversion bewteen types that hasn't been implemented yet!!");
+}
+
+}
+}
+} // namespace boost::multiprecision::detail
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
-#endif // BOOST_MP_GENERIC_INTERCONVERT_HPP
-
+#endif // BOOST_MP_GENERIC_INTERCONVERT_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/hash.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/hash.hpp
new file mode 100644
index 0000000000..664680f80c
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/hash.hpp
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2021 Matt Borland. 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_MP_DETAIL_HASH_HPP
+#define BOOST_MP_DETAIL_HASH_HPP
+
+#include <cstddef>
+#include <functional>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+namespace boost { namespace multiprecision { namespace detail {
+
+template <typename T>
+inline std::size_t hash_value(const T& v)
+{
+ std::hash<T> hasher;
+ return hasher(v);
+}
+
+#if defined(BOOST_HAS_INT128)
+
+std::size_t hash_value(const uint128_type& val);
+
+inline std::size_t hash_value(const int128_type& val)
+{
+ return hash_value(static_cast<uint128_type>(val));
+}
+
+#endif
+
+inline void hash_combine(std::size_t&) {}
+
+template <typename T, typename... Args>
+inline void hash_combine(std::size_t& seed, const T& v, Args... args)
+{
+ constexpr std::size_t adder = 0x9e3779b9;
+ seed = seed ^ (hash_value(v) + adder + (seed<<6) + (seed>>2));
+ hash_combine(seed, args...);
+}
+
+#if defined(BOOST_HAS_INT128)
+
+inline std::size_t hash_value(const uint128_type& val)
+{
+ std::size_t result = static_cast<std::size_t>(val);
+ hash_combine(result, static_cast<std::size_t>(val >> 64));
+ return result;
+}
+
+#endif
+
+}}} // Namespaces
+
+#endif // BOOST_MP_DETAIL_HASH_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/integer_ops.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/integer_ops.hpp
index 4b1a9d8bae..468e4d7596 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/integer_ops.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/integer_ops.hpp
@@ -1,73 +1,68 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
-#ifndef BOOST_MP_INT_FUNC_HPP
-#define BOOST_MP_INT_FUNC_HPP
+#ifndef BOOST_MP_DETAIL_INTEGER_OPS_HPP
+#define BOOST_MP_DETAIL_INTEGER_OPS_HPP
#include <boost/multiprecision/number.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
-namespace boost{ namespace multiprecision{
+namespace boost { namespace multiprecision {
-namespace default_ops
-{
+namespace default_ops {
template <class Backend>
-inline void eval_qr(const Backend& x, const Backend& y, Backend& q, Backend& r)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_qr(const Backend& x, const Backend& y, Backend& q, Backend& r)
{
eval_divide(q, x, y);
eval_modulus(r, x, y);
}
template <class Backend, class Integer>
-inline Integer eval_integer_modulus(const Backend& x, Integer val)
+inline BOOST_MP_CXX14_CONSTEXPR 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<Integer, Backend>::type int_type;
- Backend t;
+ using default_ops::eval_modulus;
+ using int_type = typename boost::multiprecision::detail::canonical<Integer, Backend>::type;
+ Backend t;
eval_modulus(t, x, static_cast<int_type>(val));
- Integer result;
+ Integer result(0);
eval_convert_to(&result, t);
return abs(result);
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
-
template <class B>
-inline void eval_gcd(B& result, const B& a, const B& b)
+inline BOOST_MP_CXX14_CONSTEXPR 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;
+ using default_ops::eval_is_zero;
+ using default_ops::eval_lsb;
- int shift;
+ std::ptrdiff_t shift(0);
B u(a), v(b);
int s = eval_get_sign(u);
/* GCD(0,x) := x */
- if(s < 0)
+ if (s < 0)
{
u.negate();
}
- else if(s == 0)
+ else if (s == 0)
{
result = v;
return;
}
s = eval_get_sign(v);
- if(s < 0)
+ if (s < 0)
{
v.negate();
}
- else if(s == 0)
+ else if (s == 0)
{
result = u;
return;
@@ -76,43 +71,38 @@ inline void eval_gcd(B& result, const B& a, const B& b)
/* 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);
+ std::size_t us = eval_lsb(u);
+ std::size_t vs = eval_lsb(v);
+ shift = static_cast<std::ptrdiff_t>((std::min)(us, vs));
eval_right_shift(u, us);
eval_right_shift(v, vs);
- do
+ 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)
+ if (s > 0)
u.swap(v);
- if(s == 0)
+ if (s == 0)
break;
eval_subtract(v, u);
vs = eval_lsb(v);
eval_right_shift(v, vs);
- }
- while(true);
+ } while (true);
result = u;
eval_left_shift(result, shift);
}
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
template <class B>
-inline void eval_lcm(B& result, const B& a, const B& b)
+inline BOOST_MP_CXX14_CONSTEXPR void eval_lcm(B& result, const B& a, const B& b)
{
- typedef typename mpl::front<typename B::unsigned_types>::type ui_type;
- B t;
+ using ui_type = typename std::tuple_element<0, typename B::unsigned_types>::type;
+ B t;
eval_gcd(t, a, b);
- if(eval_is_zero(t))
+ if (eval_is_zero(t))
{
result = static_cast<ui_type>(0);
}
@@ -121,118 +111,118 @@ inline void eval_lcm(B& result, const B& a, const B& b)
eval_divide(result, a, t);
eval_multiply(result, b);
}
- if(eval_get_sign(result) < 0)
+ if (eval_get_sign(result) < 0)
result.negate();
}
-}
+} // namespace default_ops
template <class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer>::type
- divide_qr(const number<Backend, ExpressionTemplates>& x, const number<Backend, ExpressionTemplates>& y,
- number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer>::type
+divide_qr(const number<Backend, ExpressionTemplates>& x, const number<Backend, ExpressionTemplates>& y,
+ number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r)
{
using default_ops::eval_qr;
eval_qr(x.backend(), y.backend(), q.backend(), r.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer>::type
- divide_qr(const number<Backend, ExpressionTemplates>& x, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& y,
- number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer>::type
+divide_qr(const number<Backend, ExpressionTemplates>& x, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& y,
+ number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r)
{
divide_qr(x, number<Backend, ExpressionTemplates>(y), q, r);
}
template <class tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer>::type
- divide_qr(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x, const number<Backend, ExpressionTemplates>& y,
- number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer>::type
+divide_qr(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x, const number<Backend, ExpressionTemplates>& y,
+ number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r)
{
divide_qr(number<Backend, ExpressionTemplates>(x), y, q, r);
}
template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer>::type
- divide_qr(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& y,
- number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer>::type
+divide_qr(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& y,
+ number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r)
{
divide_qr(number<Backend, ExpressionTemplates>(x), number<Backend, ExpressionTemplates>(y), q, r);
}
template <class Backend, expression_template_option ExpressionTemplates, class Integer>
-inline typename enable_if<mpl::and_<is_integral<Integer>, mpl::bool_<number_category<Backend>::value == number_kind_integer> >, Integer>::type
- integer_modulus(const number<Backend, ExpressionTemplates>& x, Integer val)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value && (number_category<Backend>::value == number_kind_integer), Integer>::type
+integer_modulus(const number<Backend, ExpressionTemplates>& x, Integer val)
{
using default_ops::eval_integer_modulus;
return eval_integer_modulus(x.backend(), val);
}
template <class tag, class A1, class A2, class A3, class A4, class Integer>
-inline typename enable_if<mpl::and_<is_integral<Integer>, mpl::bool_<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer> >, Integer>::type
- integer_modulus(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x, Integer val)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value && (number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer), Integer>::type
+integer_modulus(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x, Integer val)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
return integer_modulus(result_type(x), val);
}
template <class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer, unsigned>::type
- lsb(const number<Backend, ExpressionTemplates>& x)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer, std::size_t>::type
+lsb(const number<Backend, ExpressionTemplates>& x)
{
using default_ops::eval_lsb;
return eval_lsb(x.backend());
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, unsigned>::type
- lsb(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, std::size_t>::type
+lsb(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- number_type n(x);
+ using number_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ number_type n(x);
using default_ops::eval_lsb;
return eval_lsb(n.backend());
}
template <class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer, unsigned>::type
- msb(const number<Backend, ExpressionTemplates>& x)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer, std::size_t>::type
+msb(const number<Backend, ExpressionTemplates>& x)
{
using default_ops::eval_msb;
return eval_msb(x.backend());
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, unsigned>::type
- msb(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, std::size_t>::type
+msb(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- number_type n(x);
+ using number_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ number_type n(x);
using default_ops::eval_msb;
return eval_msb(n.backend());
}
template <class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer, bool>::type
- bit_test(const number<Backend, ExpressionTemplates>& x, unsigned index)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer, bool>::type
+bit_test(const number<Backend, ExpressionTemplates>& x, std::size_t index)
{
using default_ops::eval_bit_test;
return eval_bit_test(x.backend(), index);
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, bool>::type
- bit_test(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x, unsigned index)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, bool>::type
+bit_test(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& x, std::size_t index)
{
- typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
- number_type n(x);
+ using number_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ number_type n(x);
using default_ops::eval_bit_test;
return eval_bit_test(n.backend(), index);
}
template <class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer, number<Backend, ExpressionTemplates>&>::type
- bit_set(number<Backend, ExpressionTemplates>& x, unsigned index)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer, number<Backend, ExpressionTemplates>&>::type
+bit_set(number<Backend, ExpressionTemplates>& x, std::size_t index)
{
using default_ops::eval_bit_set;
eval_bit_set(x.backend(), index);
@@ -240,8 +230,8 @@ inline typename enable_if_c<number_category<Backend>::value == number_kind_integ
}
template <class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer, number<Backend, ExpressionTemplates>&>::type
- bit_unset(number<Backend, ExpressionTemplates>& x, unsigned index)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer, number<Backend, ExpressionTemplates>&>::type
+bit_unset(number<Backend, ExpressionTemplates>& x, std::size_t index)
{
using default_ops::eval_bit_unset;
eval_bit_unset(x.backend(), index);
@@ -249,15 +239,15 @@ inline typename enable_if_c<number_category<Backend>::value == number_kind_integ
}
template <class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<Backend>::value == number_kind_integer, number<Backend, ExpressionTemplates>&>::type
- bit_flip(number<Backend, ExpressionTemplates>& x, unsigned index)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_integer, number<Backend, ExpressionTemplates>&>::type
+bit_flip(number<Backend, ExpressionTemplates>& x, std::size_t 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
@@ -266,7 +256,7 @@ namespace default_ops{
template <class Backend>
struct double_precision_type
{
- typedef Backend type;
+ using type = Backend;
};
//
@@ -274,38 +264,38 @@ struct double_precision_type
// check the value is positive:
//
template <class Backend>
-inline void check_sign_of_backend(const Backend& v, const mpl::true_)
+inline BOOST_MP_CXX14_CONSTEXPR void check_sign_of_backend(const Backend& v, const std::integral_constant<bool, true>)
{
- if(eval_get_sign(v) < 0)
+ if (eval_get_sign(v) < 0)
{
- BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
}
}
template <class Backend>
-inline void check_sign_of_backend(const Backend&, const mpl::false_){}
+inline BOOST_MP_CXX14_CONSTEXPR void check_sign_of_backend(const Backend&, const std::integral_constant<bool, false>) {}
//
// Calculate (a^p)%c:
//
template <class Backend>
-void eval_powm(Backend& result, const Backend& a, const Backend& p, const Backend& c)
+BOOST_MP_CXX14_CONSTEXPR 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_multiply;
using default_ops::eval_right_shift;
- typedef typename double_precision_type<Backend>::type double_type;
- typedef typename boost::multiprecision::detail::canonical<unsigned char, double_type>::type ui_type;
+ using double_type = typename double_precision_type<Backend>::type ;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned char, double_type>::type;
+
+ check_sign_of_backend(p, std::integral_constant<bool, std::numeric_limits<number<Backend> >::is_signed>());
- check_sign_of_backend(p, mpl::bool_<std::numeric_limits<number<Backend> >::is_signed>());
-
double_type x, y(a), b(p), t;
x = ui_type(1u);
- while(eval_get_sign(b) > 0)
+ while (eval_get_sign(b) > 0)
{
- if(eval_bit_test(b, 0))
+ if (eval_bit_test(b, 0))
{
eval_multiply(t, x, y);
eval_modulus(x, t, c);
@@ -319,32 +309,32 @@ void eval_powm(Backend& result, const Backend& a, const Backend& p, const Backen
}
template <class Backend, class Integer>
-void eval_powm(Backend& result, const Backend& a, const Backend& p, Integer c)
+BOOST_MP_CXX14_CONSTEXPR void eval_powm(Backend& result, const Backend& a, const Backend& p, Integer c)
{
- typedef typename double_precision_type<Backend>::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<Integer, Backend>::type i2_type;
+ using double_type = typename double_precision_type<Backend>::type ;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned char, double_type>::type;
+ using i1_type = typename boost::multiprecision::detail::canonical<Integer, double_type>::type ;
+ using i2_type = typename boost::multiprecision::detail::canonical<Integer, Backend>::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_multiply;
using default_ops::eval_right_shift;
- check_sign_of_backend(p, mpl::bool_<std::numeric_limits<number<Backend> >::is_signed>());
+ check_sign_of_backend(p, std::integral_constant<bool, std::numeric_limits<number<Backend> >::is_signed>());
- if(eval_get_sign(p) < 0)
+ if (eval_get_sign(p) < 0)
{
- BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
+ BOOST_MP_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)
+ while (eval_get_sign(b) > 0)
{
- if(eval_bit_test(b, 0))
+ if (eval_bit_test(b, 0))
{
eval_multiply(t, x, y);
eval_modulus(x, t, static_cast<i1_type>(c));
@@ -358,23 +348,23 @@ void eval_powm(Backend& result, const Backend& a, const Backend& p, Integer c)
}
template <class Backend, class Integer>
-typename enable_if<is_unsigned<Integer> >::type eval_powm(Backend& result, const Backend& a, Integer b, const Backend& c)
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value >::type eval_powm(Backend& result, const Backend& a, Integer b, const Backend& c)
{
- typedef typename double_precision_type<Backend>::type double_type;
- typedef typename boost::multiprecision::detail::canonical<unsigned char, double_type>::type ui_type;
+ using double_type = typename double_precision_type<Backend>::type ;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned char, double_type>::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_multiply;
using default_ops::eval_right_shift;
double_type x, y(a), t;
x = ui_type(1u);
- while(b > 0)
+ while (b > 0)
{
- if(b & 1)
+ if (b & 1)
{
eval_multiply(t, x, y);
eval_modulus(x, t, c);
@@ -388,35 +378,35 @@ typename enable_if<is_unsigned<Integer> >::type eval_powm(Backend& result, const
}
template <class Backend, class Integer>
-typename enable_if<is_signed<Integer> >::type eval_powm(Backend& result, const Backend& a, Integer b, const Backend& c)
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value>::type eval_powm(Backend& result, const Backend& a, Integer b, const Backend& c)
{
- if(b < 0)
+ if (b < 0)
{
- BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
}
- eval_powm(result, a, static_cast<typename make_unsigned<Integer>::type>(b), c);
+ eval_powm(result, a, static_cast<typename boost::multiprecision::detail::make_unsigned<Integer>::type>(b), c);
}
template <class Backend, class Integer1, class Integer2>
-typename enable_if<is_unsigned<Integer1> >::type eval_powm(Backend& result, const Backend& a, Integer1 b, Integer2 c)
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer1>::value >::type eval_powm(Backend& result, const Backend& a, Integer1 b, Integer2 c)
{
- typedef typename double_precision_type<Backend>::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<Integer2, Backend>::type i2_type;
+ using double_type = typename double_precision_type<Backend>::type ;
+ using ui_type = typename boost::multiprecision::detail::canonical<unsigned char, double_type>::type;
+ using i1_type = typename boost::multiprecision::detail::canonical<Integer1, double_type>::type ;
+ using i2_type = typename boost::multiprecision::detail::canonical<Integer2, Backend>::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_multiply;
using default_ops::eval_right_shift;
double_type x, y(a), t;
x = ui_type(1u);
- while(b > 0)
+ while (b > 0)
{
- if(b & 1)
+ if (b & 1)
{
eval_multiply(t, x, y);
eval_modulus(x, t, static_cast<i1_type>(c));
@@ -430,66 +420,55 @@ typename enable_if<is_unsigned<Integer1> >::type eval_powm(Backend& result, cons
}
template <class Backend, class Integer1, class Integer2>
-typename enable_if<is_signed<Integer1> >::type eval_powm(Backend& result, const Backend& a, Integer1 b, Integer2 c)
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<Integer1>::value && boost::multiprecision::detail::is_integral<Integer1>::value>::type eval_powm(Backend& result, const Backend& a, Integer1 b, Integer2 c)
{
- if(b < 0)
+ if (b < 0)
{
- BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
}
- eval_powm(result, a, static_cast<typename make_unsigned<Integer1>::type>(b), c);
+ eval_powm(result, a, static_cast<typename boost::multiprecision::detail::make_unsigned<Integer1>::type>(b), c);
}
struct powm_func
{
template <class T, class U, class V>
- void operator()(T& result, const T& b, const U& p, const V& m)const
+ BOOST_MP_CXX14_CONSTEXPR void operator()(T& result, const T& b, const U& p, const V& m) const
{
eval_powm(result, b, p, m);
}
+ template <class R, class T, class U, class V>
+ BOOST_MP_CXX14_CONSTEXPR void operator()(R& result, const T& b, const U& p, const V& m) const
+ {
+ T temp;
+ eval_powm(temp, b, p, m);
+ result = std::move(temp);
+ }
};
-}
+} // namespace default_ops
template <class T, class U, class V>
-inline typename enable_if<
- mpl::and_<
- mpl::bool_<number_category<T>::value == number_kind_integer>,
- mpl::or_<
- is_number<T>,
- is_number_expression<T>
- >,
- mpl::or_<
- is_number<U>,
- is_number_expression<U>,
- is_integral<U>
- >,
- mpl::or_<
- is_number<V>,
- is_number_expression<V>,
- is_integral<V>
- >
- >,
- typename mpl::if_<
- is_no_et_number<T>,
- T,
- typename mpl::if_<
- is_no_et_number<U>,
- U,
- typename mpl::if_<
- is_no_et_number<V>,
- V,
- detail::expression<detail::function, default_ops::powm_func, T, U, V> >::type
- >::type
- >::type
- >::type
- powm(const T& b, const U& p, const V& mod)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
+ (number_category<T>::value == number_kind_integer) &&
+ (is_number<T>::value || is_number_expression<T>::value) &&
+ (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_integral<U>::value) &&
+ (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_integral<V>::value),
+ typename std::conditional<
+ is_no_et_number<T>::value,
+ T,
+ typename std::conditional<
+ is_no_et_number<U>::value,
+ U,
+ typename std::conditional<
+ is_no_et_number<V>::value,
+ V,
+ detail::expression<detail::function, default_ops::powm_func, T, U, V> >::type>::type>::type>::type
+powm(const T& b, const U& p, const V& mod)
{
return detail::expression<detail::function, default_ops::powm_func, T, U, V>(
- default_ops::powm_func(), b, p, mod);
+ default_ops::powm_func(), b, p, mod);
}
-}} //namespaces
+}} // namespace boost::multiprecision
#endif
-
-
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/min_max.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/min_max.hpp
index 56ac5346cf..8a78c612b0 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/min_max.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/min_max.hpp
@@ -8,7 +8,7 @@
#include <boost/multiprecision/traits/is_backend.hpp>
-namespace boost{ namespace multiprecision{
+namespace boost { namespace multiprecision {
//
// Expression template overloads for (min) and (max):
@@ -26,89 +26,81 @@ namespace boost{ namespace multiprecision{
// which fails to compile as "long" is not a valid backend type.
//
template <class Backend>
-inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on>&>::type
- (min)(const number<Backend, et_on>& a, const number<Backend, et_on>& b)
+inline typename std::enable_if<boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on>&>::type(min)(const number<Backend, et_on>& a, const number<Backend, et_on>& b)
{
return a < b ? a : b;
}
template <class Backend, class tag, class A1, class A2, class A3, class A4>
-inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type
- (min)(const number<Backend, et_on>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
+inline typename std::enable_if<boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type(min)(const number<Backend, et_on>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
{
number<Backend, et_on> t(b);
- if(a < t)
+ if (a < t)
return a;
- return BOOST_MP_MOVE(t);
+ return std::move(t);
}
template <class tag, class A1, class A2, class A3, class A4, class Backend>
-inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type
- (min)(const detail::expression<tag, A1, A2, A3, A4>& a, const number<Backend, et_on>& b)
+inline typename std::enable_if<boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type(min)(const detail::expression<tag, A1, A2, A3, A4>& a, const number<Backend, et_on>& b)
{
number<Backend, et_on> t(a);
- if(t < b)
- return BOOST_MP_MOVE(t);
+ if (t < b)
+ return std::move(t);
return b;
}
template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename detail::expression<tag, A1, A2, A3, A4>::result_type
- (min)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+inline typename detail::expression<tag, A1, A2, A3, A4>::result_type(min)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
{
typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b);
- if(t1 < t2)
- return BOOST_MP_MOVE(t1);
- return BOOST_MP_MOVE(t2);
+ if (t1 < t2)
+ return std::move(t1);
+ return std::move(t2);
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename detail::expression<tag, A1, A2, A3, A4>::result_type (min)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
+inline typename detail::expression<tag, A1, A2, A3, A4>::result_type(min)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
{
typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b);
- if(t1 < t2)
- return BOOST_MP_MOVE(t1);
- return BOOST_MP_MOVE(t2);
+ if (t1 < t2)
+ return std::move(t1);
+ return std::move(t2);
}
template <class Backend>
-inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on>&>::type
- (max)(const number<Backend, et_on>& a, const number<Backend, et_on>& b)
+inline typename std::enable_if<boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on>&>::type(max)(const number<Backend, et_on>& a, const number<Backend, et_on>& b)
{
return a > b ? a : b;
}
template <class Backend, class tag, class A1, class A2, class A3, class A4>
-inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type
- (max)(const number<Backend, et_on>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
+inline typename std::enable_if<boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type(max)(const number<Backend, et_on>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
{
number<Backend, et_on> t(b);
- if(a > t)
+ if (a > t)
return a;
- return BOOST_MP_MOVE(t);
+ return std::move(t);
}
template <class tag, class A1, class A2, class A3, class A4, class Backend>
-inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type
- (max)(const detail::expression<tag, A1, A2, A3, A4>& a, const number<Backend, et_on>& b)
+inline typename std::enable_if<boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type(max)(const detail::expression<tag, A1, A2, A3, A4>& a, const number<Backend, et_on>& b)
{
number<Backend, et_on> t(a);
- if(t > b)
- return BOOST_MP_MOVE(t);
+ if (t > b)
+ return std::move(t);
return b;
}
template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename detail::expression<tag, A1, A2, A3, A4>::result_type
- (max)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+inline typename detail::expression<tag, A1, A2, A3, A4>::result_type(max)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
{
typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b);
- if(t1 > t2)
- return BOOST_MP_MOVE(t1);
- return BOOST_MP_MOVE(t2);
+ if (t1 > t2)
+ return std::move(t1);
+ return std::move(t2);
}
template <class tag, class A1, class A2, class A3, class A4>
-inline typename detail::expression<tag, A1, A2, A3, A4>::result_type (max)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
+inline typename detail::expression<tag, A1, A2, A3, A4>::result_type(max)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
{
typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b);
- if(t1 > t2)
- return BOOST_MP_MOVE(t1);
- return BOOST_MP_MOVE(t2);
+ if (t1 > t2)
+ return std::move(t1);
+ return std::move(t2);
}
-}} // namespaces
+}} // namespace boost::multiprecision
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/no_et_ops.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/no_et_ops.hpp
index 2faee69d03..a702e85f56 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/no_et_ops.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/no_et_ops.hpp
@@ -8,614 +8,651 @@
#ifdef BOOST_MSVC
#pragma warning(push)
-#pragma warning(disable: 4714)
+#pragma warning(disable : 4714)
#endif
-namespace boost{
-namespace multiprecision{
+namespace boost {
+ namespace multiprecision {
-//
-// Operators for non-expression template enabled number.
-// NOTE: this is not a complete header - really just a suffix to default_ops.hpp.
-// NOTE: these operators have to be defined after the methods in default_ops.hpp.
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator - (const number<B, et_off>& v)
-{
- BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
- number<B, et_off> result(v);
- result.backend().negate();
- return result;
-}
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator ~ (const number<B, et_off>& v)
-{
- number<B, et_off> result;
- eval_complement(result.backend(), v.backend());
- return result;
-}
-//
-// Addition:
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator + (const number<B, et_off>& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_add;
- eval_add(result.backend(), a.backend(), b.backend());
- return result;
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator + (const number<B, et_off>& a, const V& b)
-{
- number<B, et_off> result;
- using default_ops::eval_add;
- eval_add(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
- return result;
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator + (const V& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_add;
- eval_add(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
- return result;
-}
-//
-// Subtraction:
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator - (const number<B, et_off>& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_subtract;
- eval_subtract(result.backend(), a.backend(), b.backend());
- return result;
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator - (const number<B, et_off>& a, const V& b)
-{
- number<B, et_off> result;
- using default_ops::eval_subtract;
- eval_subtract(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
- return result;
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator - (const V& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_subtract;
- eval_subtract(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
- return result;
-}
-//
-// Multiply:
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator * (const number<B, et_off>& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_multiply;
- eval_multiply(result.backend(), a.backend(), b.backend());
- return result;
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator * (const number<B, et_off>& a, const V& b)
-{
- number<B, et_off> result;
- using default_ops::eval_multiply;
- eval_multiply(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
- return result;
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator * (const V& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_multiply;
- eval_multiply(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
- return result;
-}
-//
-// divide:
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator / (const number<B, et_off>& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_divide;
- eval_divide(result.backend(), a.backend(), b.backend());
- return result;
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator / (const number<B, et_off>& a, const V& b)
-{
- number<B, et_off> result;
- using default_ops::eval_divide;
- eval_divide(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
- return result;
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator / (const V& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_divide;
- eval_divide(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
- return result;
-}
-//
-// modulus:
-//
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator % (const number<B, et_off>& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_modulus;
- eval_modulus(result.backend(), a.backend(), b.backend());
- return result;
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator % (const number<B, et_off>& a, const V& b)
-{
- number<B, et_off> result;
- using default_ops::eval_modulus;
- eval_modulus(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
- return result;
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator % (const V& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_modulus;
- eval_modulus(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
- return result;
-}
-//
-// Bitwise or:
-//
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator | (const number<B, et_off>& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_bitwise_or;
- eval_bitwise_or(result.backend(), a.backend(), b.backend());
- return result;
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator | (const number<B, et_off>& a, const V& b)
-{
- number<B, et_off> result;
- using default_ops::eval_bitwise_or;
- eval_bitwise_or(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
- return result;
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator | (const V& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_bitwise_or;
- eval_bitwise_or(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
- return result;
-}
-//
-// Bitwise xor:
-//
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ^ (const number<B, et_off>& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(result.backend(), a.backend(), b.backend());
- return result;
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator ^ (const number<B, et_off>& a, const V& b)
-{
- number<B, et_off> result;
- using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
- return result;
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator ^ (const V& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
- return result;
-}
-//
-// Bitwise and:
-//
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator & (const number<B, et_off>& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_bitwise_and;
- eval_bitwise_and(result.backend(), a.backend(), b.backend());
- return result;
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator & (const number<B, et_off>& a, const V& b)
-{
- number<B, et_off> result;
- using default_ops::eval_bitwise_and;
- eval_bitwise_and(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
- return result;
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator & (const V& a, const number<B, et_off>& b)
-{
- number<B, et_off> result;
- using default_ops::eval_bitwise_and;
- eval_bitwise_and(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
- return result;
-}
-//
-// shifts:
-//
-template <class B, class I>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator << (const number<B, et_off>& a, const I& b)
-{
- number<B, et_off> result(a);
- using default_ops::eval_left_shift;
- detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), is_signed<I>());
- eval_left_shift(result.backend(), b);
- return result;
-}
-template <class B, class I>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator >> (const number<B, et_off>& a, const I& b)
-{
- number<B, et_off> result(a);
- using default_ops::eval_right_shift;
- detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), is_signed<I>());
- eval_right_shift(result.backend(), b);
- return result;
-}
+ //
+ // Operators for non-expression template enabled number.
+ // NOTE: this is not a complete header - really just a suffix to default_ops.hpp.
+ // NOTE: these operators have to be defined after the methods in default_ops.hpp.
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(const number<B, et_off>& v)
+ {
+ static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(v);
+ number<B, et_off> result(v);
+ result.backend().negate();
+ return result;
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator~(const number<B, et_off>& v)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(v);
+ number<B, et_off> result;
+ eval_complement(result.backend(), v.backend());
+ return result;
+ }
+ //
+ // Addition:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(const number<B, et_off>& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ number<B, et_off> result;
+ using default_ops::eval_add;
+ eval_add(result.backend(), a.backend(), b.backend());
+ return result;
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
+ operator+(const number<B, et_off>& a, const V& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ number<B, et_off> result;
+ using default_ops::eval_add;
+ eval_add(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
+ return result;
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator+(const V& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b, a);
+ number<B, et_off> result;
+ using default_ops::eval_add;
+ eval_add(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
+ return result;
+ }
+ //
+ // Subtraction:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(const number<B, et_off>& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ number<B, et_off> result;
+ using default_ops::eval_subtract;
+ eval_subtract(result.backend(), a.backend(), b.backend());
+ return result;
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
+ operator-(const number<B, et_off>& a, const V& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ number<B, et_off> result;
+ using default_ops::eval_subtract;
+ eval_subtract(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
+ return result;
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator-(const V& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b, a);
+ number<B, et_off> result;
+ using default_ops::eval_subtract;
+ eval_subtract(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
+ return result;
+ }
+ //
+ // Multiply:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(const number<B, et_off>& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ number<B, et_off> result;
+ using default_ops::eval_multiply;
+ eval_multiply(result.backend(), a.backend(), b.backend());
+ return result;
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
+ operator*(const number<B, et_off>& a, const V& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ number<B, et_off> result;
+ using default_ops::eval_multiply;
+ eval_multiply(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
+ return result;
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator*(const V& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b, a);
+ number<B, et_off> result;
+ using default_ops::eval_multiply;
+ eval_multiply(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
+ return result;
+ }
+ //
+ // divide:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator/(const number<B, et_off>& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ number<B, et_off> result;
+ using default_ops::eval_divide;
+ eval_divide(result.backend(), a.backend(), b.backend());
+ return result;
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
+ operator/(const number<B, et_off>& a, const V& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ number<B, et_off> result;
+ using default_ops::eval_divide;
+ eval_divide(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
+ return result;
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator/(const V& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b, a);
+ number<B, et_off> result;
+ using default_ops::eval_divide;
+ eval_divide(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
+ return result;
+ }
+ //
+ // modulus:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator%(const number<B, et_off>& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ number<B, et_off> result;
+ using default_ops::eval_modulus;
+ eval_modulus(result.backend(), a.backend(), b.backend());
+ return result;
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator%(const number<B, et_off>& a, const V& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a);
+ number<B, et_off> result;
+ using default_ops::eval_modulus;
+ eval_modulus(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
+ return result;
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator%(const V& a, const number<B, et_off>& b)
+ {
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b);
+ number<B, et_off> result;
+ using default_ops::eval_modulus;
+ eval_modulus(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
+ return result;
+ }
+ //
+ // Bitwise or:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(const number<B, et_off>& a, const number<B, et_off>& b)
+ {
+ number<B, et_off> result;
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(result.backend(), a.backend(), b.backend());
+ return result;
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator|(const number<B, et_off>& a, const V& b)
+ {
+ number<B, et_off> result;
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
+ return result;
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator|(const V& a, const number<B, et_off>& b)
+ {
+ number<B, et_off> result;
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
+ return result;
+ }
+ //
+ // Bitwise xor:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(const number<B, et_off>& a, const number<B, et_off>& b)
+ {
+ number<B, et_off> result;
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(result.backend(), a.backend(), b.backend());
+ return result;
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator^(const number<B, et_off>& a, const V& b)
+ {
+ number<B, et_off> result;
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
+ return result;
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator^(const V& a, const number<B, et_off>& b)
+ {
+ number<B, et_off> result;
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
+ return result;
+ }
+ //
+ // Bitwise and:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(const number<B, et_off>& a, const number<B, et_off>& b)
+ {
+ number<B, et_off> result;
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(result.backend(), a.backend(), b.backend());
+ return result;
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator&(const number<B, et_off>& a, const V& b)
+ {
+ number<B, et_off> result;
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
+ return result;
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator&(const V& a, const number<B, et_off>& b)
+ {
+ number<B, et_off> result;
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
+ return result;
+ }
+ //
+ // shifts:
+ //
+ template <class B, class I>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator<<(const number<B, et_off>& a, const I& b)
+ {
+ number<B, et_off> result(a);
+ using default_ops::eval_left_shift;
+ detail::check_shift_range(b, std::integral_constant<bool, (sizeof(I) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<I>::value>());
+ eval_left_shift(result.backend(), b);
+ return result;
+ }
+ template <class B, class I>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator>>(const number<B, et_off>& a, const I& b)
+ {
+ number<B, et_off> result(a);
+ using default_ops::eval_right_shift;
+ detail::check_shift_range(b, std::integral_constant<bool, (sizeof(I) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<I>::value>());
+ eval_right_shift(result.backend(), b);
+ return result;
+ }
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(__GNUC__) && ((__GNUC__ == 4) && (__GNUC_MINOR__ < 5)))
-//
-// If we have rvalue references go all over again with rvalue ref overloads and move semantics.
-// Note that while it would be tempting to implement these so they return an rvalue reference
-// (and indeed this would be optimally efficient), this is unsafe due to users propensity to
-// write:
-//
-// const T& t = a * b;
-//
-// which would lead to a dangling reference if we didn't return by value. Of course move
-// semantics help a great deal in return by value, so performance is still pretty good...
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator - (number<B, et_off>&& v)
-{
- BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
- v.backend().negate();
- return static_cast<number<B, et_off>&&>(v);
-}
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ~ (number<B, et_off>&& v)
-{
- eval_complement(v.backend(), v.backend());
- return static_cast<number<B, et_off>&&>(v);
-}
-//
-// Addition:
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator + (number<B, et_off>&& a, const number<B, et_off>& b)
-{
- using default_ops::eval_add;
- eval_add(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator + (const number<B, et_off>& a, number<B, et_off>&& b)
-{
- using default_ops::eval_add;
- eval_add(b.backend(), a.backend());
- return static_cast<number<B, et_off>&&>(b);
-}
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator + (number<B, et_off>&& a, number<B, et_off>&& b)
-{
- using default_ops::eval_add;
- eval_add(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator + (number<B, et_off>&& a, const V& b)
-{
- using default_ops::eval_add;
- eval_add(a.backend(), number<B, et_off>::canonical_value(b));
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator + (const V& a, number<B, et_off>&& b)
-{
- using default_ops::eval_add;
- eval_add(b.backend(), number<B, et_off>::canonical_value(a));
- return static_cast<number<B, et_off>&&>(b);
-}
-//
-// Subtraction:
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator - (number<B, et_off>&& a, const number<B, et_off>& b)
-{
- using default_ops::eval_subtract;
- eval_subtract(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if<is_signed_number<B>, number<B, et_off> >::type operator - (const number<B, et_off>& a, number<B, et_off>&& b)
-{
- using default_ops::eval_subtract;
- eval_subtract(b.backend(), a.backend());
- b.backend().negate();
- return static_cast<number<B, et_off>&&>(b);
-}
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator - (number<B, et_off>&& a, number<B, et_off>&& b)
-{
- using default_ops::eval_subtract;
- eval_subtract(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator - (number<B, et_off>&& a, const V& b)
-{
- using default_ops::eval_subtract;
- eval_subtract(a.backend(), number<B, et_off>::canonical_value(b));
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<(is_compatible_arithmetic_type<V, number<B, et_off> >::value && is_signed_number<B>::value), number<B, et_off> >::type
- operator - (const V& a, number<B, et_off>&& b)
-{
- using default_ops::eval_subtract;
- eval_subtract(b.backend(), number<B, et_off>::canonical_value(a));
- b.backend().negate();
- return static_cast<number<B, et_off>&&>(b);
-}
-//
-// Multiply:
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator * (number<B, et_off>&& a, const number<B, et_off>& b)
-{
- using default_ops::eval_multiply;
- eval_multiply(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator * (const number<B, et_off>& a, number<B, et_off>&& b)
-{
- using default_ops::eval_multiply;
- eval_multiply(b.backend(), a.backend());
- return static_cast<number<B, et_off>&&>(b);
-}
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator * (number<B, et_off>&& a, number<B, et_off>&& b)
-{
- using default_ops::eval_multiply;
- eval_multiply(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator * (number<B, et_off>&& a, const V& b)
-{
- using default_ops::eval_multiply;
- eval_multiply(a.backend(), number<B, et_off>::canonical_value(b));
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator * (const V& a, number<B, et_off>&& b)
-{
- using default_ops::eval_multiply;
- eval_multiply(b.backend(), number<B, et_off>::canonical_value(a));
- return static_cast<number<B, et_off>&&>(b);
-}
-//
-// divide:
-//
-template <class B>
-BOOST_MP_FORCEINLINE number<B, et_off> operator / (number<B, et_off>&& a, const number<B, et_off>& b)
-{
- using default_ops::eval_divide;
- eval_divide(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
- operator / (number<B, et_off>&& a, const V& b)
-{
- using default_ops::eval_divide;
- eval_divide(a.backend(), number<B, et_off>::canonical_value(b));
- return static_cast<number<B, et_off>&&>(a);
-}
-//
-// modulus:
-//
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator % (number<B, et_off>&& a, const number<B, et_off>& b)
-{
- using default_ops::eval_modulus;
- eval_modulus(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator % (number<B, et_off>&& a, const V& b)
-{
- using default_ops::eval_modulus;
- eval_modulus(a.backend(), number<B, et_off>::canonical_value(b));
- return static_cast<number<B, et_off>&&>(a);
-}
-//
-// Bitwise or:
-//
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator | (number<B, et_off>&& a, const number<B, et_off>& b)
-{
- using default_ops::eval_bitwise_or;
- eval_bitwise_or(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator | (const number<B, et_off>& a, number<B, et_off>&& b)
-{
- using default_ops::eval_bitwise_or;
- eval_bitwise_or(b.backend(), a.backend());
- return static_cast<number<B, et_off>&&>(b);
-}
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator | (number<B, et_off>&& a, number<B, et_off>&& b)
-{
- using default_ops::eval_bitwise_or;
- eval_bitwise_or(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator | (number<B, et_off>&& a, const V& b)
-{
- using default_ops::eval_bitwise_or;
- eval_bitwise_or(a.backend(), number<B, et_off>::canonical_value(b));
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator | (const V& a, number<B, et_off>&& b)
-{
- using default_ops::eval_bitwise_or;
- eval_bitwise_or(b.backend(), number<B, et_off>::canonical_value(a));
- return static_cast<number<B, et_off>&&>(b);
-}
-//
-// Bitwise xor:
-//
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ^ (number<B, et_off>&& a, const number<B, et_off>& b)
-{
- using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ^ (const number<B, et_off>& a, number<B, et_off>&& b)
-{
- using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(b.backend(), a.backend());
- return static_cast<number<B, et_off>&&>(b);
-}
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ^ (number<B, et_off>&& a, number<B, et_off>&& b)
-{
- using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator ^ (number<B, et_off>&& a, const V& b)
-{
- using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(a.backend(), number<B, et_off>::canonical_value(b));
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator ^ (const V& a, number<B, et_off>&& b)
-{
- using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(b.backend(), number<B, et_off>::canonical_value(a));
- return static_cast<number<B, et_off>&&>(b);
-}
-//
-// Bitwise and:
-//
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator & (number<B, et_off>&& a, const number<B, et_off>& b)
-{
- using default_ops::eval_bitwise_and;
- eval_bitwise_and(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator & (const number<B, et_off>& a, number<B, et_off>&& b)
-{
- using default_ops::eval_bitwise_and;
- eval_bitwise_and(b.backend(), a.backend());
- return static_cast<number<B, et_off>&&>(b);
-}
-template <class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator & (number<B, et_off>&& a, number<B, et_off>&& b)
-{
- using default_ops::eval_bitwise_and;
- eval_bitwise_and(a.backend(), b.backend());
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B, class V>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator & (number<B, et_off>&& a, const V& b)
-{
- using default_ops::eval_bitwise_and;
- eval_bitwise_and(a.backend(), number<B, et_off>::canonical_value(b));
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class V, class B>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator & (const V& a, number<B, et_off>&& b)
-{
- using default_ops::eval_bitwise_and;
- eval_bitwise_and(b.backend(), number<B, et_off>::canonical_value(a));
- return static_cast<number<B, et_off>&&>(b);
-}
-//
-// shifts:
-//
-template <class B, class I>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator << (number<B, et_off>&& a, const I& b)
-{
- using default_ops::eval_left_shift;
- eval_left_shift(a.backend(), b);
- return static_cast<number<B, et_off>&&>(a);
-}
-template <class B, class I>
-BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
- operator >> (number<B, et_off>&& a, const I& b)
-{
- using default_ops::eval_right_shift;
- eval_right_shift(a.backend(), b);
- return static_cast<number<B, et_off>&&>(a);
-}
+ //
+ // If we have rvalue references go all over again with rvalue ref overloads and move semantics.
+ // Note that while it would be tempting to implement these so they return an rvalue reference
+ // (and indeed this would be optimally efficient), this is unsafe due to users propensity to
+ // write:
+ //
+ // const T& t = a * b;
+ //
+ // which would lead to a dangling reference if we didn't return by value. Of course move
+ // semantics help a great deal in return by value, so performance is still pretty good...
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(number<B, et_off>&& v)
+ {
+ static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
+ v.backend().negate();
+ return std::move(v);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator~(number<B, et_off>&& v)
+ {
+ eval_complement(v.backend(), v.backend());
+ return std::move(v);
+ }
+ //
+ // Addition:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(number<B, et_off>&& a, const number<B, et_off>& b)
+ {
+ using default_ops::eval_add;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_add(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(const number<B, et_off>& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_add;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_add(b.backend(), a.backend());
+ return std::move(b);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(number<B, et_off>&& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_add;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_add(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
+ operator+(number<B, et_off>&& a, const V& b)
+ {
+ using default_ops::eval_add;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_add(a.backend(), number<B, et_off>::canonical_value(b));
+ return std::move(a);
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator+(const V& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_add;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_add(b.backend(), number<B, et_off>::canonical_value(a));
+ return std::move(b);
+ }
+ //
+ // Subtraction:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(number<B, et_off>&& a, const number<B, et_off>& b)
+ {
+ using default_ops::eval_subtract;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_subtract(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_signed_number<B>::value, number<B, et_off> >::type operator-(const number<B, et_off>& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_subtract;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_subtract(b.backend(), a.backend());
+ b.backend().negate();
+ return std::move(b);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(number<B, et_off>&& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_subtract;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_subtract(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
+ operator-(number<B, et_off>&& a, const V& b)
+ {
+ using default_ops::eval_subtract;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_subtract(a.backend(), number<B, et_off>::canonical_value(b));
+ return std::move(a);
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(is_compatible_arithmetic_type<V, number<B, et_off> >::value && is_signed_number<B>::value) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator-(const V& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_subtract;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_subtract(b.backend(), number<B, et_off>::canonical_value(a));
+ b.backend().negate();
+ return std::move(b);
+ }
+ //
+ // Multiply:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(number<B, et_off>&& a, const number<B, et_off>& b)
+ {
+ using default_ops::eval_multiply;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_multiply(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(const number<B, et_off>& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_multiply;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_multiply(b.backend(), a.backend());
+ return std::move(b);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(number<B, et_off>&& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_multiply;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_multiply(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
+ operator*(number<B, et_off>&& a, const V& b)
+ {
+ using default_ops::eval_multiply;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_multiply(a.backend(), number<B, et_off>::canonical_value(b));
+ return std::move(a);
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator*(const V& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_multiply;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_multiply(b.backend(), number<B, et_off>::canonical_value(a));
+ return std::move(b);
+ }
+ //
+ // divide:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator/(number<B, et_off>&& a, const number<B, et_off>& b)
+ {
+ using default_ops::eval_divide;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_divide(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
+ operator/(number<B, et_off>&& a, const V& b)
+ {
+ using default_ops::eval_divide;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_divide(a.backend(), number<B, et_off>::canonical_value(b));
+ return std::move(a);
+ }
+ //
+ // modulus:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator%(number<B, et_off>&& a, const number<B, et_off>& b)
+ {
+ using default_ops::eval_modulus;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_modulus(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator%(number<B, et_off>&& a, const V& b)
+ {
+ using default_ops::eval_modulus;
+ detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
+ eval_modulus(a.backend(), number<B, et_off>::canonical_value(b));
+ return std::move(a);
+ }
+ //
+ // Bitwise or:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(number<B, et_off>&& a, const number<B, et_off>& b)
+ {
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(const number<B, et_off>& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(b.backend(), a.backend());
+ return std::move(b);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(number<B, et_off>&& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator|(number<B, et_off>&& a, const V& b)
+ {
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(a.backend(), number<B, et_off>::canonical_value(b));
+ return std::move(a);
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator|(const V& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_bitwise_or;
+ eval_bitwise_or(b.backend(), number<B, et_off>::canonical_value(a));
+ return std::move(b);
+ }
+ //
+ // Bitwise xor:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(number<B, et_off>&& a, const number<B, et_off>& b)
+ {
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(const number<B, et_off>& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(b.backend(), a.backend());
+ return std::move(b);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(number<B, et_off>&& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator^(number<B, et_off>&& a, const V& b)
+ {
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(a.backend(), number<B, et_off>::canonical_value(b));
+ return std::move(a);
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator^(const V& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_bitwise_xor;
+ eval_bitwise_xor(b.backend(), number<B, et_off>::canonical_value(a));
+ return std::move(b);
+ }
+ //
+ // Bitwise and:
+ //
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(number<B, et_off>&& a, const number<B, et_off>& b)
+ {
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(const number<B, et_off>& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(b.backend(), a.backend());
+ return std::move(b);
+ }
+ template <class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(number<B, et_off>&& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(a.backend(), b.backend());
+ return std::move(a);
+ }
+ template <class B, class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator&(number<B, et_off>&& a, const V& b)
+ {
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(a.backend(), number<B, et_off>::canonical_value(b));
+ return std::move(a);
+ }
+ template <class V, class B>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
+ operator&(const V& a, number<B, et_off>&& b)
+ {
+ using default_ops::eval_bitwise_and;
+ eval_bitwise_and(b.backend(), number<B, et_off>::canonical_value(a));
+ return std::move(b);
+ }
+ //
+ // shifts:
+ //
+ template <class B, class I>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator<<(number<B, et_off>&& a, const I& b)
+ {
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<I>::type;
-#endif
+ using default_ops::eval_left_shift;
+ eval_left_shift(a.backend(), static_cast<ui_type>(b));
+ return std::move(a);
+ }
+ template <class B, class I>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
+ operator>>(number<B, et_off>&& a, const I& b)
+ {
+ using ui_type = typename boost::multiprecision::detail::make_unsigned<I>::type;
-}} // namespaces
+ using default_ops::eval_right_shift;
+ eval_right_shift(a.backend(), static_cast<ui_type>(b));
+ return std::move(a);
+ }
+ }
+} // namespace boost::multiprecision
#ifdef BOOST_MSVC
#pragma warning(pop)
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/no_exceptions_support.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/no_exceptions_support.hpp
new file mode 100644
index 0000000000..c2133e2990
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/no_exceptions_support.hpp
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2004 - 2021 Pavel Vozenilek.
+// Copyright 2021 Matt Borland. 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_MP_DETAIL_NO_EXCEPTIONS_SUPPORT_HPP
+#define BOOST_MP_DETAIL_NO_EXCEPTIONS_SUPPORT_HPP
+
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+#ifdef BOOST_MP_STANDALONE
+
+#ifndef BOOST_NO_EXCEPTIONS
+# define BOOST_MP_TRY { try
+# define BOOST_MP_CATCH(x) catch(x)
+# define BOOST_MP_RETHROW throw;
+# define BOOST_MP_CATCH_END }
+# define BOOST_MP_THROW_EXCEPTION(x) throw (x);
+#else
+# if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900
+# define BOOST_MP_TRY { if (true)
+# define BOOST_MP_CATCH(x) else if (false)
+# else
+ // warning C4127: conditional expression is constant
+# define BOOST_MP_TRY { \
+ __pragma(warning(push)) \
+ __pragma(warning(disable: 4127)) \
+ if (true) \
+ __pragma(warning(pop))
+# define BOOST_MP_CATCH(x) else \
+ __pragma(warning(push)) \
+ __pragma(warning(disable: 4127)) \
+ if (false) \
+ __pragma(warning(pop))
+# endif
+# define BOOST_MP_RETHROW
+# define BOOST_MP_CATCH_END }
+# define BOOST_MP_THROW_EXCEPTION(x) {static_cast<void>(x);}
+#endif
+
+#else // Not standalone mode
+
+# include <boost/core/no_exceptions_support.hpp>
+# include <boost/throw_exception.hpp>
+
+# define BOOST_MP_TRY BOOST_TRY
+# define BOOST_MP_CATCH(x) BOOST_CATCH(x)
+# define BOOST_MP_RETHROW BOOST_RETHROW
+# define BOOST_MP_CATCH_END BOOST_CATCH_END
+# define BOOST_MP_THROW_EXCEPTION(x) BOOST_THROW_EXCEPTION(x)
+
+#endif // BOOST_MP_STANDALONE
+
+#endif // BOOST_MP_DETAIL_NO_EXCEPTIONS_SUPPORT_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_base.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_base.hpp
index 24e0299b15..ed395b8f00 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_base.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_base.hpp
@@ -3,126 +3,223 @@
// 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_MATH_BIG_NUM_BASE_HPP
-#define BOOST_MATH_BIG_NUM_BASE_HPP
+#ifndef BOOST_MP_NUMBER_BASE_HPP
+#define BOOST_MP_NUMBER_BASE_HPP
+#include <climits>
+#include <ios>
+#include <string>
#include <limits>
-#include <boost/utility/enable_if.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/is_constructible.hpp>
-#include <boost/type_traits/decay.hpp>
+#include <type_traits>
+#include <stdexcept>
+#include <tuple>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/traits/transcendental_reduction_type.hpp>
+#include <boost/multiprecision/traits/std_integer_traits.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+
#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable:4307)
+#pragma warning(push)
+#pragma warning(disable : 4307)
+#pragma warning(pop)
#endif
+
+#ifndef BOOST_MP_STANDALONE
#include <boost/lexical_cast.hpp>
-#ifdef BOOST_MSVC
-# pragma warning(pop)
+#include <boost/core/nvp.hpp>
#endif
+#ifdef BOOST_MP_MATH_AVAILABLE
+#include <boost/math/tools/complex.hpp>
+#endif
+
+// We now require C++11.
+#include <boost/multiprecision/detail/check_cpp11_config.hpp>
+
#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)
-# define BOOST_MP_NOEXCEPT_IF(x)
+//
+// Thread local storage:
+// Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/
+//
+#if defined(BOOST_NO_CXX11_THREAD_LOCAL)
+#define BOOST_MP_THREAD_LOCAL
+#elif !(defined(__MINGW32__) && (defined(__GNUC__) && (__GNUC__ < 9)) && !defined(__clang__))
+#define BOOST_MP_THREAD_LOCAL thread_local
+#define BOOST_MP_USING_THREAD_LOCAL
#else
-# define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
+#pragma GCC warning "thread_local on mingw is broken, please use MSys mingw gcc-9 or later, see https://sourceforge.net/p/mingw-w64/bugs/527/"
+#define BOOST_MP_THREAD_LOCAL
#endif
-#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140)
-#define BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+#ifdef __has_include
+# if __has_include(<version>)
+# include <version>
+# ifdef __cpp_lib_is_constant_evaluated
+# include <type_traits>
+# define BOOST_MP_HAS_IS_CONSTANT_EVALUATED
+# endif
+# endif
#endif
+#ifdef __has_builtin
+#if __has_builtin(__builtin_is_constant_evaluated) && !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
+#define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
+#endif
+#endif
//
-// Thread local storage:
-// Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/
+// MSVC also supports __builtin_is_constant_evaluated if it's recent enough:
+//
+#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 192528326)
+# define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
+#endif
//
-#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && !defined(__MINGW32__)
-# define BOOST_MP_THREAD_LOCAL thread_local
+// As does GCC-9:
+//
+#if defined(BOOST_GCC) && !defined(BOOST_NO_CXX14_CONSTEXPR) && (__GNUC__ >= 9) && !defined(BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
+# define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
+#endif
+
+#if defined(BOOST_MP_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
+# define BOOST_MP_IS_CONST_EVALUATED(x) std::is_constant_evaluated()
+#elif defined(BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
+# define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_is_constant_evaluated()
+#elif !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_GCC) && (__GNUC__ >= 6)
+# define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_constant_p(x)
#else
-# define BOOST_MP_THREAD_LOCAL
+# define BOOST_MP_NO_CONSTEXPR_DETECTION
+#endif
+
+#define BOOST_MP_CXX14_CONSTEXPR BOOST_CXX14_CONSTEXPR
+//
+// Early compiler versions trip over the constexpr code:
+//
+#if defined(__clang__) && (__clang_major__ < 5)
+#undef BOOST_MP_CXX14_CONSTEXPR
+#define BOOST_MP_CXX14_CONSTEXPR
+#endif
+#if defined(__apple_build_version__) && (__clang_major__ < 9)
+#undef BOOST_MP_CXX14_CONSTEXPR
+#define BOOST_MP_CXX14_CONSTEXPR
+#endif
+#if defined(BOOST_GCC) && (__GNUC__ < 6)
+#undef BOOST_MP_CXX14_CONSTEXPR
+#define BOOST_MP_CXX14_CONSTEXPR
+#endif
+#if defined(BOOST_INTEL)
+#undef BOOST_MP_CXX14_CONSTEXPR
+#define BOOST_MP_CXX14_CONSTEXPR
+#define BOOST_MP_NO_CONSTEXPR_DETECTION
+#endif
+
+#ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
+# define BOOST_CXX14_CONSTEXPR_IF_DETECTION
+#else
+# define BOOST_CXX14_CONSTEXPR_IF_DETECTION constexpr
#endif
#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable:6326)
+#pragma warning(push)
+#pragma warning(disable : 6326)
#endif
-namespace boost{
- namespace multiprecision{
+namespace boost {
+namespace multiprecision {
enum expression_template_option
{
- et_off = 0,
- et_on = 1
+ et_off = 0,
+ et_on = 1
+};
+
+enum struct variable_precision_options : signed char
+{
+ assume_uniform_precision = -1,
+ preserve_target_precision = 0,
+ preserve_source_precision = 1,
+ preserve_component_precision = 2,
+ preserve_related_precision = 3,
+ preserve_all_precision = 4,
};
+inline constexpr bool operator==(variable_precision_options a, variable_precision_options b)
+{
+ return static_cast<unsigned>(a) == static_cast<unsigned>(b);
+}
+
template <class Backend>
struct expression_template_default
{
- static const expression_template_option value = et_on;
+ static constexpr expression_template_option value = et_on;
};
template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
class number;
template <class T>
-struct is_number : public mpl::false_ {};
+struct is_number : public std::integral_constant<bool, false>
+{};
template <class Backend, expression_template_option ExpressionTemplates>
-struct is_number<number<Backend, ExpressionTemplates> > : public mpl::true_ {};
+struct is_number<number<Backend, ExpressionTemplates> > : public std::integral_constant<bool, true>
+{};
template <class T>
-struct is_et_number : public mpl::false_ {};
+struct is_et_number : public std::integral_constant<bool, false>
+{};
template <class Backend>
-struct is_et_number<number<Backend, et_on> > : public mpl::true_ {};
+struct is_et_number<number<Backend, et_on> > : public std::integral_constant<bool, true>
+{};
template <class T>
-struct is_no_et_number : public mpl::false_ {};
+struct is_no_et_number : public std::integral_constant<bool, false>
+{};
template <class Backend>
-struct is_no_et_number<number<Backend, et_off> > : public mpl::true_ {};
+struct is_no_et_number<number<Backend, et_off> > : public std::integral_constant<bool, true>
+{};
-namespace detail{
+namespace detail {
// Forward-declare an expression wrapper
-template<class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void>
+template <class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void>
struct expression;
} // namespace detail
template <class T>
-struct is_number_expression : public mpl::false_ {};
+struct is_number_expression : public std::integral_constant<bool, false>
+{};
-template<class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::true_ {};
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public std::integral_constant<bool, true>
+{};
template <class T, class Num>
struct is_compatible_arithmetic_type
- : public mpl::bool_<
- is_convertible<T, Num>::value
- && !is_same<T, Num>::value
- && !is_number_expression<T>::value>
+ : public std::integral_constant<bool,
+ std::is_convertible<T, Num>::value && !std::is_same<T, Num>::value && !is_number_expression<T>::value>
{};
-namespace detail{
+namespace detail {
//
-// Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers:
+// Workaround for missing abs(long long) and abs(__int128) on some compilers:
//
template <class T>
-BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
+constexpr typename std::enable_if<(boost::multiprecision::detail::is_signed<T>::value || std::is_floating_point<T>::value), T>::type abs(T t) 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.
+ // that val is the most negative value permitted in long long.
// See https://svn.boost.org/trac/boost/ticket/9740.
return t < 0 ? T(1u) + T(-(t + 1)) : t;
}
template <class T>
-BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
+constexpr typename std::enable_if<boost::multiprecision::detail::is_unsigned<T>::value, T>::type abs(T t) noexcept
{
return t;
}
@@ -130,167 +227,198 @@ BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type abs(T t)
#define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
template <class T>
-BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), typename make_unsigned<T>::type>::type unsigned_abs(T t) BOOST_NOEXCEPT
+constexpr typename std::enable_if<(boost::multiprecision::detail::is_signed<T>::value || std::is_floating_point<T>::value), typename boost::multiprecision::detail::make_unsigned<T>::type>::type unsigned_abs(T t) 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.
+ // that val is the most negative value permitted in long long.
// See https://svn.boost.org/trac/boost/ticket/9740.
- return t < 0 ? static_cast<typename make_unsigned<T>::type>(1u) + static_cast<typename make_unsigned<T>::type>(-(t + 1)) : static_cast<typename make_unsigned<T>::type>(t);
+ return t < 0 ? static_cast<typename boost::multiprecision::detail::make_unsigned<T>::type>(1u) + static_cast<typename boost::multiprecision::detail::make_unsigned<T>::type>(-(t + 1)) : static_cast<typename boost::multiprecision::detail::make_unsigned<T>::type>(t);
}
template <class T>
-BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT
+constexpr typename std::enable_if<boost::multiprecision::detail::is_unsigned<T>::value, T>::type unsigned_abs(T t) noexcept
{
return t;
}
-//
-// Move support:
-//
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-# define BOOST_MP_MOVE(x) std::move(x)
-#else
-# define BOOST_MP_MOVE(x) x
-#endif
-
template <class T>
struct bits_of
{
- BOOST_STATIC_ASSERT(is_integral<T>::value || is_enum<T>::value || std::numeric_limits<T>::is_specialized);
- static const unsigned value =
- std::numeric_limits<T>::is_specialized ?
- std::numeric_limits<T>::digits
- : sizeof(T) * CHAR_BIT - (is_signed<T>::value ? 1 : 0);
+ static_assert(boost::multiprecision::detail::is_integral<T>::value || std::is_enum<T>::value || std::numeric_limits<T>::is_specialized, "Failed integer size check");
+ static constexpr unsigned value =
+ std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::digits
+ : sizeof(T) * CHAR_BIT - (boost::multiprecision::detail::is_signed<T>::value ? 1 : 0);
};
#if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__)
-template<> struct bits_of<__float128> { static const unsigned value = 113; };
+#define BOOST_MP_BITS_OF_FLOAT128_DEFINED
+template <>
+struct bits_of<float128_type>
+{
+ static constexpr unsigned value = 113;
+};
#endif
template <int b>
struct has_enough_bits
{
template <class T>
- struct type : public mpl::bool_<bits_of<T>::value>= b>{};
+ struct type : public std::integral_constant<bool, bits_of<T>::value >= b>
+ {};
+};
+
+template <class Tuple, int i, int digits, bool = (i >= std::tuple_size<Tuple>::value)>
+struct find_index_of_large_enough_type
+{
+ static constexpr int value = bits_of<typename std::tuple_element<static_cast<std::size_t>(i), Tuple>::type>::value >= digits ? i : find_index_of_large_enough_type<Tuple, i + 1, digits>::value;
+};
+template <class Tuple, int i, int digits>
+struct find_index_of_large_enough_type<Tuple, i, digits, true>
+{
+ static constexpr int value = INT_MAX;
+};
+
+template <int index, class Tuple, class Fallback, bool = (std::tuple_size<Tuple>::value <= index)>
+struct dereference_tuple
+{
+ using type = typename std::tuple_element<static_cast<std::size_t>(index), Tuple>::type;
+};
+template <int index, class Tuple, class Fallback>
+struct dereference_tuple<index, Tuple, Fallback, true>
+{
+ using type = Fallback;
};
template <class Val, class Backend, class Tag>
struct canonical_imp
{
- typedef typename remove_cv<typename decay<const Val>::type>::type type;
+ using type = typename std::remove_cv<typename std::decay<const Val>::type>::type;
};
template <class B, class Backend, class Tag>
struct canonical_imp<number<B, et_on>, Backend, Tag>
{
- typedef B type;
+ using type = B;
};
template <class B, class Backend, class Tag>
struct canonical_imp<number<B, et_off>, Backend, Tag>
{
- typedef B type;
+ using type = B;
};
#ifdef __SUNPRO_CC
template <class B, class Backend>
-struct canonical_imp<number<B, et_on>, Backend, mpl::int_<3> >
+struct canonical_imp<number<B, et_on>, Backend, std::integral_constant<int, 3> >
{
- typedef B type;
+ using type = B;
};
template <class B, class Backend>
-struct canonical_imp<number<B, et_off>, Backend, mpl::int_<3> >
+struct canonical_imp<number<B, et_off>, Backend, std::integral_constant<int, 3> >
{
- typedef B type;
+ using type = B;
};
#endif
template <class Val, class Backend>
-struct canonical_imp<Val, Backend, mpl::int_<0> >
+struct canonical_imp<Val, Backend, std::integral_constant<int, 0> >
{
- typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
- typedef typename mpl::find_if<
- typename Backend::signed_types,
- pred_type
- >::type iter_type;
- typedef typename mpl::end<typename Backend::signed_types>::type end_type;
- typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
+ static constexpr int index = find_index_of_large_enough_type<typename Backend::signed_types, 0, bits_of<Val>::value>::value;
+ using type = typename dereference_tuple<index, typename Backend::signed_types, Val>::type;
};
template <class Val, class Backend>
-struct canonical_imp<Val, Backend, mpl::int_<1> >
+struct canonical_imp<Val, Backend, std::integral_constant<int, 1> >
{
- typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
- typedef typename mpl::find_if<
- typename Backend::unsigned_types,
- pred_type
- >::type iter_type;
- typedef typename mpl::end<typename Backend::unsigned_types>::type end_type;
- typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
+ static constexpr int index = find_index_of_large_enough_type<typename Backend::unsigned_types, 0, bits_of<Val>::value>::value;
+ using type = typename dereference_tuple<index, typename Backend::unsigned_types, Val>::type;
};
template <class Val, class Backend>
-struct canonical_imp<Val, Backend, mpl::int_<2> >
+struct canonical_imp<Val, Backend, std::integral_constant<int, 2> >
{
- typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
- typedef typename mpl::find_if<
- typename Backend::float_types,
- pred_type
- >::type iter_type;
- typedef typename mpl::end<typename Backend::float_types>::type end_type;
- typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
+ static constexpr int index = find_index_of_large_enough_type<typename Backend::float_types, 0, bits_of<Val>::value>::value;
+ using type = typename dereference_tuple<index, typename Backend::float_types, Val>::type;
};
template <class Val, class Backend>
-struct canonical_imp<Val, Backend, mpl::int_<3> >
+struct canonical_imp<Val, Backend, std::integral_constant<int, 3> >
{
- typedef const char* type;
+ using type = const char*;
+};
+template <class Val, class Backend>
+struct canonical_imp<Val, Backend, std::integral_constant<int, 4> >
+{
+ using underlying = typename std::underlying_type<Val>::type;
+ using tag = typename std::conditional<boost::multiprecision::detail::is_signed<Val>::value, std::integral_constant<int, 0>, std::integral_constant<int, 1>>::type;
+ using type = typename canonical_imp<underlying, Backend, tag>::type;
};
template <class Val, class Backend>
struct canonical
{
- typedef typename mpl::if_<
- is_signed<Val>,
- mpl::int_<0>,
- typename mpl::if_<
- is_unsigned<Val>,
- mpl::int_<1>,
- typename mpl::if_<
- is_floating_point<Val>,
- mpl::int_<2>,
- typename mpl::if_<
- mpl::or_<
- is_convertible<Val, const char*>,
- is_same<Val, std::string>
- >,
- mpl::int_<3>,
- mpl::int_<4>
- >::type
- >::type
- >::type
- >::type tag_type;
-
- typedef typename canonical_imp<Val, Backend, tag_type>::type type;
+ using tag_type = typename std::conditional<
+ boost::multiprecision::detail::is_signed<Val>::value && boost::multiprecision::detail::is_integral<Val>::value,
+ std::integral_constant<int, 0>,
+ typename std::conditional<
+ boost::multiprecision::detail::is_unsigned<Val>::value,
+ std::integral_constant<int, 1>,
+ typename std::conditional<
+ std::is_floating_point<Val>::value,
+ std::integral_constant<int, 2>,
+ typename std::conditional<
+ (std::is_convertible<Val, const char*>::value || std::is_same<Val, std::string>::value),
+ std::integral_constant<int, 3>,
+ typename std::conditional<
+ std::is_enum<Val>::value,
+ std::integral_constant<int, 4>,
+ std::integral_constant<int, 5> >::type>::type>::type>::type>::type;
+
+ using type = typename canonical_imp<Val, Backend, tag_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{};
+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 <class T>
struct backend_type;
@@ -298,69 +426,63 @@ struct backend_type;
template <class T, expression_template_option ExpressionTemplates>
struct backend_type<number<T, ExpressionTemplates> >
{
- typedef T type;
+ using type = T;
};
template <class tag, class A1, class A2, class A3, class A4>
struct backend_type<expression<tag, A1, A2, A3, A4> >
{
- typedef typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type type;
+ using type = typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type;
};
-
template <class T1, class T2>
struct combine_expression
{
-#ifdef BOOST_NO_CXX11_DECLTYPE
- typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type;
-#else
- typedef decltype(T1() + T2()) type;
-#endif
+ using type = decltype(T1() + T2());
};
template <class T1, expression_template_option ExpressionTemplates, class T2>
struct combine_expression<number<T1, ExpressionTemplates>, T2>
{
- typedef number<T1, ExpressionTemplates> type;
+ using type = number<T1, ExpressionTemplates>;
};
template <class T1, class T2, expression_template_option ExpressionTemplates>
struct combine_expression<T1, number<T2, ExpressionTemplates> >
{
- typedef number<T2, ExpressionTemplates> type;
+ using type = number<T2, ExpressionTemplates>;
};
template <class T, expression_template_option ExpressionTemplates>
struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
{
- typedef number<T, ExpressionTemplates> type;
+ using type = number<T, ExpressionTemplates>;
};
template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
{
- typedef typename mpl::if_c<
- is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
- number<T1, ExpressionTemplates1>,
- number<T2, ExpressionTemplates2>
- >::type type;
+ using type = typename std::conditional<
+ std::is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
+ number<T1, ExpressionTemplates1>,
+ number<T2, ExpressionTemplates2> >::type;
};
template <class T>
struct arg_type
{
- typedef expression<terminal, T> type;
+ using type = expression<terminal, T>;
};
template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
{
- typedef expression<Tag, Arg1, Arg2, Arg3, Arg4> type;
+ using type = expression<Tag, Arg1, Arg2, Arg3, Arg4>;
};
struct unmentionable
{
- unmentionable* proc(){ return 0; }
+ unmentionable* proc() { return nullptr; }
};
typedef unmentionable* (unmentionable::*unmentionable_type)();
@@ -368,554 +490,962 @@ typedef unmentionable* (unmentionable::*unmentionable_type)();
template <class T, bool b>
struct expression_storage_base
{
- typedef const T& type;
+ using type = const T&;
};
template <class T>
struct expression_storage_base<T, true>
{
- typedef T type;
+ using type = T;
};
template <class T>
-struct expression_storage : public expression_storage_base<T, boost::is_arithmetic<T>::value> {};
+struct expression_storage : public expression_storage_base<T, boost::multiprecision::detail::is_arithmetic<T>::value>
+{};
template <class T>
struct expression_storage<T*>
{
- typedef T* type;
+ using type = T*;
};
template <class T>
struct expression_storage<const T*>
{
- typedef const T* type;
+ using type = const T*;
};
template <class tag, class A1, class A2, class A3, class A4>
struct expression_storage<expression<tag, A1, A2, A3, A4> >
{
- typedef expression<tag, A1, A2, A3, A4> type;
+ using type = expression<tag, A1, A2, A3, A4>;
};
-template<class tag, class Arg1>
+template <class tag, class Arg1>
struct expression<tag, Arg1, void, void, void>
{
- typedef mpl::int_<1> arity;
- typedef typename arg_type<Arg1>::type left_type;
- typedef typename left_type::result_type left_result_type;
- typedef typename left_type::result_type result_type;
- typedef tag tag_type;
+ using arity = std::integral_constant<int, 1> ;
+ using left_type = typename arg_type<Arg1>::type ;
+ using left_result_type = typename left_type::result_type;
+ using result_type = typename left_type::result_type;
+ using tag_type = tag ;
- explicit expression(const Arg1& a) : arg(a) {}
- expression(const expression& e) : arg(e.arg) {}
+ explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
+ BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
- left_type left()const { return left_type(arg); }
-
- const Arg1& left_ref()const BOOST_NOEXCEPT { return arg; }
-
- 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:
+ // If we have static_assert we can give a more useful error message
+ // than if we simply have no operator defined at all:
//
- template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
- explicit operator T ()const
+ template <class Other>
+ BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
{
- result_type r(*this);
- return static_cast<bool>(r);
+ // 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;
}
- template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
- explicit operator T ()const
+ BOOST_MP_CXX14_CONSTEXPR expression& operator++()
{
- return static_cast<T>(static_cast<result_type>(*this));
+ // 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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;
}
-# else
+ template <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+
+ BOOST_MP_CXX14_CONSTEXPR left_type left() const
+ {
+ return left_type(arg);
+ }
+
+ BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg; }
+
+ static constexpr unsigned depth = left_type::depth + 1;
template <class T
#ifndef __SUNPRO_CC
-, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+ ,
+ typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
#endif
->
- explicit operator T()const
+ >
+ explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
{
return static_cast<T>(static_cast<result_type>(*this));
}
- BOOST_MP_FORCEINLINE explicit operator bool()const
+ BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
{
result_type r(*this);
return static_cast<bool>(r);
}
-#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
- BOOST_MP_FORCEINLINE explicit operator void()const {}
-#endif
-# endif
-#else
- operator unmentionable_type()const
- {
- result_type r(*this);
- return r ? &unmentionable::proc : 0;
- }
-#endif
template <class T>
- T convert_to()
+ BOOST_MP_CXX14_CONSTEXPR T convert_to()
{
result_type r(*this);
return r.template convert_to<T>();
}
-private:
+ private:
typename expression_storage<Arg1>::type arg;
- expression& operator=(const expression&);
+ expression& operator=(const expression&);
};
-template<class Arg1>
+template <class Arg1>
struct expression<terminal, Arg1, void, void, void>
{
- typedef mpl::int_<0> arity;
- typedef Arg1 result_type;
- typedef terminal tag_type;
-
- explicit expression(const Arg1& a) : arg(a) {}
- expression(const expression& e) : arg(e.arg) {}
-
- const Arg1& value()const BOOST_NOEXCEPT { return arg; }
+ using arity = std::integral_constant<int, 0>;
+ using result_type = Arg1 ;
+ using tag_type = terminal ;
- static const unsigned depth = 0;
+ explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
+ BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
-#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:
+ // If we have static_assert we can give a more useful error message
+ // than if we simply have no operator defined at all:
//
- template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
- explicit operator T ()const
+ template <class Other>
+ BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
{
- result_type r(*this);
- return static_cast<bool>(r);
-}
- template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
- explicit operator T ()const
+ // 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR expression& operator++()
{
- return static_cast<T>(static_cast<result_type>(*this));
+ // 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
}
-# else
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+
+ BOOST_MP_CXX14_CONSTEXPR const Arg1& value() const noexcept
+ {
+ return arg;
+ }
+
+ static constexpr unsigned depth = 0;
+
template <class T
#ifndef __SUNPRO_CC
-, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+ ,
+ typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
#endif
->
- explicit operator T()const
+ >
+ explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
{
return static_cast<T>(static_cast<result_type>(*this));
}
- BOOST_MP_FORCEINLINE explicit operator bool()const
+ BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
{
result_type r(*this);
return static_cast<bool>(r);
}
-#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
- BOOST_MP_FORCEINLINE explicit operator void()const {}
-#endif
-# endif
-#else
- operator unmentionable_type()const
- {
- return arg ? &unmentionable::proc : 0;
- }
-#endif
template <class T>
- T convert_to()
+ BOOST_MP_CXX14_CONSTEXPR T convert_to()
{
result_type r(*this);
return r.template convert_to<T>();
}
-private:
+ private:
typename expression_storage<Arg1>::type arg;
- expression& operator=(const expression&);
+ expression& operator=(const expression&);
};
template <class tag, class Arg1, class Arg2>
struct expression<tag, Arg1, Arg2, void, void>
{
- typedef mpl::int_<2> arity;
- typedef typename arg_type<Arg1>::type left_type;
- typedef typename arg_type<Arg2>::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<left_result_type, right_result_type>::type result_type;
- typedef tag tag_type;
-
- expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
- expression(const expression& e) : arg1(e.arg1), arg2(e.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 <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
- explicit operator T ()const
+ using arity = std::integral_constant<int, 2> ;
+ using left_type = typename arg_type<Arg1>::type ;
+ using right_type = typename arg_type<Arg2>::type ;
+ using left_result_type = typename left_type::result_type ;
+ using right_result_type = typename right_type::result_type ;
+ using result_type = typename combine_expression<left_result_type, right_result_type>::type;
+ using tag_type = tag ;
+
+ BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
+ BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2) {}
+
+ //
+ // If we have static_assert we can give a more useful error message
+ // than if we simply have no operator defined at all:
+ //
+ template <class Other>
+ BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
{
- result_type r(*this);
- return static_cast<bool>(r);
-}
- template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
- explicit operator T ()const
+ // 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR expression& operator++()
{
- return static_cast<T>(static_cast<result_type>(*this));
+ // 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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;
}
-# else
+ template <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+
+ BOOST_MP_CXX14_CONSTEXPR left_type left() const
+ {
+ return left_type(arg1);
+ }
+ BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg2); }
+ BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg1; }
+ BOOST_MP_CXX14_CONSTEXPR const Arg2& right_ref() const noexcept { return arg2; }
+
template <class T
#ifndef __SUNPRO_CC
-, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+ ,
+ typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
#endif
->
- explicit operator T()const
+ >
+ explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
{
return static_cast<T>(static_cast<result_type>(*this));
}
- BOOST_MP_FORCEINLINE explicit operator bool()const
+ BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
{
result_type r(*this);
return static_cast<bool>(r);
}
-#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
- BOOST_MP_FORCEINLINE explicit operator void()const {}
-#endif
-# endif
-#else
- operator unmentionable_type()const
- {
- result_type r(*this);
- return r ? &unmentionable::proc : 0;
- }
-#endif
template <class T>
- T convert_to()
+ BOOST_MP_CXX14_CONSTEXPR T convert_to()
{
result_type r(*this);
return r.template convert_to<T>();
}
- 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:
+ static const constexpr unsigned left_depth = left_type::depth + 1;
+ static const constexpr unsigned right_depth = right_type::depth + 1;
+ static const constexpr unsigned depth = left_depth > right_depth ? left_depth : right_depth;
+
+ private:
typename expression_storage<Arg1>::type arg1;
typename expression_storage<Arg2>::type arg2;
- expression& operator=(const expression&);
+ expression& operator=(const expression&);
};
template <class tag, class Arg1, class Arg2, class Arg3>
struct expression<tag, Arg1, Arg2, Arg3, void>
{
- typedef mpl::int_<3> arity;
- typedef typename arg_type<Arg1>::type left_type;
- typedef typename arg_type<Arg2>::type middle_type;
- typedef typename arg_type<Arg3>::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<right_result_type, middle_result_type>::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 expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.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 <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
- explicit operator T ()const
+ using arity = std::integral_constant<int, 3> ;
+ using left_type = typename arg_type<Arg1>::type ;
+ using middle_type = typename arg_type<Arg2>::type ;
+ using right_type = typename arg_type<Arg3>::type ;
+ using left_result_type = typename left_type::result_type ;
+ using middle_result_type = typename middle_type::result_type;
+ using right_result_type = typename right_type::result_type ;
+ using result_type = typename combine_expression<
+ left_result_type,
+ typename combine_expression<right_result_type, middle_result_type>::type>::type;
+ using tag_type = tag ;
+
+ BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
+ BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3) {}
+
+ //
+ // If we have static_assert we can give a more useful error message
+ // than if we simply have no operator defined at all:
+ //
+ template <class Other>
+ BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
{
- result_type r(*this);
- return static_cast<bool>(r);
-}
- template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
- explicit operator T ()const
+ // 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR expression& operator++()
{
- return static_cast<T>(static_cast<result_type>(*this));
+ // 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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;
}
-# else
+ template <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+
+ BOOST_MP_CXX14_CONSTEXPR left_type left() const
+ {
+ return left_type(arg1);
+ }
+ BOOST_MP_CXX14_CONSTEXPR middle_type middle() const { return middle_type(arg2); }
+ BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg3); }
+ BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg1; }
+ BOOST_MP_CXX14_CONSTEXPR const Arg2& middle_ref() const noexcept { return arg2; }
+ BOOST_MP_CXX14_CONSTEXPR const Arg3& right_ref() const noexcept { return arg3; }
+
template <class T
#ifndef __SUNPRO_CC
-, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+ ,
+ typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
#endif
->
- explicit operator T()const
+ >
+ explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
{
return static_cast<T>(static_cast<result_type>(*this));
}
- BOOST_MP_FORCEINLINE explicit operator bool()const
+ BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
{
result_type r(*this);
return static_cast<bool>(r);
}
-#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
- BOOST_MP_FORCEINLINE explicit operator void()const {}
-#endif
-# endif
-#else
- operator unmentionable_type()const
- {
- result_type r(*this);
- return r ? &unmentionable::proc : 0;
- }
-#endif
template <class T>
- T convert_to()
+ BOOST_MP_CXX14_CONSTEXPR T convert_to()
{
result_type r(*this);
return r.template convert_to<T>();
}
- 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:
+ static constexpr unsigned left_depth = left_type::depth + 1;
+ static constexpr unsigned middle_depth = middle_type::depth + 1;
+ static constexpr unsigned right_depth = right_type::depth + 1;
+ static constexpr 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<Arg1>::type arg1;
typename expression_storage<Arg2>::type arg2;
typename expression_storage<Arg3>::type arg3;
- expression& operator=(const expression&);
+ expression& operator=(const expression&);
};
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
struct expression
{
- typedef mpl::int_<4> arity;
- typedef typename arg_type<Arg1>::type left_type;
- typedef typename arg_type<Arg2>::type left_middle_type;
- typedef typename arg_type<Arg3>::type right_middle_type;
- typedef typename arg_type<Arg4>::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<right_middle_result_type, right_result_type>::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 expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3), arg4(e.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 <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
- explicit operator T ()const
+ using arity = std::integral_constant<int, 4> ;
+ using left_type = typename arg_type<Arg1>::type ;
+ using left_middle_type = typename arg_type<Arg2>::type ;
+ using right_middle_type = typename arg_type<Arg3>::type ;
+ using right_type = typename arg_type<Arg4>::type ;
+ using left_result_type = typename left_type::result_type ;
+ using left_middle_result_type = typename left_middle_type::result_type ;
+ using right_middle_result_type = typename right_middle_type::result_type;
+ using right_result_type = typename right_type::result_type ;
+ using result_type = typename combine_expression<
+ left_result_type,
+ typename combine_expression<
+ left_middle_result_type,
+ typename combine_expression<right_middle_result_type, right_result_type>::type>::type>::type;
+ using tag_type = tag ;
+
+ BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3, const Arg4& a4) : arg1(a1), arg2(a2), arg3(a3), arg4(a4) {}
+ BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3), arg4(e.arg4) {}
+
+ //
+ // If we have static_assert we can give a more useful error message
+ // than if we simply have no operator defined at all:
+ //
+ template <class Other>
+ BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
{
- result_type r(*this);
- return static_cast<bool>(r);
-}
- template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
- explicit operator T ()const
+ // 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR expression& operator++()
{
- return static_cast<T>(static_cast<result_type>(*this));
+ // 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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;
}
-# else
+ template <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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 <class Other>
+ BOOST_MP_CXX14_CONSTEXPR 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;
+ }
+
+ BOOST_MP_CXX14_CONSTEXPR left_type left() const
+ {
+ return left_type(arg1);
+ }
+ BOOST_MP_CXX14_CONSTEXPR left_middle_type left_middle() const { return left_middle_type(arg2); }
+ BOOST_MP_CXX14_CONSTEXPR right_middle_type right_middle() const { return right_middle_type(arg3); }
+ BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg4); }
+ BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg1; }
+ BOOST_MP_CXX14_CONSTEXPR const Arg2& left_middle_ref() const noexcept { return arg2; }
+ BOOST_MP_CXX14_CONSTEXPR const Arg3& right_middle_ref() const noexcept { return arg3; }
+ BOOST_MP_CXX14_CONSTEXPR const Arg4& right_ref() const noexcept { return arg4; }
+
template <class T
#ifndef __SUNPRO_CC
-, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+ ,
+ typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
#endif
->
- explicit operator T()const
+ >
+ explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
{
return static_cast<T>(static_cast<result_type>(*this));
}
- BOOST_MP_FORCEINLINE explicit operator bool()const
+ BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
{
result_type r(*this);
return static_cast<bool>(r);
}
-#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
- BOOST_MP_FORCEINLINE explicit operator void()const {}
-#endif
-# endif
-#else
- operator unmentionable_type()const
- {
- result_type r(*this);
- return r ? &unmentionable::proc : 0;
- }
-#endif
template <class T>
- T convert_to()
+ BOOST_MP_CXX14_CONSTEXPR T convert_to()
{
result_type r(*this);
return r.template convert_to<T>();
}
- 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 constexpr unsigned left_depth = left_type::depth + 1;
+ static constexpr unsigned left_middle_depth = left_middle_type::depth + 1;
+ static constexpr unsigned right_middle_depth = right_middle_type::depth + 1;
+ static constexpr 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 constexpr unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth;
+ static constexpr 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:
+ static constexpr unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
+
+ private:
typename expression_storage<Arg1>::type arg1;
typename expression_storage<Arg2>::type arg2;
typename expression_storage<Arg3>::type arg3;
typename expression_storage<Arg4>::type arg4;
- expression& operator=(const expression&);
+ expression& operator=(const expression&);
};
template <class T>
struct digits2
{
- BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
- BOOST_STATIC_ASSERT((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10));
+ static_assert(std::numeric_limits<T>::is_specialized, "numeric_limits must be specialized here");
+ static_assert((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10), "Failed radix check");
// 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<T>::digits + 1));
- static const long m_value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
- static inline BOOST_CONSTEXPR long value()BOOST_NOEXCEPT { return m_value; }
+ static_assert(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1), "Too many digits to cope with here");
+ static constexpr long m_value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
+ static inline constexpr long value() 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 <class S>
-void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
+void format_float_string(S& str, std::intmax_t my_exp, std::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
{
- typedef typename S::size_type size_type;
+ using size_type = typename S::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 showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
bool neg = str.size() && (str[0] == '-');
- if(neg)
+ if (neg)
str.erase(0, 1);
- if(digits == 0)
+ if (digits == 0 && !fixed)
{
- digits = (std::max)(str.size(), size_type(16));
+ digits = static_cast<std::intmax_t>((std::max)(str.size(), size_type(16)));
}
- if(iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
+ 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)
+ if (scientific || fixed)
{
- str.append(1, '.');
- str.append(size_type(digits), '0');
- if(scientific)
+ if (showpoint || digits > 0) {
+ str.append(1, '.');
+ if (digits > 0)
+ str.append(size_type(digits), '0');
+ }
+ if (scientific)
str.append("e+00");
}
else
{
- if(showpoint)
+ if (showpoint)
{
str.append(1, '.');
- if(digits > 1)
+ if (digits > 1)
str.append(size_type(digits - 1), '0');
}
}
- if(neg)
+ if (neg)
str.insert(static_cast<std::string::size_type>(0), 1, '-');
- else if(showpos)
+ else if (showpos)
str.insert(static_cast<std::string::size_type>(0), 1, '+');
return;
}
- if(!fixed && !scientific && !showpoint)
+ if (!fixed && !scientific && !showpoint)
{
//
// Suppress trailing zeros:
//
std::string::iterator pos = str.end();
- while(pos != str.begin() && *--pos == '0'){}
- if(pos != str.end())
+ while (pos != str.begin() && *--pos == '0')
+ {
+ }
+ if (pos != str.end())
++pos;
str.erase(pos, str.end());
- if(str.empty())
+ if (str.empty())
str = '0';
}
- else if(!fixed || (my_exp >= 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)
+ std::intmax_t chars = static_cast<std::intmax_t>(str.size());
+ chars = digits - chars;
+ if (scientific)
++chars;
- if(chars > 0)
+ if (chars > 0)
{
str.append(static_cast<std::string::size_type>(chars), '0');
}
}
- if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
+ if (fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
{
- if(1 + my_exp > static_cast<boost::intmax_t>(str.size()))
+ if (1 + my_exp > static_cast<std::intmax_t>(str.size()))
{
// Just pad out the end with zeros:
- str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
- if(showpoint || fixed)
+ str.append(static_cast<std::string::size_type>(1 + my_exp - static_cast<std::intmax_t>(str.size())), '0');
+ if (showpoint || (fixed && digits > 0))
str.append(".");
}
- else if(my_exp + 1 < static_cast<boost::intmax_t>(str.size()))
+ else if (my_exp + 1 < static_cast<std::intmax_t>(str.size()))
{
- if(my_exp < 0)
+ if (my_exp < 0)
{
str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
str.insert(static_cast<std::string::size_type>(0), "0.");
@@ -926,62 +1456,96 @@ void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits,
str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
}
}
- else if(showpoint || fixed) // we have exactly the digits we require to left of the point
+ else if (showpoint || (fixed && digits > 0)) // we have exactly the digits we require to left of the point
str += ".";
- if(fixed)
+ 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');
+ auto pos = str.find('.');
+ if (pos != str.npos) { // this test is probably redundant, but just to be safe and for clarity
+ std::intmax_t l = static_cast<std::intmax_t>(pos + 1);
+ l = static_cast<std::intmax_t>(digits - (static_cast<std::intmax_t>(str.size()) - l));
+ if (l > 0)
+ str.append(size_type(l), '0');
+ }
}
}
else
{
BOOST_MP_USING_ABS
// Scientific format:
- if(showpoint || (str.size() > 1))
+ if (showpoint || (str.size() > 1))
str.insert(static_cast<std::string::size_type>(1u), 1, '.');
str.append(static_cast<std::string::size_type>(1u), 'e');
- S e = boost::lexical_cast<S>(abs(my_exp));
- if(e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
+
+ S e;
+
+ #ifndef BOOST_MP_STANDALONE
+ e = boost::lexical_cast<S>(abs(my_exp));
+ #else
+ BOOST_IF_CONSTEXPR(std::is_same<S, std::string>::value)
+ {
+ e = std::to_string(abs(my_exp));
+ }
+ else
+ {
+ const std::string str_local_exp = std::to_string(abs(my_exp));
+ e = S(str_local_exp.cbegin(), str_local_exp.cend());
+ }
+ #endif
+
+ if (e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
- if(my_exp < 0)
+ if (my_exp < 0)
e.insert(static_cast<std::string::size_type>(0), 1, '-');
else
e.insert(static_cast<std::string::size_type>(0), 1, '+');
str.append(e);
}
- if(neg)
+ if (neg)
str.insert(static_cast<std::string::size_type>(0), 1, '-');
- else if(showpos)
+ else if (showpos)
str.insert(static_cast<std::string::size_type>(0), 1, '+');
}
template <class V>
-void check_shift_range(V val, const mpl::true_&, const mpl::true_&)
+BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&)
{
- if(val > (std::numeric_limits<std::size_t>::max)())
- BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
- if(val < 0)
- BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
+ if (val > (std::numeric_limits<std::size_t>::max)())
+ BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
+ if (val < 0)
+ BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
}
template <class V>
-void check_shift_range(V val, const mpl::false_&, const mpl::true_&)
+BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
{
- if(val < 0)
- BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
+ if (val < 0)
+ BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
}
template <class V>
-void check_shift_range(V val, const mpl::true_&, const mpl::false_&)
+BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&)
{
- if(val > (std::numeric_limits<std::size_t>::max)())
- BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
+ if (val > (std::numeric_limits<std::size_t>::max)())
+ BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
}
template <class V>
-void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT{}
+BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&) noexcept {}
+
+template <class T>
+BOOST_MP_CXX14_CONSTEXPR const T& evaluate_if_expression(const T& val) { return val; }
+template <class T>
+BOOST_MP_CXX14_CONSTEXPR T&& evaluate_if_expression(T&& val) { return static_cast<T&&>(val); }
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+BOOST_MP_CXX14_CONSTEXPR typename expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type evaluate_if_expression(const expression<tag, Arg1, Arg2, Arg3, Arg4>& val) { return val; }
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+BOOST_MP_CXX14_CONSTEXPR typename expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type evaluate_if_expression(expression<tag, Arg1, Arg2, Arg3, Arg4>&& val) { return val; }
+
+template <class T>
+struct convertible_to
+{
+ operator T () const;
+};
} // namespace detail
@@ -990,99 +1554,146 @@ void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT
//
enum number_category_type
{
- number_kind_unknown = -1,
- number_kind_integer = 0,
+ number_kind_unknown = -1,
+ number_kind_integer = 0,
number_kind_floating_point = 1,
- number_kind_rational = 2,
- number_kind_fixed_point = 3
+ number_kind_rational = 2,
+ number_kind_fixed_point = 3,
+ number_kind_complex = 4
};
+template <class Num, bool, bool>
+struct number_category_base : public std::integral_constant<int, number_kind_unknown>
+{};
template <class Num>
-struct number_category : public mpl::int_<std::numeric_limits<Num>::is_integer ? number_kind_integer : (std::numeric_limits<Num>::max_exponent ? number_kind_floating_point : number_kind_unknown)> {};
+struct number_category_base<Num, true, false> : public std::integral_constant<int, std::numeric_limits<Num>::is_integer ? number_kind_integer : (std::numeric_limits<Num>::max_exponent ? number_kind_floating_point : number_kind_unknown)>
+{};
+template <class Num>
+struct number_category : public number_category_base<Num, std::is_class<Num>::value || boost::multiprecision::detail::is_arithmetic<Num>::value, std::is_abstract<Num>::value>
+{};
template <class Backend, expression_template_option ExpressionTemplates>
-struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>{};
+struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>
+{};
template <class tag, class A1, class A2, class A3, class A4>
-struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>{};
+struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
+{};
//
// Specializations for types which do not always have numberic_limits specializations:
//
#ifdef BOOST_HAS_INT128
template <>
-struct number_category<__int128> : public mpl::int_<number_kind_integer> {};
+struct number_category<boost::multiprecision::int128_type> : public std::integral_constant<int, number_kind_integer>
+{};
template <>
-struct number_category<unsigned __int128> : public mpl::int_<number_kind_integer> {};
+struct number_category<boost::multiprecision::uint128_type> : public std::integral_constant<int, number_kind_integer>
+{};
#endif
#ifdef BOOST_HAS_FLOAT128
template <>
-struct number_category<__float128> : public mpl::int_<number_kind_floating_point> {};
+struct number_category<boost::multiprecision::float128_type> : public std::integral_constant<int, number_kind_floating_point>
+{};
#endif
template <class T>
-struct component_type;
-template <class T, expression_template_option ExpressionTemplates>
-struct component_type<number<T, ExpressionTemplates> > : public component_type<T>{};
+struct component_type
+{
+ using type = T;
+};
template <class tag, class A1, class A2, class A3, class A4>
-struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>{};
+struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
+{};
+
+template <class T>
+struct scalar_result_from_possible_complex
+{
+ using type = typename std::conditional<number_category<T>::value == number_kind_complex, typename component_type<T>::type, T>::type;
+};
template <class T>
-struct is_unsigned_number : public mpl::false_{};
+struct complex_result_from_scalar; // individual backends must specialize this trait.
+
+template <class T>
+struct is_unsigned_number : public std::integral_constant<bool, false>
+{};
template <class Backend, expression_template_option ExpressionTemplates>
-struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend> {};
+struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend>
+{};
template <class T>
-struct is_signed_number : public mpl::bool_<!is_unsigned_number<T>::value> {};
+struct is_signed_number : public std::integral_constant<bool, !is_unsigned_number<T>::value>
+{};
template <class T>
-struct is_interval_number : public mpl::false_ {};
+struct is_interval_number : public std::integral_constant<bool, false>
+{};
template <class Backend, expression_template_option ExpressionTemplates>
-struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>{};
+struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>
+{};
-}} // namespaces
+template <class T, class U>
+struct is_equivalent_number_type : public std::is_same<T, U>
+{};
-namespace boost{ namespace math{ namespace tools{
+template <class Backend, expression_template_option ExpressionTemplates, class T2>
+struct is_equivalent_number_type<number<Backend, ExpressionTemplates>, T2> : public is_equivalent_number_type<Backend, T2>
+{};
+template <class T1, class Backend, expression_template_option ExpressionTemplates>
+struct is_equivalent_number_type<T1, number<Backend, ExpressionTemplates> > : public is_equivalent_number_type<Backend, T1>
+{};
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+struct is_equivalent_number_type<number<Backend, ExpressionTemplates>, number<Backend2, ExpressionTemplates2> > : public is_equivalent_number_type<Backend, Backend2>
+{};
-template <class T>
-struct promote_arg;
+}
+} // namespace boost
-template <class tag, class A1, class A2, class A3, class A4>
-struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
-{
- typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type type;
-};
+#ifdef BOOST_MP_MATH_AVAILABLE
+namespace boost { namespace math {
+ namespace tools {
-template <class R, class B, boost::multiprecision::expression_template_option ET>
-inline R real_cast(const boost::multiprecision::number<B, ET>& val)
-{
- return val.template convert_to<R>();
-}
+ template <class T>
+ struct promote_arg;
-template <class R, class tag, class A1, class A2, class A3, class A4>
-inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
-{
- typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type val_type;
- return val_type(val).template convert_to<R>();
-}
+ template <class tag, class A1, class A2, class A3, class A4>
+ struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
+ {
+ using type = typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ };
+ template <class R, class B, boost::multiprecision::expression_template_option ET>
+ inline R real_cast(const boost::multiprecision::number<B, ET>& val)
+ {
+ return val.template convert_to<R>();
+ }
-}
+ template <class R, class tag, class A1, class A2, class A3, class A4>
+ inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
+ {
+ using val_type = typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
+ return val_type(val).template convert_to<R>();
+ }
-namespace constants{
+ template <class B, boost::multiprecision::expression_template_option ET>
+ struct is_complex_type<boost::multiprecision::number<B, ET> > : public std::integral_constant<bool, boost::multiprecision::number_category<B>::value == boost::multiprecision::number_kind_complex> {};
- template <class T>
- struct is_explicitly_convertible_from_string;
+} // namespace tools
- template <class B, boost::multiprecision::expression_template_option ET>
- struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
- {
- static const bool value = true;
- };
+namespace constants {
-}
+template <class T>
+struct is_explicitly_convertible_from_string;
+
+template <class B, boost::multiprecision::expression_template_option ET>
+struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
+{
+ static constexpr bool value = true;
+};
-}}
+} // namespace constants
-#ifdef BOOST_MSVC
-# pragma warning(pop)
+}} // namespace boost::math
#endif
-#endif // BOOST_MATH_BIG_NUM_BASE_HPP
-
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+#endif // BOOST_MP_NUMBER_BASE_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_compare.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_compare.hpp
index adf034265c..41160308a9 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_compare.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/number_compare.hpp
@@ -3,18 +3,19 @@
// 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_MP_COMPARE_HPP
-#define BOOST_MP_COMPARE_HPP
+#ifndef BOOST_MP_NUMBER_COMPARE_HPP
+#define BOOST_MP_NUMBER_COMPARE_HPP
#include <boost/multiprecision/traits/is_backend.hpp>
+#include <boost/multiprecision/detail/fpclassify.hpp>
//
// Comparison operators for number.
//
-namespace boost{ namespace multiprecision{
+namespace boost { namespace multiprecision {
-namespace default_ops{
+namespace default_ops {
//
// The dispatching mechanism used here to deal with differently typed arguments
@@ -22,456 +23,611 @@ namespace default_ops{
// under strange and hard to reproduce circumstances.
//
template <class B>
-inline bool eval_eq(const B& a, const B& b)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq(const B& a, const B& b)
{
return a.compare(b) == 0;
}
template <class T, class U>
-inline bool eval_eq_imp(const T& a, const U& b, const mpl::true_&)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq_imp(const T& a, const U& b, const std::integral_constant<bool, true>&)
{
typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
return eval_eq(a, t.backend());
}
template <class T, class U>
-inline bool eval_eq_imp(const T& a, const U& b, const mpl::false_&)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq_imp(const T& a, const U& b, const std::integral_constant<bool, false>&)
{
typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
return eval_eq(t.backend(), b);
}
template <class T, class U>
-inline bool eval_eq(const T& a, const U& b)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq(const T& a, const U& b)
{
- typedef mpl::bool_<boost::multiprecision::detail::is_first_backend<T, U>::value> tag_type;
+ using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_first_backend<T, U>::value>;
return eval_eq_imp(a, b, tag_type());
}
template <class B>
-inline bool eval_lt(const B& a, const B& b)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const B& a, const B& b)
{
return a.compare(b) < 0;
}
template <class T, class U>
-inline bool eval_lt_imp(const T& a, const U& b, const mpl::true_&)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt_imp(const T& a, const U& b, const std::integral_constant<bool, true>&)
{
typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
return eval_lt(a, t.backend());
}
template <class T, class U>
-inline bool eval_lt_imp(const T& a, const U& b, const mpl::false_&)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt_imp(const T& a, const U& b, const std::integral_constant<bool, false>&)
{
typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
return eval_lt(t.backend(), b);
}
template <class T, class U>
-inline bool eval_lt(const T& a, const U& b)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const T& a, const U& b)
{
- typedef mpl::bool_<boost::multiprecision::detail::is_first_backend<T, U>::value> tag_type;
+ using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_first_backend<T, U>::value>;
return eval_lt_imp(a, b, tag_type());
}
template <class B>
-inline bool eval_gt(const B& a, const B& b)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const B& a, const B& b)
{
return a.compare(b) > 0;
}
template <class T, class U>
-inline bool eval_gt_imp(const T& a, const U& b, const mpl::true_&)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt_imp(const T& a, const U& b, const std::integral_constant<bool, true>&)
{
typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
return eval_gt(a, t.backend());
}
template <class T, class U>
-inline bool eval_gt_imp(const T& a, const U& b, const mpl::false_&)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt_imp(const T& a, const U& b, const std::integral_constant<bool, false>&)
{
typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
return eval_gt(t.backend(), b);
}
template <class T, class U>
-inline bool eval_gt(const T& a, const U& b)
+inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const T& a, const U& b)
{
- typedef mpl::bool_<boost::multiprecision::detail::is_first_backend<T, U>::value> tag_type;
+ using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_first_backend<T, U>::value>;
return eval_gt_imp(a, b, tag_type());
}
} // namespace default_ops
-namespace detail{
+namespace detail {
template <class Num, class Val>
-struct is_valid_mixed_compare : public mpl::false_ {};
+struct is_valid_mixed_compare : public std::integral_constant<bool, false>
+{};
template <class B, expression_template_option ET, class Val>
-struct is_valid_mixed_compare<number<B, ET>, Val> : public is_convertible<Val, number<B, ET> > {};
+struct is_valid_mixed_compare<number<B, ET>, Val> : public std::is_convertible<Val, number<B, ET> >
+{};
template <class B, expression_template_option ET>
-struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public mpl::false_ {};
+struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public std::integral_constant<bool, false>
+{};
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> >
- : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
+struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ : public std::is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+{};
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
- : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
+struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+ : public std::is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+{};
template <class Backend, expression_template_option ExpressionTemplates>
-inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>&)
+inline constexpr typename std::enable_if<number_category<Backend>::value != number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>&)
{
return false;
}
template <class Backend, expression_template_option ExpressionTemplates>
-inline
-#if !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
-BOOST_CONSTEXPR
-#endif
- typename boost::enable_if_c<number_category<Backend>::value == number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>& a)
+inline constexpr typename std::enable_if<number_category<Backend>::value == number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>& a)
{
using default_ops::eval_fpclassify;
return eval_fpclassify(a.backend()) == FP_NAN;
}
template <class Arithmetic>
-inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value != number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic&)
+inline constexpr typename std::enable_if<number_category<Arithmetic>::value != number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic&)
{
return false;
}
template <class Arithmetic>
-inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value == number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic& a)
-{
- return (boost::math::isnan)(a);
+inline
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ BOOST_MP_CXX14_CONSTEXPR
+#endif
+ typename std::enable_if < number_category < Arithmetic> ::value == number_kind_floating_point, bool> ::type
+ is_unordered_value(const Arithmetic& a)
+{
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ if (BOOST_MP_IS_CONST_EVALUATED(a))
+ {
+ return a != a;
+ }
+ else
+#endif
+ {
+ return BOOST_MP_ISNAN(a);
+ }
}
template <class T, class U>
-inline BOOST_CONSTEXPR bool is_unordered_comparison(const T& a, const U& b)
+inline constexpr bool is_unordered_comparison(const T& a, const U& b)
{
return is_unordered_value(a) || is_unordered_value(b);
}
-}
+} // namespace detail
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool operator == (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+inline BOOST_MP_CXX14_CONSTEXPR bool operator==(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_eq;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return eval_eq(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator == (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && !is_number_expression<Arithmetic>::value, bool>::type
+operator==(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_eq;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator == (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && !is_number_expression<Arithmetic>::value, bool>::type
+operator==(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_eq;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator == (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+operator==(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_eq;
result_type t(b);
- if(detail::is_unordered_comparison(a, t)) return false;
+ if (detail::is_unordered_comparison(a, t))
+ return false;
return eval_eq(t.backend(), result_type::canonical_value(a));
}
+template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator==(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_eq;
+ result_type t(b);
+ if (detail::is_unordered_comparison(a, t))
+ return false;
+ return eval_eq(t.backend(), a.backend());
+}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_eq;
result_type t(a);
- if(detail::is_unordered_comparison(t, b)) return false;
+ if (detail::is_unordered_comparison(t, b))
+ return false;
return eval_eq(t.backend(), result_type::canonical_value(b));
}
+template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_eq;
+ result_type t(a);
+ if (detail::is_unordered_comparison(t, b))
+ return false;
+ return eval_eq(t.backend(), b.backend());
+}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
- operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
+operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
{
using default_ops::eval_eq;
- typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
- if(detail::is_unordered_comparison(t, t2)) return false;
+ if (detail::is_unordered_comparison(t, t2))
+ return false;
return eval_eq(t.backend(), t2.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool operator != (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_eq;
- if(detail::is_unordered_comparison(a, b)) return true;
+ if (detail::is_unordered_comparison(a, b))
+ return true;
return !eval_eq(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator != (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && !is_number_expression<Arithmetic>::value, bool>::type
+operator!=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_eq;
- if(detail::is_unordered_comparison(a, b)) return true;
+ if (detail::is_unordered_comparison(a, b))
+ return true;
return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator != (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && !is_number_expression<Arithmetic>::value, bool>::type
+operator!=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_eq;
- if(detail::is_unordered_comparison(a, b)) return true;
+ if (detail::is_unordered_comparison(a, b))
+ return true;
return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator != (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+operator!=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_eq;
result_type t(b);
- if(detail::is_unordered_comparison(a, t)) return true;
+ if (detail::is_unordered_comparison(a, t))
+ return true;
return !eval_eq(t.backend(), result_type::canonical_value(a));
}
+template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_eq;
+ result_type t(b);
+ if (detail::is_unordered_comparison(a, t))
+ return true;
+ return !eval_eq(t.backend(), a.backend());
+}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_eq;
result_type t(a);
- if(detail::is_unordered_comparison(t, b)) return true;
+ if (detail::is_unordered_comparison(t, b))
+ return true;
+ return !eval_eq(t.backend(), result_type::canonical_value(b));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_eq;
+ result_type t(a);
+ if (detail::is_unordered_comparison(t, b))
+ return true;
return !eval_eq(t.backend(), result_type::canonical_value(b));
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
- operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
+operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
{
using default_ops::eval_eq;
- typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
- if(detail::is_unordered_comparison(t, t2)) return true;
+ if (detail::is_unordered_comparison(t, t2))
+ return true;
return !eval_eq(t.backend(), t2.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool operator < (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
+operator<(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_lt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return eval_lt(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
+operator<(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_lt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
+operator<(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_gt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator < (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator<(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_gt;
result_type t(b);
- if(detail::is_unordered_comparison(a, t)) return false;
+ if (detail::is_unordered_comparison(a, t))
+ return false;
return eval_gt(t.backend(), result_type::canonical_value(a));
}
+template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator<(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_gt;
+ result_type t(b);
+ return a < t;
+}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_lt;
result_type t(a);
- if(detail::is_unordered_comparison(t, b)) return false;
+ if (detail::is_unordered_comparison(t, b))
+ return false;
return eval_lt(t.backend(), result_type::canonical_value(b));
}
+template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_lt;
+ result_type t(a);
+ return t < b;
+}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
- operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
{
using default_ops::eval_lt;
- typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
- if(detail::is_unordered_comparison(t, t2)) return false;
+ if (detail::is_unordered_comparison(t, t2))
+ return false;
return eval_lt(t.backend(), t2.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool operator > (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
+operator>(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_gt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return eval_gt(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
+operator>(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_gt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
+operator>(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_lt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator > (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator>(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_lt;
+ result_type t(b);
+ return a > t;
+}
+template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator>(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_lt;
result_type t(b);
- if(detail::is_unordered_comparison(a, t)) return false;
return a > t;
}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_gt;
+ result_type t(a);
+ return t > b;
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_gt;
result_type t(a);
- if(detail::is_unordered_comparison(t, b)) return false;
return t > b;
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
- operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
{
using default_ops::eval_gt;
- typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
- if(detail::is_unordered_comparison(t, t2)) return false;
return t > t2;
}
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool operator <= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
+operator<=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_gt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return !eval_gt(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
+operator<=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_gt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
+operator<=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_lt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator <= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator<=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_lt;
- if(detail::is_unordered_value(a) || detail::is_unordered_value(b))
+ if (detail::is_unordered_value(a) || detail::is_unordered_value(b))
return false;
result_type t(b);
- if(detail::is_unordered_comparison(a, t)) return false;
+ if (detail::is_unordered_comparison(a, t))
+ return false;
return !eval_lt(t.backend(), result_type::canonical_value(a));
}
+template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator<=(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_lt;
+ if (detail::is_unordered_value(a) || detail::is_unordered_value(b))
+ return false;
+ result_type t(b);
+ return a <= t;
+}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_gt;
result_type t(a);
- if(detail::is_unordered_comparison(t, b)) return false;
+ if (detail::is_unordered_comparison(t, b))
+ return false;
return !eval_gt(t.backend(), result_type::canonical_value(b));
}
+template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_gt;
+ result_type t(a);
+ return t <= b;
+}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
- operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
{
using default_ops::eval_gt;
- typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
- if(detail::is_unordered_comparison(t, t2)) return false;
+ if (detail::is_unordered_comparison(t, t2))
+ return false;
return !eval_gt(t.backend(), t2.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool operator >= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
+operator>=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_lt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return !eval_lt(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
+operator>=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_lt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
+operator>=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_gt;
- if(detail::is_unordered_comparison(a, b)) return false;
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator >= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator>=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_gt;
result_type t(b);
- if(detail::is_unordered_comparison(a, t)) return false;
+ if (detail::is_unordered_comparison(a, t))
+ return false;
return !eval_gt(t.backend(), result_type::canonical_value(a));
}
+template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator>=(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_gt;
+ result_type t(b);
+ return a >= t;
+}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
{
- typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
using default_ops::eval_lt;
result_type t(a);
- if(detail::is_unordered_comparison(t, b)) return false;
+ if (detail::is_unordered_comparison(t, b))
+ return false;
return !eval_lt(t.backend(), result_type::canonical_value(b));
}
+template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR bool operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
+{
+ using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
+ using default_ops::eval_lt;
+ result_type t(a);
+ return t >= b;
+}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
- operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
+operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
{
using default_ops::eval_lt;
- typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
- if(detail::is_unordered_comparison(t, t2)) return false;
+ if (detail::is_unordered_comparison(t, t2))
+ return false;
return !eval_lt(t.backend(), t2.backend());
}
@@ -479,182 +635,214 @@ inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A
// C99 comparison macros as functions:
//
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a > b; }
+inline BOOST_MP_CXX14_CONSTEXPR bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a > b; }
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a > b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a > b; }
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a > b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a > b; }
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a > b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a > b; }
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a > b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a > b; }
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
- isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a > b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
+ isgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a > b; }
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a >= b; }
+inline BOOST_MP_CXX14_CONSTEXPR bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a >= b; }
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a >= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isgreaterequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a >= b; }
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
- isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a >= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isgreaterequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a >= b; }
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a >= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isgreaterequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a >= b; }
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
- isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a >= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isgreaterequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a >= b; }
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
- isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a >= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
+ isgreaterequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a >= b; }
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a <= b; }
+inline BOOST_MP_CXX14_CONSTEXPR bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a <= b; }
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
-islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a <= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ islessequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a <= b; }
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
-islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a <= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ islessequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a <= b; }
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
-islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a <= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ islessequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a <= b; }
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
-islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a <= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ islessequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a <= b; }
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
-islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a <= b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
+ islessequal
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a <= b; }
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a < b; }
+inline BOOST_MP_CXX14_CONSTEXPR bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a < b; }
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
-isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a < b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isless
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a < b; }
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
-isless BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a < b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isless
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a < b; }
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
-isless BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a < b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isless
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a < b; }
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
-isless BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a < b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isless
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a < b; }
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
-isless BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a < b; }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
+ isless
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a < b; }
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
-{
- if(detail::is_unordered_comparison(a, b)) return false;
+inline BOOST_MP_CXX14_CONSTEXPR bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+{
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return a != b;
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
-islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
-{
- if(detail::is_unordered_comparison(a, b)) return false;
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ islessgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+{
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return a != b;
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
-islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
-{
- if(detail::is_unordered_comparison(a, b)) return false;
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ islessgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+{
+ if (detail::is_unordered_comparison(a, b))
+ return false;
return a != b;
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
-islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ islessgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
{
typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
- return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
+ return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
-islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
-{
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ islessgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
+{
typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
- return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
+ return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
-islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
-{
- typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
+ islessgreater
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
+{
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
- return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
+ return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
}
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
-inline bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return detail::is_unordered_comparison(a, b); }
+inline BOOST_MP_CXX14_CONSTEXPR bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return detail::is_unordered_comparison(a, b); }
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
-isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return detail::is_unordered_comparison(a, b); }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isunordered
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return detail::is_unordered_comparison(a, b); }
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
-isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return detail::is_unordered_comparison(a, b); }
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isunordered
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return detail::is_unordered_comparison(a, b); }
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
-isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
-{
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isunordered
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
+{
typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
return detail::is_unordered_comparison(a, b);
}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
-isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
-{
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isunordered
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
+{
typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
return detail::is_unordered_comparison(a, b);
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
-inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
-isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
+ isunordered
+ BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
{
- typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
return detail::is_unordered_comparison(a, b);
}
-}} // namespaces
-
-#endif // BOOST_MP_COMPARE_HPP
+}} // namespace boost::multiprecision
+#endif // BOOST_MP_NUMBER_COMPARE_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/precision.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/precision.hpp
new file mode 100644
index 0000000000..df58144297
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/precision.hpp
@@ -0,0 +1,313 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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_MP_DETAIL_PRECISION_HPP
+#define BOOST_MP_DETAIL_PRECISION_HPP
+
+#include <boost/multiprecision/traits/is_variable_precision.hpp>
+#include <boost/multiprecision/detail/number_base.hpp>
+#include <boost/multiprecision/detail/digits.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+
+namespace boost { namespace multiprecision { namespace detail {
+
+template <class B, boost::multiprecision::expression_template_option ET>
+inline constexpr unsigned current_precision_of_last_chance_imp(const boost::multiprecision::number<B, ET>&, const std::integral_constant<int, 0>&)
+{
+ return std::numeric_limits<boost::multiprecision::number<B, ET> >::digits10;
+}
+template <class B, boost::multiprecision::expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR unsigned current_precision_of_last_chance_imp(const boost::multiprecision::number<B, ET>& val, const std::integral_constant<int, 1>&)
+{
+ //
+ // We have an arbitrary precision integer, take it's "precision" as the
+ // location of the most-significant-bit less the location of the
+ // least-significant-bit, ie the number of bits required to represent the
+ // the value assuming we will have an exponent to shift things by:
+ //
+ return static_cast<unsigned>(val.is_zero() ? 1 : 1 + digits2_2_10(msb(abs(val)) - lsb(abs(val)) + 1));
+}
+template <class B, boost::multiprecision::expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR unsigned current_precision_of_last_chance_imp(const boost::multiprecision::number<B, ET>& val, const std::integral_constant<int, 2>&)
+{
+ //
+ // We have an arbitrary precision rational, take it's "precision" as the
+ // the larger of the "precision" of numerator and denominator:
+ //
+ return (std::max)(current_precision_of_last_chance_imp(numerator(val), std::integral_constant<int, 1>()), current_precision_of_last_chance_imp(denominator(val), std::integral_constant<int, 1>()));
+}
+
+template <class B, boost::multiprecision::expression_template_option ET>
+inline BOOST_MP_CXX14_CONSTEXPR unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>& n, const std::integral_constant<bool, true>&)
+{
+ return n.precision();
+}
+template <class B, boost::multiprecision::expression_template_option ET>
+inline constexpr unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>& val, const std::integral_constant<bool, false>&)
+{
+ using tag = std::integral_constant<int,
+ std::numeric_limits<boost::multiprecision::number<B, ET> >::is_specialized &&
+ std::numeric_limits<boost::multiprecision::number<B, ET> >::is_integer &&
+ std::numeric_limits<boost::multiprecision::number<B, ET> >::is_exact &&
+ !std::numeric_limits<boost::multiprecision::number<B, ET> >::is_modulo
+ ? 1
+ : boost::multiprecision::number_category<boost::multiprecision::number<B, ET> >::value == boost::multiprecision::number_kind_rational ? 2
+ : 0>;
+ return current_precision_of_last_chance_imp(val, tag());
+}
+
+template <class R, class Terminal>
+inline constexpr unsigned current_precision_of_terminal(const Terminal&)
+{
+ return (R::thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
+ ? (std::numeric_limits<Terminal>::min_exponent ? std::numeric_limits<Terminal>::digits10 : 1 + std::numeric_limits<Terminal>::digits10) : 0;
+}
+template <class R, class Terminal>
+inline constexpr unsigned current_precision_of(const Terminal& r)
+{
+ return current_precision_of_terminal<R>(R::canonical_value(r));
+}
+template <class R>
+inline constexpr unsigned current_precision_of(const float&)
+{
+ using list = typename R::backend_type::float_types;
+ using first_float = typename std::tuple_element<0, list>::type;
+
+ return (R::thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision) ? std::numeric_limits<first_float>::digits10 : 0;
+}
+
+template <class R, class Terminal, std::size_t N>
+inline constexpr unsigned current_precision_of(const Terminal (&)[N])
+{ // For string literals:
+ return 0;
+}
+
+template <class R, class B, boost::multiprecision::expression_template_option ET>
+inline constexpr unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>& n, const std::true_type&)
+{
+ return std::is_same<R, boost::multiprecision::number<B, ET> >::value
+ || (std::is_same<typename R::value_type, boost::multiprecision::number<B, ET> >::value && (R::thread_default_variable_precision_options() >= variable_precision_options::preserve_component_precision))
+ || (R::thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
+ ? current_precision_of_imp(n, boost::multiprecision::detail::is_variable_precision<boost::multiprecision::number<B, ET> >()) : 0;
+}
+template <class R, class B, boost::multiprecision::expression_template_option ET>
+inline constexpr unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>& n, const std::false_type&)
+{
+ return std::is_same<R, boost::multiprecision::number<B, ET> >::value
+ || std::is_same<typename R::value_type, boost::multiprecision::number<B, ET> >::value
+ ? current_precision_of_imp(n, boost::multiprecision::detail::is_variable_precision<boost::multiprecision::number<B, ET> >()) : 0;
+}
+
+template <class R, class B, boost::multiprecision::expression_template_option ET>
+inline constexpr unsigned current_precision_of(const boost::multiprecision::number<B, ET>& n)
+{
+ return current_precision_of_imp<R>(n, boost::multiprecision::detail::is_variable_precision<R>());
+}
+
+template <class R, class tag, class Arg1>
+inline constexpr unsigned current_precision_of(const expression<tag, Arg1, void, void, void>& expr)
+{
+ return current_precision_of<R>(expr.left_ref());
+}
+
+template <class R, class Arg1>
+inline constexpr unsigned current_precision_of(const expression<terminal, Arg1, void, void, void>& expr)
+{
+ return current_precision_of<R>(expr.value());
+}
+
+template <class R, class tag, class Arg1, class Arg2>
+inline constexpr unsigned current_precision_of(const expression<tag, Arg1, Arg2, void, void>& expr)
+{
+ return (std::max)(current_precision_of<R>(expr.left_ref()), current_precision_of<R>(expr.right_ref()));
+}
+
+template <class R, class tag, class Arg1, class Arg2, class Arg3>
+inline constexpr unsigned current_precision_of(const expression<tag, Arg1, Arg2, Arg3, void>& expr)
+{
+ return (std::max)((std::max)(current_precision_of<R>(expr.left_ref()), current_precision_of<R>(expr.right_ref())), current_precision_of<R>(expr.middle_ref()));
+}
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable : 4130)
+#endif
+
+template <class R, bool = boost::multiprecision::detail::is_variable_precision<R>::value>
+struct scoped_default_precision
+{
+ template <class T>
+ constexpr scoped_default_precision(const T&) {}
+ template <class T, class U>
+ constexpr scoped_default_precision(const T&, const U&) {}
+ template <class T, class U, class V>
+ constexpr scoped_default_precision(const T&, const U&, const V&) {}
+
+ //
+ // This function is never called: in C++17 it won't be compiled either:
+ //
+ unsigned precision() const
+ {
+ BOOST_MP_ASSERT("This function should never be called!!" == nullptr);
+ return 0;
+ }
+};
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+template <class R>
+struct scoped_default_precision<R, true>
+{
+ template <class T>
+ BOOST_MP_CXX14_CONSTEXPR scoped_default_precision(const T& a)
+ {
+ init(has_uniform_precision() ? R::thread_default_precision() : (std::max)(R::thread_default_precision(), current_precision_of<R>(a)));
+ }
+ template <class T, class U>
+ BOOST_MP_CXX14_CONSTEXPR scoped_default_precision(const T& a, const U& b)
+ {
+ init(has_uniform_precision() ? R::thread_default_precision() : (std::max)(R::thread_default_precision(), (std::max)(current_precision_of<R>(a), current_precision_of<R>(b))));
+ }
+ template <class T, class U, class V>
+ BOOST_MP_CXX14_CONSTEXPR scoped_default_precision(const T& a, const U& b, const V& c)
+ {
+ init(has_uniform_precision() ? R::thread_default_precision() : (std::max)((std::max)(current_precision_of<R>(a), current_precision_of<R>(b)), (std::max)(R::thread_default_precision(), current_precision_of<R>(c))));
+ }
+ ~scoped_default_precision()
+ {
+ if(m_new_prec != m_old_prec)
+ R::thread_default_precision(m_old_prec);
+ }
+ BOOST_MP_CXX14_CONSTEXPR unsigned precision() const
+ {
+ return m_new_prec;
+ }
+
+ static constexpr bool has_uniform_precision()
+ {
+ return R::thread_default_variable_precision_options() <= boost::multiprecision::variable_precision_options::assume_uniform_precision;
+ }
+
+ private:
+ BOOST_MP_CXX14_CONSTEXPR void init(unsigned p)
+ {
+ m_old_prec = R::thread_default_precision();
+ if (p && (p != m_old_prec))
+ {
+ R::thread_default_precision(p);
+ m_new_prec = p;
+ }
+ else
+ m_new_prec = m_old_prec;
+ }
+ unsigned m_old_prec, m_new_prec;
+};
+
+template <class T>
+inline BOOST_MP_CXX14_CONSTEXPR void maybe_promote_precision(T*, const std::integral_constant<bool, false>&) {}
+
+template <class T>
+inline BOOST_MP_CXX14_CONSTEXPR void maybe_promote_precision(T* obj, const std::integral_constant<bool, true>&)
+{
+ if (obj->precision() != T::thread_default_precision())
+ {
+ obj->precision(T::thread_default_precision());
+ }
+}
+
+template <class T>
+inline BOOST_MP_CXX14_CONSTEXPR void maybe_promote_precision(T* obj)
+{
+ maybe_promote_precision(obj, std::integral_constant<bool, boost::multiprecision::detail::is_variable_precision<T>::value>());
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+#define BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(T) \
+ if \
+ constexpr(boost::multiprecision::detail::is_variable_precision<T>::value)
+#else
+#define BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(T) if (boost::multiprecision::detail::is_variable_precision<T>::value)
+#endif
+
+template <class T, bool = boost::multiprecision::detail::is_variable_precision<T>::value>
+struct scoped_target_precision
+{
+ variable_precision_options opts;
+ scoped_target_precision() : opts(T::thread_default_variable_precision_options())
+ {
+ T::thread_default_variable_precision_options(variable_precision_options::preserve_target_precision);
+ }
+ ~scoped_target_precision()
+ {
+ T::thread_default_variable_precision_options(opts);
+ }
+};
+template <class T>
+struct scoped_target_precision<T, false> {};
+
+template <class T, bool = boost::multiprecision::detail::is_variable_precision<T>::value>
+struct scoped_source_precision
+{
+ variable_precision_options opts;
+ scoped_source_precision() : opts(T::thread_default_variable_precision_options())
+ {
+ T::thread_default_variable_precision_options(variable_precision_options::preserve_source_precision);
+ }
+ ~scoped_source_precision()
+ {
+ T::thread_default_variable_precision_options(opts);
+ }
+};
+template <class T>
+struct scoped_source_precision<T, false> {};
+
+template <class T, bool = boost::multiprecision::detail::is_variable_precision<T>::value>
+struct scoped_precision_options
+{
+ unsigned saved_digits;
+ boost::multiprecision::variable_precision_options saved_options;
+
+ scoped_precision_options(unsigned digits)
+ : saved_digits(T::thread_default_precision()), saved_options(T::thread_default_variable_precision_options())
+ {
+ T::thread_default_precision(digits);
+ }
+ scoped_precision_options(unsigned digits, variable_precision_options opts)
+ : saved_digits(T::thread_default_precision()), saved_options(T::thread_default_variable_precision_options())
+ {
+ T::thread_default_precision(digits);
+ T::thread_default_variable_precision_options(opts);
+ }
+ template <class U>
+ scoped_precision_options(const U& u)
+ : saved_digits(T::thread_default_precision()), saved_options(T::thread_default_variable_precision_options())
+ {
+ T::thread_default_precision(u.precision());
+ T::thread_default_variable_precision_options(U::thread_default_variable_precision_options());
+ }
+ ~scoped_precision_options()
+ {
+ T::thread_default_variable_precision_options(saved_options);
+ T::thread_default_precision(saved_digits);
+ }
+};
+
+template <class T>
+struct scoped_precision_options<T, false>
+{
+ scoped_precision_options(unsigned) {}
+ scoped_precision_options(unsigned, variable_precision_options) {}
+ template <class U>
+ scoped_precision_options(const U&) {}
+ ~scoped_precision_options() {}
+};
+
+}
+}
+} // namespace boost::multiprecision::detail
+
+#endif // BOOST_MP_DETAIL_PRECISION_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/rebind.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/rebind.hpp
new file mode 100644
index 0000000000..6c6bbda127
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/rebind.hpp
@@ -0,0 +1,19 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2012 John Maddock.
+// Copyright Christopher Kormanyos 2013. 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_MP_DETAIL_REBIND_HPP
+#define BOOST_MP_DETAIL_REBIND_HPP
+
+namespace boost { namespace multiprecision { namespace backends { namespace detail {
+template <class value_type, class my_allocator>
+struct rebind
+{
+ using type = typename std::allocator_traits<my_allocator>::template rebind_alloc<value_type>;
+};
+}}}} // namespace boost::multiprecision::backends::detail
+
+#endif // BOOST_MP_DETAIL_REBIND_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/standalone_config.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/standalone_config.hpp
new file mode 100644
index 0000000000..9c8ee9a5bc
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/standalone_config.hpp
@@ -0,0 +1,114 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2010 - 2021 Douglas Gregor
+// Copyright 2021 Matt Borland.
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+//
+// Used to support configuration options depending on standalone context
+// by providing either required support or disabling functionality
+
+#ifndef BOOST_MP_STANDALONE_CONFIG_HPP
+#define BOOST_MP_STANDALONE_CONFIG_HPP
+
+#include <climits>
+// Boost.Config is dependency free so it is considered a requirement to use Boost.Multiprecision in standalone mode
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+// Minimum language standard transition
+ #ifdef _MSVC_LANG
+ # if _MSVC_LANG < 201402L
+ # pragma warning("The minimum language standard to use Boost.Math will be C++14 starting in July 2023 (Boost 1.82 release)");
+ # endif
+ #else
+ # if __cplusplus < 201402L
+ # warning "The minimum language standard to use Boost.Math will be C++14 starting in July 2023 (Boost 1.82 release)"
+ # endif
+ #endif
+
+// If any of the most frequently used boost headers are missing assume that standalone mode is supposed to be used
+#ifdef __has_include
+#if !__has_include(<boost/assert.hpp>) || !__has_include(<boost/lexical_cast.hpp>) || \
+ !__has_include(<boost/throw_exception.hpp>) || !__has_include(<boost/predef/other/endian.h>)
+# ifndef BOOST_MP_STANDALONE
+# define BOOST_MP_STANDALONE
+# endif
+#endif
+#endif
+
+#ifndef BOOST_MP_STANDALONE
+
+#include <boost/integer.hpp>
+#include <boost/integer_traits.hpp>
+
+// Required typedefs for interoperability with standalone mode
+#if defined(BOOST_HAS_INT128) && defined(__cplusplus)
+namespace boost { namespace multiprecision {
+ using int128_type = boost::int128_type;
+ using uint128_type = boost::uint128_type;
+}}
+#endif
+#if defined(BOOST_HAS_FLOAT128) && defined(__cplusplus)
+namespace boost { namespace multiprecision {
+ using float128_type = boost::float128_type;
+}}
+#endif
+
+// Boost.Math available by default
+#define BOOST_MP_MATH_AVAILABLE
+
+#else // Standalone mode
+
+#ifdef BOOST_MATH_STANDALONE
+# define BOOST_MP_MATH_AVAILABLE
+#endif
+
+#ifndef BOOST_MP_MATH_AVAILABLE
+# define BOOST_MATH_INSTRUMENT_CODE(x)
+#endif
+
+// Prevent Macro sub
+#ifndef BOOST_PREVENT_MACRO_SUBSTITUTION
+# define BOOST_PREVENT_MACRO_SUBSTITUTION
+#endif
+
+#if defined(BOOST_HAS_INT128) && defined(__cplusplus)
+namespace boost { namespace multiprecision {
+# ifdef __GNUC__
+ __extension__ typedef __int128 int128_type;
+ __extension__ typedef unsigned __int128 uint128_type;
+# else
+ typedef __int128 int128_type;
+ typedef unsigned __int128 uint128_type;
+# endif
+}}
+
+#endif
+// same again for __float128:
+#if defined(BOOST_HAS_FLOAT128) && defined(__cplusplus)
+namespace boost { namespace multiprecision {
+# ifdef __GNUC__
+ __extension__ typedef __float128 float128_type;
+# else
+ typedef __float128 float128_type;
+# endif
+}}
+
+#endif
+
+#endif // BOOST_MP_STANDALONE
+
+// Workarounds for numeric limits on old compilers
+#ifdef BOOST_HAS_INT128
+# ifndef INT128_MAX
+# define INT128_MAX static_cast<boost::multiprecision::int128_type>((static_cast<boost::multiprecision::uint128_type>(1) << ((__SIZEOF_INT128__ * __CHAR_BIT__) - 1)) - 1)
+# endif
+# ifndef INT128_MIN
+# define INT128_MIN (-INT128_MAX - 1)
+# endif
+# ifndef UINT128_MAX
+# define UINT128_MAX ((2 * static_cast<boost::multiprecision::uint128_type>(INT128_MAX)) + 1)
+# endif
+#endif
+
+#endif // BOOST_MP_STANDALONE_CONFIG_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/ublas_interop.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/ublas_interop.hpp
index cf56dc9fb8..ad3afa987f 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/ublas_interop.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/detail/ublas_interop.hpp
@@ -3,75 +3,73 @@
// 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_MP_UBLAS_HPP
-#define BOOST_MP_UBLAS_HPP
+#ifndef BOOST_MP_UBLAS_INTEROP_HPP
+#define BOOST_MP_UBLAS_INTEROP_HPP
namespace boost { namespace numeric { namespace ublas {
-template<class V>
+template <class V>
class sparse_vector_element;
template <class V, class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline bool operator == (const sparse_vector_element<V>& a, const ::boost::multiprecision::number<Backend, ExpressionTemplates>& b)
+inline bool operator==(const sparse_vector_element<V>& a, const ::boost::multiprecision::number<Backend, ExpressionTemplates>& b)
{
- typedef typename sparse_vector_element<V>::const_reference ref_type;
+ using ref_type = typename sparse_vector_element<V>::const_reference;
return static_cast<ref_type>(a) == b;
}
-template<class X, class Y>
+template <class X, class Y>
struct promote_traits;
template <class Backend1, boost::multiprecision::expression_template_option ExpressionTemplates1, class Backend2, boost::multiprecision::expression_template_option ExpressionTemplates2>
struct promote_traits<boost::multiprecision::number<Backend1, ExpressionTemplates1>, boost::multiprecision::number<Backend2, ExpressionTemplates2> >
{
- typedef boost::multiprecision::number<Backend1, ExpressionTemplates1> number1_t;
- typedef boost::multiprecision::number<Backend2, ExpressionTemplates2> number2_t;
- typedef typename mpl::if_c<
- is_convertible<number1_t, number2_t>::value && !is_convertible<number2_t, number1_t>::value,
- number2_t, number1_t
- >::type promote_type;
+ using number1_t = boost::multiprecision::number<Backend1, ExpressionTemplates1>;
+ using number2_t = boost::multiprecision::number<Backend2, ExpressionTemplates2>;
+ using promote_type = typename std::conditional<
+ std::is_convertible<number1_t, number2_t>::value && !std::is_convertible<number2_t, number1_t>::value,
+ number2_t, number1_t>::type;
};
template <class Backend1, boost::multiprecision::expression_template_option ExpressionTemplates1, class Arithmetic>
struct promote_traits<boost::multiprecision::number<Backend1, ExpressionTemplates1>, Arithmetic>
{
- typedef boost::multiprecision::number<Backend1, ExpressionTemplates1> promote_type;
+ using promote_type = boost::multiprecision::number<Backend1, ExpressionTemplates1>;
};
template <class Arithmetic, class Backend1, boost::multiprecision::expression_template_option ExpressionTemplates1>
struct promote_traits<Arithmetic, boost::multiprecision::number<Backend1, ExpressionTemplates1> >
{
- typedef boost::multiprecision::number<Backend1, ExpressionTemplates1> promote_type;
+ using promote_type = boost::multiprecision::number<Backend1, ExpressionTemplates1>;
};
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<Backend1, ExpressionTemplates1>, boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
{
- typedef boost::multiprecision::number<Backend1, ExpressionTemplates1> number1_t;
- typedef boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> expression_type;
- typedef typename expression_type::result_type number2_t;
- typedef typename promote_traits<number1_t, number2_t>::promote_type promote_type;
+ using number1_t = boost::multiprecision::number<Backend1, ExpressionTemplates1> ;
+ using expression_type = boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>;
+ using number2_t = typename expression_type::result_type ;
+ using promote_type = typename promote_traits<number1_t, number2_t>::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<tag, Arg1, Arg2, Arg3, Arg4>, boost::multiprecision::number<Backend1, ExpressionTemplates1> >
{
- typedef boost::multiprecision::number<Backend1, ExpressionTemplates1> number1_t;
- typedef boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> expression_type;
- typedef typename expression_type::result_type number2_t;
- typedef typename promote_traits<number1_t, number2_t>::promote_type promote_type;
+ using number1_t = boost::multiprecision::number<Backend1, ExpressionTemplates1> ;
+ using expression_type = boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>;
+ using number2_t = typename expression_type::result_type ;
+ using promote_type = typename promote_traits<number1_t, number2_t>::promote_type ;
};
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tagb, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
struct promote_traits<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, boost::multiprecision::detail::expression<tagb, Arg1b, Arg2b, Arg3b, Arg4b> >
{
- typedef boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> expression1_t;
- typedef typename expression1_t::result_type number1_t;
- typedef boost::multiprecision::detail::expression<tagb, Arg1b, Arg2b, Arg3b, Arg4b> expression2_t;
- typedef typename expression2_t::result_type number2_t;
+ using expression1_t = boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> ;
+ using number1_t = typename expression1_t::result_type ;
+ using expression2_t = boost::multiprecision::detail::expression<tagb, Arg1b, Arg2b, Arg3b, Arg4b>;
+ using number2_t = typename expression2_t::result_type ;
};
-}}} // namespace
+}}} // namespace boost::numeric::ublas
#endif
-
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/integer.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/integer.hpp
new file mode 100644
index 0000000000..2873b730a6
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/integer.hpp
@@ -0,0 +1,363 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2012-21 John Maddock.
+// Copyright 2021 Iskandarov Lev. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_MP_INTEGER_HPP
+#define BOOST_MP_INTEGER_HPP
+
+#include <type_traits>
+#include <boost/multiprecision/cpp_int.hpp>
+#include <boost/multiprecision/detail/bitscan.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+namespace boost {
+namespace multiprecision {
+
+template <class Integer, class I2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value && boost::multiprecision::detail::is_integral<I2>::value, Integer&>::type
+multiply(Integer& result, const I2& a, const I2& b)
+{
+ return result = static_cast<Integer>(a) * static_cast<Integer>(b);
+}
+template <class Integer, class I2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value && boost::multiprecision::detail::is_integral<I2>::value, Integer&>::type
+add(Integer& result, const I2& a, const I2& b)
+{
+ return result = static_cast<Integer>(a) + static_cast<Integer>(b);
+}
+template <class Integer, class I2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value && boost::multiprecision::detail::is_integral<I2>::value, Integer&>::type
+subtract(Integer& result, const I2& a, const I2& b)
+{
+ return result = static_cast<Integer>(a) - static_cast<Integer>(b);
+}
+
+template <class Integer>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value>::type divide_qr(const Integer& x, const Integer& y, Integer& q, Integer& r)
+{
+ q = x / y;
+ r = x % y;
+}
+
+template <class I1, class I2>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I1>::value && boost::multiprecision::detail::is_integral<I2>::value, I2>::type integer_modulus(const I1& x, I2 val)
+{
+ return static_cast<I2>(x % val);
+}
+
+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 long long),
+// otherwise synthesize a cpp_int to do the job.
+//
+template <class I>
+struct double_integer
+{
+ static constexpr const unsigned int_t_digits =
+ 2 * sizeof(I) <= sizeof(long long) ? std::numeric_limits<I>::digits * 2 : 1;
+
+ using type = typename std::conditional<
+ 2 * sizeof(I) <= sizeof(long long),
+ typename std::conditional<
+ boost::multiprecision::detail::is_signed<I>::value && boost::multiprecision::detail::is_integral<I>::value,
+ typename boost::multiprecision::detail::int_t<int_t_digits>::least,
+ typename boost::multiprecision::detail::uint_t<int_t_digits>::least>::type,
+ typename std::conditional<
+ 2 * sizeof(I) <= sizeof(double_limb_type),
+ typename std::conditional<
+ boost::multiprecision::detail::is_signed<I>::value && boost::multiprecision::detail::is_integral<I>::value,
+ signed_double_limb_type,
+ double_limb_type>::type,
+ number<cpp_int_backend<sizeof(I) * CHAR_BIT * 2, sizeof(I) * CHAR_BIT * 2, (boost::multiprecision::detail::is_signed<I>::value ? signed_magnitude : unsigned_magnitude), unchecked, void> > >::type>::type;
+};
+
+} // namespace detail
+
+template <class I1, class I2, class I3>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I1>::value && boost::multiprecision::detail::is_unsigned<I2>::value && boost::multiprecision::detail::is_integral<I3>::value, I1>::type
+powm(const I1& a, I2 b, I3 c)
+{
+ using double_type = typename detail::double_integer<I1>::type;
+
+ I1 x(1), y(a);
+ double_type result(0);
+
+ 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 <class I1, class I2, class I3>
+inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I1>::value && boost::multiprecision::detail::is_signed<I2>::value && boost::multiprecision::detail::is_integral<I2>::value && boost::multiprecision::detail::is_integral<I3>::value, I1>::type
+powm(const I1& a, I2 b, I3 c)
+{
+ if (b < 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
+ }
+ return powm(a, static_cast<typename boost::multiprecision::detail::make_unsigned<I2>::type>(b), c);
+}
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value, std::size_t>::type lsb(const Integer& val)
+{
+ if (val <= 0)
+ {
+ if (val == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
+ }
+ else
+ {
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
+ }
+ }
+ return detail::find_lsb(val);
+}
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value, std::size_t>::type msb(Integer val)
+{
+ if (val <= 0)
+ {
+ if (val == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
+ }
+ else
+ {
+ BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
+ }
+ }
+ return detail::find_msb(val);
+}
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value, bool>::type bit_test(const Integer& val, std::size_t index)
+{
+ Integer mask = 1;
+ if (index >= sizeof(Integer) * CHAR_BIT)
+ return 0;
+ if (index)
+ mask <<= index;
+ return val & mask ? true : false;
+}
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value, Integer&>::type bit_set(Integer& val, std::size_t index)
+{
+ Integer mask = 1;
+ if (index >= sizeof(Integer) * CHAR_BIT)
+ return val;
+ if (index)
+ mask <<= index;
+ val |= mask;
+ return val;
+}
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value, Integer&>::type bit_unset(Integer& val, std::size_t index)
+{
+ Integer mask = 1;
+ if (index >= sizeof(Integer) * CHAR_BIT)
+ return val;
+ if (index)
+ mask <<= index;
+ val &= ~mask;
+ return val;
+}
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value, Integer&>::type bit_flip(Integer& val, std::size_t index)
+{
+ Integer mask = 1;
+ if (index >= sizeof(Integer) * CHAR_BIT)
+ return val;
+ if (index)
+ mask <<= index;
+ val ^= mask;
+ return val;
+}
+
+namespace detail {
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR Integer karatsuba_sqrt(const Integer& x, Integer& r, size_t bits)
+{
+ //
+ // Define the floating point type used for std::sqrt, in our tests, sqrt(double) and sqrt(long double) take
+ // about the same amount of time as long as long double is not an emulated 128-bit type (ie the same type
+ // as __float128 from libquadmath). So only use long double if it's an 80-bit type:
+ //
+#ifndef __clang__
+ typedef typename std::conditional<(std::numeric_limits<long double>::digits == 64), long double, double>::type real_cast_type;
+#else
+ // clang has buggy __int128 -> long double conversion:
+ typedef double real_cast_type;
+#endif
+ //
+ // As per the Karatsuba sqrt algorithm, the low order bits/4 bits pay no part in the result, only in the remainder,
+ // so define the number of bits our argument must have before passing to std::sqrt is safe, even if doing so
+ // looses a few bits:
+ //
+ constexpr std::size_t cutoff = (std::numeric_limits<real_cast_type>::digits * 4) / 3;
+ //
+ // Type which can hold at least "cutoff" bits:
+ //
+#ifdef BOOST_HAS_INT128
+ using cutoff_t = typename std::conditional<(cutoff > 64), uint128_type, std::uint64_t>::type;
+#else
+ using cutoff_t = std::uint64_t;
+#endif
+ //
+ // See if we can take the fast path:
+ //
+ if (bits <= cutoff)
+ {
+ constexpr cutoff_t half_bits = (cutoff_t(1u) << ((sizeof(cutoff_t) * CHAR_BIT) / 2)) - 1;
+ cutoff_t val = static_cast<cutoff_t>(x);
+ real_cast_type real_val = static_cast<real_cast_type>(val);
+ cutoff_t s64 = static_cast<cutoff_t>(std::sqrt(real_val));
+ // converting to long double can loose some precision, and `sqrt` can give eps error, so we'll fix this
+ // this is needed
+ while ((s64 > half_bits) || (s64 * s64 > val))
+ s64--;
+ // in my tests this never fired, but theoretically this might be needed
+ while ((s64 < half_bits) && ((s64 + 1) * (s64 + 1) <= val))
+ s64++;
+ r = static_cast<Integer>(val - s64 * s64);
+ return static_cast<Integer>(s64);
+ }
+ // https://hal.inria.fr/file/index/docid/72854/filename/RR-3805.pdf
+ std::size_t b = bits / 4;
+ Integer q = x;
+ q >>= b * 2;
+ Integer s = karatsuba_sqrt(q, r, bits - b * 2);
+ Integer t = 0u;
+ bit_set(t, static_cast<unsigned>(b * 2));
+ r <<= b;
+ t--;
+ t &= x;
+ t >>= b;
+ t += r;
+ s <<= 1;
+ divide_qr(t, s, q, r);
+ r <<= b;
+ t = 0u;
+ bit_set(t, static_cast<unsigned>(b));
+ t--;
+ t &= x;
+ r += t;
+ s <<= (b - 1); // we already <<1 it before
+ s += q;
+ q *= q;
+ // we substract after, so it works for unsigned integers too
+ if (r < q)
+ {
+ t = s;
+ t <<= 1;
+ t--;
+ r += t;
+ s--;
+ }
+ r -= q;
+ return s;
+}
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR Integer bitwise_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;
+ switch (x)
+ {
+ case 0:
+ r = 0;
+ return s;
+ case 1:
+ r = 0;
+ return 1;
+ case 2:
+ r = 1;
+ return 1;
+ case 3:
+ r = 2;
+ return 1;
+ default:
+ break;
+ // fall through:
+ }
+ std::ptrdiff_t g = msb(x);
+
+ 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;
+}
+
+} // namespace detail
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value, Integer>::type sqrt(const Integer& x, Integer& r)
+{
+#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
+ // recursive Karatsuba sqrt can cause issues in constexpr context:
+ if (BOOST_MP_IS_CONST_EVALUATED(x))
+ {
+ return detail::bitwise_sqrt(x, r);
+ }
+#endif
+ if (x == 0u) {
+ r = 0u;
+ return 0u;
+ }
+
+ return detail::karatsuba_sqrt(x, r, msb(x) + 1);
+}
+
+template <class Integer>
+BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Integer>::value, Integer>::type sqrt(const Integer& x)
+{
+ Integer r(0);
+ return sqrt(x, r);
+}
+
+}} // namespace boost::multiprecision
+
+#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/number.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/number.hpp
index f99ef2a970..c6e8167c2e 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/number.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/number.hpp
@@ -3,226 +3,505 @@
// 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_MATH_EXTENDED_REAL_HPP
-#define BOOST_MATH_EXTENDED_REAL_HPP
-
-#include <boost/cstdint.hpp>
-#include <boost/mpl/max.hpp>
-#include <boost/mpl/plus.hpp>
-#include <boost/mpl/or.hpp>
-#include <boost/mpl/find_if.hpp>
-#include <boost/assert.hpp>
-#include <boost/type_traits/remove_pointer.hpp>
-#include <boost/type_traits/is_signed.hpp>
-#include <boost/type_traits/is_unsigned.hpp>
-#include <boost/type_traits/is_floating_point.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#include <boost/type_traits/make_unsigned.hpp>
-#include <boost/throw_exception.hpp>
+#ifndef BOOST_MP_NUMBER_HPP
+#define BOOST_MP_NUMBER_HPP
+
+#include <cstdint>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/precision.hpp>
#include <boost/multiprecision/detail/generic_interconvert.hpp>
#include <boost/multiprecision/detail/number_compare.hpp>
#include <boost/multiprecision/traits/is_restricted_conversion.hpp>
-#include <istream> // stream operators
-#include <cstdio> // EOF
-#include <cctype> // isspace
+#include <boost/multiprecision/traits/is_complex.hpp>
+#include <boost/multiprecision/traits/is_convertible_arithmetic.hpp>
+#include <boost/multiprecision/detail/hash.hpp>
+#include <boost/multiprecision/detail/number_base.hpp>
+#include <istream> // stream operators
+#include <cstdio> // EOF
+#include <cctype> // isspace
+#include <functional> // std::hash
+#include <type_traits>
+#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
+#include <string_view>
+#endif
+
+#ifndef BOOST_MP_STANDALONE
+#include <boost/core/nvp.hpp>
+#endif
-namespace boost{ namespace multiprecision{
+namespace boost {
+namespace multiprecision {
#ifdef BOOST_MSVC
// warning C4127: conditional expression is constant
// warning C4714: function marked as __forceinline not inlined
#pragma warning(push)
-#pragma warning(disable:4127 4714 6326)
+#pragma warning(disable : 4127 4714 6326)
#endif
template <class Backend, expression_template_option ExpressionTemplates>
class number
{
- typedef number<Backend, ExpressionTemplates> self_type;
-public:
- typedef Backend backend_type;
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number() BOOST_MP_NOEXCEPT_IF(noexcept(Backend())) {}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(e.m_backend){}
+ using self_type = number<Backend, ExpressionTemplates>;
+
+ public:
+ using backend_type = Backend ;
+ using value_type = typename component_type<self_type>::type;
+
+ static constexpr expression_template_option et = ExpressionTemplates;
+
+ BOOST_MP_FORCEINLINE constexpr number() noexcept(noexcept(Backend())) {}
+ BOOST_MP_FORCEINLINE constexpr number(const number& e) noexcept(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(e.m_backend) {}
template <class V>
- BOOST_MP_FORCEINLINE number(const V& v, typename boost::enable_if_c<
- (boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value)
- && !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
- && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
-#ifdef BOOST_HAS_FLOAT128
- && !boost::is_same<V, __float128>::value
-#endif
- >::type* = 0)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v,
+ typename std::enable_if<
+ (boost::multiprecision::detail::is_convertible_arithmetic<V, Backend>::value
+ || std::is_same<std::string, V>::value
+ || std::is_convertible<V, const char*>::value)
+ && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
+ && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
{
m_backend = canonical_value(v);
}
template <class V>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<
- is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
- && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
- >::type* = 0)
+ BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
+ std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
#ifndef BOOST_INTEL
- BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
+ noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
#endif
- : m_backend(canonical_value(v)) {}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e, unsigned digits10)
- BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend const&>(), std::declval<unsigned>())))
- : m_backend(e.m_backend, digits10){}
- template <class V>
- explicit BOOST_MP_FORCEINLINE number(const V& v, typename boost::enable_if_c<
- (boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value)
- && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
- && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
- >::type* = 0)
- BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<typename detail::canonical<V, Backend>::type const&>()))
- {
- m_backend = canonical_value(v);
- }
+ : m_backend(canonical_value(v))
+ {}
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE constexpr number(const V& v, U digits10,
+ typename std::enable_if<
+ (boost::multiprecision::detail::is_convertible_arithmetic<V, Backend>::value
+ || std::is_same<std::string, V>::value
+ || std::is_convertible<V, const char*>::value)
+ && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
+ && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex)
+ && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)
+ && std::is_same<self_type, value_type>::value
+ && std::is_integral<U>::value
+ && (std::numeric_limits<U>::digits <= std::numeric_limits<unsigned>::digits)
+ && std::is_constructible<Backend, typename detail::canonical<V, Backend>::type const&, unsigned>::value>::type* = nullptr)
+ : m_backend(canonical_value(v), static_cast<unsigned>(digits10))
+ {}
+ //
+ // Conversions from unscoped enum's are implicit:
+ //
template <class V>
- explicit BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<
- detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
- && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
- || !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)
- >::type* = 0)
- BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
- : m_backend(canonical_value(v)) {}
- /*
+ BOOST_MP_FORCEINLINE
+#if !(defined(BOOST_MSVC) && (BOOST_MSVC <= 1900))
+ constexpr
+#endif
+ number(const V& v, typename std::enable_if<
+ std::is_enum<V>::value && std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
+ : number(static_cast<typename std::underlying_type<V>::type>(v))
+ {}
//
- // This conflicts with component based initialization (for rational and complex types)
- // which is arguably more useful. Disabled for now.
+ // Conversions from scoped enum's are explicit:
//
template <class V>
- number(V v, unsigned digits10, typename boost::enable_if<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > >::type* dummy1 = 0)
+ BOOST_MP_FORCEINLINE explicit
+#if !(defined(BOOST_MSVC) && (BOOST_MSVC <= 1900))
+ constexpr
+#endif
+ number(const V& v, typename std::enable_if<
+ std::is_enum<V>::value && !std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
+ : number(static_cast<typename std::underlying_type<V>::type>(v))
+ {}
+
+ template <class U>
+ BOOST_MP_FORCEINLINE constexpr number(const number& e, U digits10, typename std::enable_if<std::is_constructible<Backend, const Backend&, unsigned>::value && std::is_integral<U>::value && (std::numeric_limits<U>::digits <= std::numeric_limits<unsigned>::digits)>::type* = nullptr)
+ noexcept(noexcept(Backend(std::declval<Backend const&>(), std::declval<unsigned>())))
+ : m_backend(e.m_backend, static_cast<unsigned>(digits10)) {}
+ template <class V>
+ explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename std::enable_if<
+ (boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
+ noexcept(noexcept(std::declval<Backend&>() = std::declval<typename detail::canonical<V, Backend>::type const&>()))
{
- m_backend.precision(digits10);
m_backend = canonical_value(v);
}
- */
- template<expression_template_option ET>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number<Backend, ET>& val)
- BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(val.backend()) {}
+ template <class V>
+ explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
+ detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value || !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)>::type* = nullptr)
+ noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
+ : m_backend(canonical_value(v)) {}
+ template <class V>
+ explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, unsigned digits10, typename std::enable_if<(boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)>::type* = nullptr)
+ : m_backend(canonical_value(v), digits10) {}
+
+ template <expression_template_option ET>
+ BOOST_MP_FORCEINLINE constexpr number(const number<Backend, ET>& val)
+ noexcept(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(val.backend()) {}
template <class Other, expression_template_option ET>
- BOOST_MP_FORCEINLINE number(const number<Other, ET>& val,
- typename boost::enable_if_c<(boost::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = 0)
- BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Other const&>())))
- : m_backend(val.backend()) {}
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val,
+ typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = nullptr)
+ noexcept(noexcept(Backend(std::declval<Other const&>())))
+ : m_backend(val.backend()) {}
template <class Other, expression_template_option ET>
- explicit number(const number<Other, ET>& val, typename boost::enable_if_c<
- (!detail::is_explicitly_convertible<Other, Backend>::value)
- >::type* = 0)
+ explicit BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
+ (!detail::is_explicitly_convertible<Other, Backend>::value)>::type* = nullptr)
{
//
// Attempt a generic interconvertion:
//
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard_1(val);
+ detail::scoped_default_precision<number<Other, ET> > precision_guard_2(val);
using detail::generic_interconvert;
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ {
+ if (precision_guard_1.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ self_type t;
+ generic_interconvert(t.backend(), val.backend(), number_category<Backend>(), number_category<Other>());
+ *this = std::move(t);
+ return;
+ }
+ }
generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
}
template <class Other, expression_template_option ET>
- explicit BOOST_MP_FORCEINLINE number(const number<Other, ET>& val, typename boost::enable_if_c<
- (detail::is_explicitly_convertible<Other, Backend>::value
- && (detail::is_restricted_conversion<Other, Backend>::value || !boost::is_convertible<Other, Backend>::value))
- >::type* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Other const&>())))
- : m_backend(val.backend()) {}
-
- template <class V>
- BOOST_MP_FORCEINLINE number(V v1, V v2, typename boost::enable_if<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > >::type* = 0)
+ explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
+ (detail::is_explicitly_convertible<Other, Backend>::value && (detail::is_restricted_conversion<Other, Backend>::value || !std::is_convertible<Other, Backend>::value))>::type* = nullptr) noexcept(noexcept(Backend(std::declval<Other const&>())))
+ : m_backend(val.backend()) {}
+
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
+ : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)))
+ {
+ }
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(V&& v1, const U& v2,
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
+ : m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(v2)))
+ {
+ }
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, U&& v2,
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
+ : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
+ {
+ }
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(V&& v1, U&& v2,
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
+ : m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
+ {
+ }
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && (!std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ || boost::multiprecision::detail::is_variable_precision<Backend>::value))>::type* = nullptr)
+ {
+ using default_ops::assign_components;
+ // Copy precision options from this type to component_type:
+ boost::multiprecision::detail::scoped_precision_options<value_type> scoped_opts(*this);
+ // precision guards:
+ detail::scoped_default_precision<self_type> precision_guard(v1, v2, *this);
+ detail::scoped_default_precision<value_type> component_precision_guard(v1, v2, *this);
+ assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
+ }
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
+ typename std::enable_if<
+ (std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value && !std::is_same<V, self_type>::value && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = nullptr)
{
using default_ops::assign_components;
- assign_components(m_backend, canonical_value(v1), canonical_value(v2));
+ // Copy precision options from this type to component_type:
+ boost::multiprecision::detail::scoped_precision_options<value_type> scoped_opts(*this);
+ // precision guards:
+ detail::scoped_default_precision<self_type> precision_guard(v1, v2, *this);
+ detail::scoped_default_precision<value_type> component_precision_guard(v1, v2, *this);
+ assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
+ }
+#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
+ //
+ // Support for new types in C++17
+ //
+ template <class Traits>
+ explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view)
+ {
+ using default_ops::assign_from_string_view;
+ assign_from_string_view(this->backend(), view);
+ }
+ template <class Traits>
+ explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& view_y)
+ {
+ using default_ops::assign_from_string_view;
+ assign_from_string_view(this->backend(), view_x, view_y);
+ }
+ template <class Traits>
+ explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& v, unsigned digits10)
+ : m_backend(canonical_value(v), digits10) {}
+ template <class Traits>
+ BOOST_MP_CXX14_CONSTEXPR number& assign(const std::basic_string_view<char, Traits>& view)
+ {
+ using default_ops::assign_from_string_view;
+ assign_from_string_view(this->backend(), view);
+ return *this;
}
+#endif
+
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
+ typename std::enable_if<(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value && !std::is_same<value_type, self_type>::value)>::type* = nullptr)
+ : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10)
+ {}
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
+ typename std::enable_if<((std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value) && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = nullptr)
+ : m_backend(detail::evaluate_if_expression(v1), detail::evaluate_if_expression(v2), digits10) {}
+
template <class Other, expression_template_option ET>
- BOOST_MP_FORCEINLINE number(const number<Other, ET>& v1, const number<Other, ET>& v2, typename boost::enable_if<boost::is_convertible<Other, Backend> >::type* = 0)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(
+ const number<Other, ET>& v1,
+ const number<Other, ET>& v2,
+ typename std::enable_if<
+ std::is_convertible<Other, Backend>::value
+ && (!std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&>::value || boost::multiprecision::detail::is_variable_precision<Backend>::value) >::type* = nullptr)
{
using default_ops::assign_components;
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);
assign_components(m_backend, v1.backend(), v2.backend());
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
- typedef typename is_same<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::type tag_type;
+ using tag_type = std::integral_constant<bool, is_equivalent_number_type<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>;
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(e);
+ //
+ // If the current precision of *this differs from that of expression e, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_IF_CONSTEXPR (std::is_same<self_type, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
+ {
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(e);
+ return *this = std::move(t);
+ }
+ }
do_assign(e, tag_type());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
- typedef typename is_same<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::type tag_type;
+ using tag_type = std::integral_constant<bool, is_equivalent_number_type<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>;
+
+ //
+ // If the current precision of *this differs from that of expression e, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
+ {
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ {
+ const detail::scoped_default_precision<number<Backend, ExpressionTemplates>> precision_guard(e);
+
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t;
+ t.assign(e);
+ return *this = std::move(t);
+ }
+ }
+ }
do_assign(e, tag_type());
return *this;
}
+ BOOST_MP_CXX14_CONSTEXPR number& assign(const value_type& a, const value_type& b)
+ {
+ assign_components(backend(), a.backend(), b.backend());
+ return *this;
+ }
+ template <class V, class U>
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(std::is_convertible<V, value_type>::value&& std::is_convertible<U, value_type>::value && !std::is_same<value_type, self_type>::value), number&>::type
+ assign(const V& v1, const U& v2, unsigned Digits)
+ {
+ self_type r(v1, v2, Digits);
+ boost::multiprecision::detail::scoped_source_precision<self_type> scope;
+ return *this = r;
+ }
+ BOOST_MP_CXX14_CONSTEXPR number& assign(const value_type & a, const value_type & b, unsigned Digits)
+ {
+ this->precision(Digits);
+ boost::multiprecision::detail::scoped_target_precision<self_type> scoped;
+ assign_components(backend(), canonical_value(detail::evaluate_if_expression(a)), canonical_value(detail::evaluate_if_expression(b)));
+ return *this;
+ }
- BOOST_MP_FORCEINLINE number& operator=(const number& e)
- BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<Backend const&>()))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(const number& e)
+ noexcept(noexcept(std::declval<Backend&>() = std::declval<Backend const&>()))
{
m_backend = e.m_backend;
return *this;
}
template <class V>
- BOOST_MP_FORCEINLINE typename boost::enable_if<is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
- operator=(const V& v)
- BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
+ operator=(const V& v)
+ noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
{
m_backend = canonical_value(v);
return *this;
}
template <class V>
- BOOST_MP_FORCEINLINE number<Backend, ExpressionTemplates>& assign(const V& v)
- BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v)
+ noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
{
m_backend = canonical_value(v);
return *this;
}
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v, const U& digits10_or_component)
+ noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
+ {
+ number t(v, digits10_or_component);
+ boost::multiprecision::detail::scoped_source_precision<self_type> scope;
+ static_cast<void>(scope);
+ return *this = t;
+ }
template <class Other, expression_template_option ET>
- typename boost::disable_if<boost::multiprecision::detail::is_explicitly_convertible<Other, Backend>, number<Backend, ExpressionTemplates>& >::type
- assign(const number<Other, ET>& v)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!boost::multiprecision::detail::is_explicitly_convertible<Other, Backend>::value, number<Backend, ExpressionTemplates>&>::type
+ assign(const number<Other, ET>& v)
{
//
// Attempt a generic interconvertion:
//
using detail::generic_interconvert;
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
+ detail::scoped_default_precision<number<Other, ET> > precision_guard2(*this, v);
+ //
+ // If the current precision of *this differs from that of value v, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(v);
+ return *this = std::move(t);
+ }
generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
+ BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = nullptr)
{
+ //
+ // No preicsion guard here, we already have one in operator=
+ //
*this = e;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- explicit number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e,
- typename boost::enable_if_c<!is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value
- && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
+ explicit BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e,
+ typename std::enable_if<!std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = nullptr)
{
+ //
+ // No precision guard as assign has one already:
+ //
assign(e);
}
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(number&& r)
- BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend>())))
- : m_backend(static_cast<Backend&&>(r.m_backend)){}
- BOOST_MP_FORCEINLINE number& operator=(number&& r) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<Backend>()))
+ // rvalues:
+ BOOST_MP_FORCEINLINE constexpr number(number&& r)
+ noexcept(noexcept(Backend(std::declval<Backend>())))
+ : m_backend(static_cast<Backend&&>(r.m_backend))
+ {}
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(number&& r) noexcept(noexcept(std::declval<Backend&>() = std::declval<Backend>()))
{
m_backend = static_cast<Backend&&>(r.m_backend);
return *this;
}
-#endif
+ template <class Other, expression_template_option ET>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(number<Other, ET>&& val,
+ typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = nullptr)
+ noexcept(noexcept(Backend(std::declval<Other const&>())))
+ : m_backend(static_cast<number<Other, ET>&&>(val).backend()) {}
+ template <class Other, expression_template_option ET>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value), number&>::type
+ operator=(number<Other, ET>&& val)
+ noexcept(noexcept(Backend(std::declval<Other const&>())))
+ {
+ m_backend = std::move(val).backend();
+ return *this;
+ }
- number& operator+=(const self_type& val)
+ BOOST_MP_CXX14_CONSTEXPR number& operator+=(const self_type& val)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);
+ //
+ // If the current precision of *this differs from that of expression e, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this + val);
+ return *this = std::move(t);
+ }
do_add(detail::expression<detail::terminal, self_type>(val), detail::terminal());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
// Create a copy if e contains this, but not if we're just doing a
// x += x
- if(contains_self(e) && !is_self(e))
+ if ((contains_self(e) && !is_self(e)))
{
self_type temp(e);
do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
@@ -235,8 +514,27 @@ public:
}
template <class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator+=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR number& operator+=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
+ //
+ // If the current precision of *this differs from that of expression e, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
+ {
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this + e);
+ return *this = std::move(t);
+ }
+ }
//
// Fused multiply-add:
//
@@ -246,25 +544,59 @@ public:
}
template <class V>
- typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
- operator+=(const V& v)
+ typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
+ BOOST_MP_CXX14_CONSTEXPR operator+=(const V& v)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
+ //
+ // If the current precision of *this differs from that of value v, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this + v);
+ return *this = std::move(t);
+ }
+
using default_ops::eval_add;
eval_add(m_backend, canonical_value(v));
return *this;
}
- number& operator-=(const self_type& val)
+ BOOST_MP_CXX14_CONSTEXPR number& operator-=(const self_type& val)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);
+ //
+ // If the current precision of *this differs from that of expression e, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this - val);
+ return *this = std::move(t);
+ }
do_subtract(detail::expression<detail::terminal, self_type>(val), detail::terminal());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
// Create a copy if e contains this:
- if(contains_self(e))
+ if (contains_self(e))
{
self_type temp(e);
do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
@@ -277,17 +609,53 @@ public:
}
template <class V>
- typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
- operator-=(const V& v)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
+ operator-=(const V& v)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
+ //
+ // If the current precision of *this differs from that of value v, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this - v);
+ return *this = std::move(t);
+ }
+
using default_ops::eval_subtract;
eval_subtract(m_backend, canonical_value(v));
return *this;
}
template <class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator-=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR number& operator-=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
+ //
+ // If the current precision of *this differs from that of expression e, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
+ {
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this - e);
+ return *this = std::move(t);
+ }
+ }
//
// Fused multiply-subtract:
//
@@ -296,19 +664,35 @@ public:
return *this;
}
-
- number& operator *= (const self_type& e)
+ BOOST_MP_CXX14_CONSTEXPR number& operator*=(const self_type& e)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
+ //
+ // If the current precision of *this differs from that of expression e, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this * e);
+ return *this = std::move(t);
+ }
do_multiplies(detail::expression<detail::terminal, self_type>(e), detail::terminal());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
// Create a temporary if the RHS references *this, but not
// if we're just doing an x *= x;
- if(contains_self(e) && !is_self(e))
+ if ((contains_self(e) && !is_self(e)))
{
self_type temp(e);
do_multiplies(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
@@ -321,26 +705,60 @@ public:
}
template <class V>
- typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
- operator*=(const V& v)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
+ operator*=(const V& v)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
+ //
+ // If the current precision of *this differs from that of value v, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this * v);
+ return *this = std::move(t);
+ }
+
using default_ops::eval_multiply;
eval_multiply(m_backend, canonical_value(v));
return *this;
}
- number& operator%=(const self_type& e)
+ BOOST_MP_CXX14_CONSTEXPR number& operator%=(const self_type& e)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
+ //
+ // If the current precision of *this differs from that of expression e, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this % e);
+ return *this = std::move(t);
+ }
do_modulus(detail::expression<detail::terminal, self_type>(e), detail::terminal());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
// Create a temporary if the RHS references *this:
- if(contains_self(e))
+ if (contains_self(e))
{
self_type temp(e);
do_modulus(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
@@ -352,10 +770,10 @@ public:
return *this;
}
template <class V>
- typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
- operator%=(const V& v)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
+ operator%=(const V& v)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
using default_ops::eval_modulus;
eval_modulus(m_backend, canonical_value(v));
return *this;
@@ -369,65 +787,82 @@ public:
// execute the increment/decrement on destruction, but
// correct implementation will be tricky, so defered for now...
//
- BOOST_MP_FORCEINLINE number& operator++()
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator++()
{
using default_ops::eval_increment;
eval_increment(m_backend);
return *this;
}
- BOOST_MP_FORCEINLINE number& operator--()
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator--()
{
using default_ops::eval_decrement;
eval_decrement(m_backend);
return *this;
}
- inline number operator++(int)
+ inline BOOST_MP_CXX14_CONSTEXPR number operator++(int)
{
using default_ops::eval_increment;
self_type temp(*this);
eval_increment(m_backend);
- return BOOST_MP_MOVE(temp);
+ return temp;
}
- inline number operator--(int)
+ inline BOOST_MP_CXX14_CONSTEXPR number operator--(int)
{
using default_ops::eval_decrement;
self_type temp(*this);
eval_decrement(m_backend);
- return BOOST_MP_MOVE(temp);
+ return temp;
}
template <class V>
- BOOST_MP_FORCEINLINE typename boost::enable_if<is_integral<V>, number&>::type operator <<= (V val)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<V>::value, number&>::type operator<<=(V val)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left-shift operation is only valid for integer types");
- detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), is_signed<V>());
+ static_assert(number_category<Backend>::value == number_kind_integer, "The left-shift operation is only valid for integer types");
+ detail::check_shift_range(val, std::integral_constant<bool, (sizeof(V) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<V>::value && boost::multiprecision::detail::is_integral<V>::value > ());
eval_left_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
return *this;
}
template <class V>
- BOOST_MP_FORCEINLINE typename boost::enable_if<is_integral<V>, number&>::type operator >>= (V val)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<V>::value, number&>::type operator>>=(V val)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right-shift operation is only valid for integer types");
- detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), is_signed<V>());
+ static_assert(number_category<Backend>::value == number_kind_integer, "The right-shift operation is only valid for integer types");
+ detail::check_shift_range(val, std::integral_constant<bool, (sizeof(V) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<V>::value && boost::multiprecision::detail::is_integral<V>::value>());
eval_right_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
return *this;
}
- BOOST_MP_FORCEINLINE number& operator /= (const self_type& e)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator/=(const self_type& e)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
+ //
+ // If the current precision of *this differs from that of expression e, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this / e);
+ return *this = std::move(t);
+ }
do_divide(detail::expression<detail::terminal, self_type>(e), detail::terminal());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
// Create a temporary if the RHS references *this:
- if(contains_self(e))
+ if (contains_self(e))
{
self_type temp(e);
do_divide(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
@@ -440,28 +875,45 @@ public:
}
template <class V>
- BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
- operator/=(const V& v)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
+ operator/=(const V& v)
{
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
+ //
+ // If the current precision of *this differs from that of value v, then we
+ // create a temporary (which will have the correct precision thanks to precision_guard)
+ // and then move the result into *this. In C++17 we add a leading "if constexpr"
+ // which causes this code to be eliminated in the common case that this type is
+ // not actually variable precision. Pre C++17 this code should still be mostly
+ // optimised away, but we can't prevent instantiation of the dead code leading
+ // to longer build and possibly link times.
+ //
+ BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ number t(*this / v);
+ return *this = std::move(t);
+ }
+
using default_ops::eval_divide;
eval_divide(m_backend, canonical_value(v));
return *this;
}
- BOOST_MP_FORCEINLINE number& operator&=(const self_type& e)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator&=(const self_type& e)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
do_bitwise_and(detail::expression<detail::terminal, self_type>(e), detail::terminal());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
// Create a temporary if the RHS references *this, but not
// if we're just doing an x &= x;
- if(contains_self(e) && !is_self(e))
+ if (contains_self(e) && !is_self(e))
{
self_type temp(e);
do_bitwise_and(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
@@ -474,29 +926,29 @@ public:
}
template <class V>
- BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
- operator&=(const V& v)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
+ operator&=(const V& v)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
using default_ops::eval_bitwise_and;
eval_bitwise_and(m_backend, canonical_value(v));
return *this;
}
- BOOST_MP_FORCEINLINE number& operator|=(const self_type& e)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator|=(const self_type& e)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
do_bitwise_or(detail::expression<detail::terminal, self_type>(e), detail::terminal());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
// Create a temporary if the RHS references *this, but not
// if we're just doing an x |= x;
- if(contains_self(e) && !is_self(e))
+ if (contains_self(e) && !is_self(e))
{
self_type temp(e);
do_bitwise_or(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
@@ -509,27 +961,27 @@ public:
}
template <class V>
- BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
- operator|=(const V& v)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
+ operator|=(const V& v)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
using default_ops::eval_bitwise_or;
eval_bitwise_or(m_backend, canonical_value(v));
return *this;
}
- BOOST_MP_FORCEINLINE number& operator^=(const self_type& e)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator^=(const self_type& e)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
do_bitwise_xor(detail::expression<detail::terminal, self_type>(e), detail::terminal());
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
- if(contains_self(e))
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
+ if (contains_self(e))
{
self_type temp(e);
do_bitwise_xor(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
@@ -542,10 +994,10 @@ public:
}
template <class V>
- BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
- operator^=(const V& v)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
+ operator^=(const V& v)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
using default_ops::eval_bitwise_xor;
eval_bitwise_xor(m_backend, canonical_value(v));
return *this;
@@ -553,19 +1005,19 @@ public:
//
// swap:
//
- BOOST_MP_FORCEINLINE void swap(self_type& other) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend>().swap(std::declval<Backend&>())))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(self_type& other) noexcept(noexcept(std::declval<Backend>().swap(std::declval<Backend&>())))
{
m_backend.swap(other.backend());
}
//
// Zero and sign:
//
- BOOST_MP_FORCEINLINE bool is_zero()const
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool is_zero() const
{
using default_ops::eval_is_zero;
return eval_is_zero(m_backend);
}
- BOOST_MP_FORCEINLINE int sign()const
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int sign() const
{
using default_ops::eval_get_sign;
return eval_get_sign(m_backend);
@@ -573,219 +1025,282 @@ public:
//
// String conversion functions:
//
- std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0))const
+ std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0)) const
{
return m_backend.str(digits, f);
}
- template<class Archive>
- void serialize(Archive & ar, const unsigned int /*version*/)
+
+ #ifndef BOOST_MP_STANDALONE
+ template <class Archive>
+ void serialize(Archive& ar, const unsigned int /*version*/)
{
- ar & m_backend;
+ ar& boost::make_nvp("backend", m_backend);
}
-private:
+ #endif
+
+ private:
template <class T>
- void convert_to_imp(T* result)const
+ BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(T* result) const
{
using default_ops::eval_convert_to;
eval_convert_to(result, m_backend);
}
template <class B2, expression_template_option ET>
- void convert_to_imp(number<B2, ET>* result)const
+ BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(number<B2, ET>* result) const
{
result->assign(*this);
}
- void convert_to_imp(std::string* result)const
+ BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(std::string* result) const
{
*result = this->str();
}
-public:
+
+ public:
template <class T>
- T convert_to()const
+ BOOST_MP_CXX14_CONSTEXPR T convert_to() const
{
- T result;
+ T result = T();
convert_to_imp(&result);
return result;
}
//
// Use in boolean context, and explicit conversion operators:
//
-#ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
-# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) || (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 <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
- explicit operator T ()const
- {
- using default_ops::eval_is_zero;
- return !eval_is_zero(backend());
- }
- template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value, int>::type = 0>
- explicit operator T ()const
- {
- return this->template convert_to<T>();
- }
-# else
-#if BOOST_WORKAROUND(BOOST_MSVC, < 1900)
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1900) || (defined(__apple_build_version__) && BOOST_WORKAROUND(__clang_major__, < 9))
template <class T>
#else
- template <class T, class = typename boost::disable_if_c<boost::is_constructible<T, self_type const&>::value || !boost::is_default_constructible<T>::value, T>::type>
+ template <class T, class = typename std::enable_if<std::is_enum<T>::value || !(std::is_constructible<T, detail::convertible_to<self_type const&> >::value || !std::is_default_constructible<T>::value || (!boost::multiprecision::detail::is_arithmetic<T>::value && !boost::multiprecision::detail::is_complex<T>::value)), T>::type>
#endif
- explicit operator T ()const
+ explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
{
return this->template convert_to<T>();
}
- BOOST_MP_FORCEINLINE explicit operator bool()const
+ BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
{
return !is_zero();
}
-#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
- BOOST_MP_FORCEINLINE explicit operator void()const {}
-#endif
-# endif
-#else
- typedef bool (self_type::*unmentionable_type)()const;
-
- BOOST_MP_FORCEINLINE operator unmentionable_type()const
- {
- return is_zero() ? 0 : &self_type::is_zero;
- }
-#endif
//
// Default precision:
//
- static unsigned default_precision() BOOST_NOEXCEPT
+ static BOOST_MP_CXX14_CONSTEXPR unsigned default_precision() noexcept
{
return Backend::default_precision();
}
- static void default_precision(unsigned digits10)
+ static BOOST_MP_CXX14_CONSTEXPR void default_precision(unsigned digits10)
{
Backend::default_precision(digits10);
+ Backend::thread_default_precision(digits10);
+ }
+ static BOOST_MP_CXX14_CONSTEXPR unsigned thread_default_precision() noexcept
+ {
+ return Backend::thread_default_precision();
}
- unsigned precision()const BOOST_NOEXCEPT
+ static BOOST_MP_CXX14_CONSTEXPR void thread_default_precision(unsigned digits10)
+ {
+ Backend::thread_default_precision(digits10);
+ }
+ BOOST_MP_CXX14_CONSTEXPR unsigned precision() const noexcept
{
return m_backend.precision();
}
- void precision(unsigned digits10)
+ BOOST_MP_CXX14_CONSTEXPR void precision(unsigned digits10)
{
m_backend.precision(digits10);
}
//
+ // Variable precision options:
+ //
+ static constexpr variable_precision_options default_variable_precision_options()noexcept
+ {
+ return Backend::default_variable_precision_options();
+ }
+ static constexpr variable_precision_options thread_default_variable_precision_options()noexcept
+ {
+ return Backend::thread_default_variable_precision_options();
+ }
+ static BOOST_MP_CXX14_CONSTEXPR void default_variable_precision_options(variable_precision_options opts)
+ {
+ Backend::default_variable_precision_options(opts);
+ }
+ static BOOST_MP_CXX14_CONSTEXPR void thread_default_variable_precision_options(variable_precision_options opts)
+ {
+ Backend::thread_default_variable_precision_options(opts);
+ }
+ //
// Comparison:
//
- BOOST_MP_FORCEINLINE int compare(const number<Backend, ExpressionTemplates>& o)const
- BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend>().compare(std::declval<Backend>())))
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int compare(const number<Backend, ExpressionTemplates>& o) const
+ noexcept(noexcept(std::declval<Backend>().compare(std::declval<Backend>())))
{
return m_backend.compare(o.m_backend);
}
template <class V>
- BOOST_MP_FORCEINLINE typename boost::enable_if<is_arithmetic<V>, int>::type compare(const V& o)const
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value && (number_category<Backend>::value != number_kind_complex), int>::type compare(const V& o) const
{
using default_ops::eval_get_sign;
- if(o == 0)
+ if (o == 0)
return eval_get_sign(m_backend);
return m_backend.compare(canonical_value(o));
}
- BOOST_MP_FORCEINLINE Backend& backend() BOOST_NOEXCEPT
+ template <class V>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value && (number_category<Backend>::value == number_kind_complex), int>::type compare(const V& o) const
{
- return m_backend;
+ using default_ops::eval_get_sign;
+ return m_backend.compare(canonical_value(o));
}
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& backend()const BOOST_NOEXCEPT
+ //
+ // Direct access to the underlying backend:
+ //
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend& backend() & noexcept
{
return m_backend;
}
-private:
+ BOOST_MP_FORCEINLINE constexpr const Backend& backend() const& noexcept { return m_backend; }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend&& backend() && noexcept { return static_cast<Backend&&>(m_backend); }
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend const&& backend() const&& noexcept { return static_cast<Backend const&&>(m_backend); }
+ //
+ // Complex number real and imag:
+ //
+ BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type
+ real() const
+ {
+ using default_ops::eval_real;
+ detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);
+ typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result;
+ eval_real(result.backend(), backend());
+ return result;
+ }
+ BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type
+ imag() const
+ {
+ using default_ops::eval_imag;
+ detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);
+ typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result;
+ eval_imag(result.backend(), backend());
+ return result;
+ }
+ template <class T>
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T, self_type>::value, self_type&>::type real(const T& val)
+ {
+ using default_ops::eval_set_real;
+ eval_set_real(backend(), canonical_value(val));
+ return *this;
+ }
+ template <class T>
+ inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T, self_type>::value && number_category<self_type>::value == number_kind_complex, self_type&>::type imag(const T& val)
+ {
+ using default_ops::eval_set_imag;
+ eval_set_imag(backend(), canonical_value(val));
+ return *this;
+ }
+
+ private:
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const mpl::true_&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_assignable<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>::type
+ do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, false>&)
{
- do_assign(e, tag());
+ // The result of the expression isn't the same type as this -
+ // create a temporary result and assign it to *this:
+ using temp_type = typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
+ temp_type t(e);
+ *this = std::move(t);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const mpl::false_&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_assignable<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>::type
+ do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, false>&)
{
// The result of the expression isn't the same type as this -
// create a temporary result and assign it to *this:
- typedef typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type temp_type;
- temp_type t(e);
+ using temp_type = typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
+ temp_type t(e);
this->assign(t);
}
+ template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, true>&)
+ {
+ do_assign(e, tag());
+ }
template <class Exp>
- void do_assign(const Exp& e, const detail::add_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::add_immediates&)
{
using default_ops::eval_add;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_add(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::subtract_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::subtract_immediates&)
{
using default_ops::eval_subtract;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::multiply_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_immediates&)
{
using default_ops::eval_multiply;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_multiply(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::multiply_add&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_add&)
{
using default_ops::eval_multiply_add;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_multiply_add(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::multiply_subtract&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_subtract&)
{
using default_ops::eval_multiply_subtract;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_multiply_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::divide_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divide_immediates&)
{
using default_ops::eval_divide;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_divide(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::negate&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::negate&)
{
- typedef typename Exp::left_type left_type;
+ using left_type = typename Exp::left_type;
do_assign(e.left(), typename left_type::tag_type());
m_backend.negate();
}
template <class Exp>
- void do_assign(const Exp& e, const detail::plus&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::plus&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
- static int const left_depth = left_type::depth;
- static int const right_depth = right_type::depth;
+ constexpr int const left_depth = left_type::depth;
+ constexpr int const right_depth = right_type::depth;
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && br)
+ if (bl && br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
}
- else if(bl && is_self(e.left()))
+ else if (bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_add(e.right(), typename right_type::tag_type());
}
- else if(br && is_self(e.right()))
+ else if (br && is_self(e.right()))
{
// Ignore the right node, it's *this, just add the left:
do_add(e.left(), typename left_type::tag_type());
}
- else if(!br && (bl || (left_depth >= right_depth)))
+ else if (!br && (bl || (left_depth >= right_depth)))
{ // br is always false, but if bl is true we must take the this branch:
do_assign(e.left(), typename left_type::tag_type());
do_add(e.right(), typename right_type::tag_type());
@@ -797,34 +1312,34 @@ private:
}
}
template <class Exp>
- void do_assign(const Exp& e, const detail::minus&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::minus&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
- static int const left_depth = left_type::depth;
- static int const right_depth = right_type::depth;
+ constexpr int const left_depth = left_type::depth;
+ constexpr int const right_depth = right_type::depth;
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && br)
+ if (bl && br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
}
- else if(bl && is_self(e.left()))
+ else if (bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just subtract the right:
do_subtract(e.right(), typename right_type::tag_type());
}
- else if(br && is_self(e.right()))
+ else if (br && is_self(e.right()))
{
// Ignore the right node, it's *this, just subtract the left and negate the result:
do_subtract(e.left(), typename left_type::tag_type());
m_backend.negate();
}
- else if(!br && (bl || (left_depth >= right_depth)))
+ else if (!br && (bl || (left_depth >= right_depth)))
{ // br is always false, but if bl is true we must take the this branch:
do_assign(e.left(), typename left_type::tag_type());
do_subtract(e.right(), typename right_type::tag_type());
@@ -837,33 +1352,33 @@ private:
}
}
template <class Exp>
- void do_assign(const Exp& e, const detail::multiplies&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiplies&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
- static int const left_depth = left_type::depth;
- static int const right_depth = right_type::depth;
+ constexpr int const left_depth = left_type::depth;
+ constexpr int const right_depth = right_type::depth;
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && br)
+ if (bl && br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
}
- else if(bl && is_self(e.left()))
+ else if (bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_multiplies(e.right(), typename right_type::tag_type());
}
- else if(br && is_self(e.right()))
+ else if (br && is_self(e.right()))
{
// Ignore the right node, it's *this, just add the left:
do_multiplies(e.left(), typename left_type::tag_type());
}
- else if(!br && (bl || (left_depth >= right_depth)))
+ else if (!br && (bl || (left_depth >= right_depth)))
{ // br is always false, but if bl is true we must take the this branch:
do_assign(e.left(), typename left_type::tag_type());
do_multiplies(e.right(), typename right_type::tag_type());
@@ -875,20 +1390,20 @@ private:
}
}
template <class Exp>
- void do_assign(const Exp& e, const detail::divides&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divides&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && is_self(e.left()))
+ if (bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_divide(e.right(), typename right_type::tag_type());
}
- else if(br)
+ else if (br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
@@ -900,25 +1415,25 @@ private:
}
}
template <class Exp>
- void do_assign(const Exp& e, const detail::modulus&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus&)
{
//
// This operation is only valid for integer backends:
//
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && is_self(e.left()))
+ if (bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_modulus(e.right(), typename right_type::tag_type());
}
- else if(br)
+ else if (br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
@@ -930,40 +1445,41 @@ private:
}
}
template <class Exp>
- void do_assign(const Exp& e, const detail::modulus_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus_immediates&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
using default_ops::eval_modulus;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_modulus(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::bitwise_and&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and&)
{
//
// This operation is only valid for integer backends:
//
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
- static int const left_depth = left_type::depth;
- static int const right_depth = right_type::depth;
+ constexpr int const left_depth = left_type::depth;
+ constexpr int const right_depth = right_type::depth;
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && is_self(e.left()))
+ if (bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_bitwise_and(e.right(), typename right_type::tag_type());
}
- else if(br && is_self(e.right()))
+ else if (br && is_self(e.right()))
{
do_bitwise_and(e.left(), typename left_type::tag_type());
}
- else if(!br && (bl || (left_depth >= right_depth)))
+ else if (!br && (bl || (left_depth >= right_depth)))
{
do_assign(e.left(), typename left_type::tag_type());
do_bitwise_and(e.right(), typename right_type::tag_type());
@@ -975,40 +1491,40 @@ private:
}
}
template <class Exp>
- void do_assign(const Exp& e, const detail::bitwise_and_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and_immediates&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
using default_ops::eval_bitwise_and;
eval_bitwise_and(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::bitwise_or&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or&)
{
//
// This operation is only valid for integer backends:
//
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
- static int const left_depth = left_type::depth;
- static int const right_depth = right_type::depth;
+ constexpr int const left_depth = left_type::depth;
+ constexpr int const right_depth = right_type::depth;
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && is_self(e.left()))
+ if (bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_bitwise_or(e.right(), typename right_type::tag_type());
}
- else if(br && is_self(e.right()))
+ else if (br && is_self(e.right()))
{
do_bitwise_or(e.left(), typename left_type::tag_type());
}
- else if(!br && (bl || (left_depth >= right_depth)))
+ else if (!br && (bl || (left_depth >= right_depth)))
{
do_assign(e.left(), typename left_type::tag_type());
do_bitwise_or(e.right(), typename right_type::tag_type());
@@ -1020,40 +1536,40 @@ private:
}
}
template <class Exp>
- void do_assign(const Exp& e, const detail::bitwise_or_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or_immediates&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
using default_ops::eval_bitwise_or;
eval_bitwise_or(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::bitwise_xor&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor&)
{
//
// This operation is only valid for integer backends:
//
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
- static int const left_depth = left_type::depth;
- static int const right_depth = right_type::depth;
+ constexpr int const left_depth = left_type::depth;
+ constexpr int const right_depth = right_type::depth;
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && is_self(e.left()))
+ if (bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_bitwise_xor(e.right(), typename right_type::tag_type());
}
- else if(br && is_self(e.right()))
+ else if (br && is_self(e.right()))
{
do_bitwise_xor(e.left(), typename left_type::tag_type());
}
- else if(!br && (bl || (left_depth >= right_depth)))
+ else if (!br && (bl || (left_depth >= right_depth)))
{
do_assign(e.left(), typename left_type::tag_type());
do_bitwise_xor(e.right(), typename right_type::tag_type());
@@ -1065,305 +1581,313 @@ private:
}
}
template <class Exp>
- void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
using default_ops::eval_bitwise_xor;
eval_bitwise_xor(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
}
template <class Exp>
- void do_assign(const Exp& e, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::terminal&)
{
- if(!is_self(e))
+ if (!is_self(e))
{
m_backend = canonical_value(e.value());
}
}
template <class Exp>
- void do_assign(const Exp& e, const detail::function&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::function&)
{
- typedef typename Exp::arity tag_type;
+ using tag_type = typename Exp::arity;
+ boost::multiprecision::detail::maybe_promote_precision(this);
do_assign_function(e, tag_type());
}
template <class Exp>
- void do_assign(const Exp& e, const detail::shift_left&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_left&)
{
// We can only shift by an integer value, not an arbitrary expression:
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
- typedef typename right_type::arity right_arity;
- BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
- typedef typename right_type::result_type right_value_type;
- BOOST_STATIC_ASSERT_MSG(is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
- typedef typename left_type::tag_type tag_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type ;
+ using right_arity = typename right_type::arity;
+ static_assert(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
+ using right_value_type = typename right_type::result_type;
+ static_assert(boost::multiprecision::detail::is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
+ using tag_type = typename left_type::tag_type;
do_assign_left_shift(e.left(), canonical_value(e.right().value()), tag_type());
}
template <class Exp>
- void do_assign(const Exp& e, const detail::shift_right&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_right&)
{
// We can only shift by an integer value, not an arbitrary expression:
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
- typedef typename right_type::arity right_arity;
- BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
- typedef typename right_type::result_type right_value_type;
- BOOST_STATIC_ASSERT_MSG(is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
- typedef typename left_type::tag_type tag_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type ;
+ using right_arity = typename right_type::arity;
+ static_assert(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
+ using right_value_type = typename right_type::result_type;
+ static_assert(boost::multiprecision::detail::is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
+ using tag_type = typename left_type::tag_type;
do_assign_right_shift(e.left(), canonical_value(e.right().value()), tag_type());
}
template <class Exp>
- void do_assign(const Exp& e, const detail::bitwise_complement&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_complement&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
using default_ops::eval_complement;
self_type temp(e.left());
eval_complement(m_backend, temp.backend());
}
template <class Exp>
- void do_assign(const Exp& e, const detail::complement_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::complement_immediates&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
using default_ops::eval_complement;
eval_complement(m_backend, canonical_value(e.left().value()));
}
template <class Exp, class Val>
- void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
using default_ops::eval_right_shift;
- detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
+ detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
eval_right_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
}
template <class Exp, class Val>
- void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
using default_ops::eval_left_shift;
- detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
+ detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
eval_left_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
}
template <class Exp, class Val, class Tag>
- void do_assign_right_shift(const Exp& e, const Val& val, const Tag&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const Tag&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
using default_ops::eval_right_shift;
self_type temp(e);
- detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
+ detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
eval_right_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
}
template <class Exp, class Val, class Tag>
- void do_assign_left_shift(const Exp& e, const Val& val, const Tag&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const Tag&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
using default_ops::eval_left_shift;
self_type temp(e);
- detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
+ detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
eval_left_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
}
template <class Exp>
- void do_assign_function(const Exp& e, const mpl::int_<1>&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 1>&)
{
e.left().value()(&m_backend);
}
template <class Exp>
- void do_assign_function(const Exp& e, const mpl::int_<2>&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 2>&)
{
- typedef typename Exp::right_type right_type;
- typedef typename right_type::tag_type tag_type;
+ using right_type = typename Exp::right_type ;
+ using tag_type = typename right_type::tag_type;
do_assign_function_1(e.left().value(), e.right_ref(), tag_type());
}
template <class F, class Exp>
- void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&)
{
f(m_backend, function_arg_value(val));
}
template <class F, class Exp, class Tag>
- void do_assign_function_1(const F& f, const Exp& val, const Tag&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const Tag&)
{
- number t(val);
+ typename Exp::result_type t(val);
f(m_backend, t.backend());
}
template <class Exp>
- void do_assign_function(const Exp& e, const mpl::int_<3>&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 3>&)
{
- typedef typename Exp::middle_type middle_type;
- typedef typename middle_type::tag_type tag_type;
- typedef typename Exp::right_type end_type;
- typedef typename end_type::tag_type end_tag;
+ using middle_type = typename Exp::middle_type ;
+ using tag_type = typename middle_type::tag_type;
+ using end_type = typename Exp::right_type ;
+ using end_tag = typename end_type::tag_type ;
do_assign_function_2(e.left().value(), e.middle_ref(), e.right_ref(), tag_type(), end_tag());
}
template <class F, class Exp1, class Exp2>
- void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const detail::terminal&)
{
f(m_backend, function_arg_value(val1), function_arg_value(val2));
}
template <class F, class Exp1, class Exp2, class Tag1>
- void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const detail::terminal&)
{
- self_type temp1(val1);
- f(m_backend, BOOST_MP_MOVE(temp1.backend()), function_arg_value(val2));
+ typename Exp1::result_type temp1(val1);
+ f(m_backend, std::move(temp1.backend()), function_arg_value(val2));
}
template <class F, class Exp1, class Exp2, class Tag2>
- void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const Tag2&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const Tag2&)
{
- self_type temp2(val2);
- f(m_backend, function_arg_value(val1), BOOST_MP_MOVE(temp2.backend()));
+ typename Exp2::result_type temp2(val2);
+ f(m_backend, function_arg_value(val1), std::move(temp2.backend()));
}
template <class F, class Exp1, class Exp2, class Tag1, class Tag2>
- void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const Tag2&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const Tag2&)
{
- self_type temp1(val1);
- self_type temp2(val2);
- f(m_backend, BOOST_MP_MOVE(temp1.backend()), BOOST_MP_MOVE(temp2.backend()));
+ typename Exp1::result_type temp1(val1);
+ typename Exp2::result_type temp2(val2);
+ f(m_backend, std::move(temp1.backend()), std::move(temp2.backend()));
}
template <class Exp>
- void do_assign_function(const Exp& e, const mpl::int_<4>&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 4>&)
{
- typedef typename Exp::left_middle_type left_type;
- typedef typename left_type::tag_type left_tag_type;
- typedef typename Exp::right_middle_type middle_type;
- typedef typename middle_type::tag_type middle_tag_type;
- typedef typename Exp::right_type right_type;
- typedef typename right_type::tag_type right_tag_type;
+ using left_type = typename Exp::left_middle_type ;
+ using left_tag_type = typename left_type::tag_type ;
+ using middle_type = typename Exp::right_middle_type;
+ using middle_tag_type = typename middle_type::tag_type ;
+ using right_type = typename Exp::right_type ;
+ using right_tag_type = typename right_type::tag_type ;
do_assign_function_3a(e.left().value(), e.left_middle_ref(), e.right_middle_ref(), e.right_ref(), left_tag_type(), middle_tag_type(), right_tag_type());
}
+
template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
- void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag2& t2, const Tag3& t3)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag2& t2, const Tag3& t3)
{
do_assign_function_3b(f, val1, val2, val3, t2, t3);
}
template <class F, class Exp1, class Exp2, class Exp3, class Tag1, class Tag2, class Tag3>
- void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag1&, const Tag2& t2, const Tag3& t3)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag1&, const Tag2& t2, const Tag3& t3)
{
- number t(val1);
- do_assign_function_3b(f, BOOST_MP_MOVE(t), val2, val3, t2, t3);
+ typename Exp1::result_type t(val1);
+ do_assign_function_3b(f, std::move(t), val2, val3, t2, t3);
}
template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
- void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag3& t3)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag3& t3)
{
do_assign_function_3c(f, val1, val2, val3, t3);
}
template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
- void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& /*t2*/, const Tag3& t3)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& /*t2*/, const Tag3& t3)
{
- number t(val2);
- do_assign_function_3c(f, val1, BOOST_MP_MOVE(t), val3, t3);
+ typename Exp2::result_type t(val2);
+ do_assign_function_3c(f, val1, std::move(t), val3, t3);
}
template <class F, class Exp1, class Exp2, class Exp3>
- void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&)
{
f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3));
}
template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
- void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& /*t3*/)
+ BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& /*t3*/)
{
- number t(val3);
- do_assign_function_3c(f, val1, val2, BOOST_MP_MOVE(t), detail::terminal());
+ typename Exp3::result_type t(val3);
+ do_assign_function_3c(f, val1, val2, std::move(t), detail::terminal());
}
template <class Exp>
- void do_add(const Exp& e, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::terminal&)
{
using default_ops::eval_add;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_add(m_backend, canonical_value(e.value()));
}
template <class Exp>
- void do_add(const Exp& e, const detail::negate&)
+ BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::negate&)
{
- typedef typename Exp::left_type left_type;
+ using left_type = typename Exp::left_type;
+ boost::multiprecision::detail::maybe_promote_precision(this);
do_subtract(e.left(), typename left_type::tag_type());
}
template <class Exp>
- void do_add(const Exp& e, const detail::plus&)
+ BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::plus&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_add(e.left(), typename left_type::tag_type());
do_add(e.right(), typename right_type::tag_type());
}
template <class Exp>
- void do_add(const Exp& e, const detail::minus&)
+ BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::minus&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_add(e.left(), typename left_type::tag_type());
do_subtract(e.right(), typename right_type::tag_type());
}
template <class Exp, class unknown>
- void do_add(const Exp& e, const unknown&)
+ BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const unknown&)
{
self_type temp(e);
do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
}
template <class Exp>
- void do_add(const Exp& e, const detail::add_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::add_immediates&)
{
using default_ops::eval_add;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_add(m_backend, canonical_value(e.left().value()));
eval_add(m_backend, canonical_value(e.right().value()));
}
template <class Exp>
- void do_add(const Exp& e, const detail::subtract_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::subtract_immediates&)
{
using default_ops::eval_add;
using default_ops::eval_subtract;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_add(m_backend, canonical_value(e.left().value()));
eval_subtract(m_backend, canonical_value(e.right().value()));
}
template <class Exp>
- void do_subtract(const Exp& e, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::terminal&)
{
using default_ops::eval_subtract;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_subtract(m_backend, canonical_value(e.value()));
}
template <class Exp>
- void do_subtract(const Exp& e, const detail::negate&)
+ BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::negate&)
{
- typedef typename Exp::left_type left_type;
+ using left_type = typename Exp::left_type;
do_add(e.left(), typename left_type::tag_type());
}
template <class Exp>
- void do_subtract(const Exp& e, const detail::plus&)
+ BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::plus&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_subtract(e.left(), typename left_type::tag_type());
do_subtract(e.right(), typename right_type::tag_type());
}
template <class Exp>
- void do_subtract(const Exp& e, const detail::minus&)
+ BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::minus&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_subtract(e.left(), typename left_type::tag_type());
do_add(e.right(), typename right_type::tag_type());
}
template <class Exp>
- void do_subtract(const Exp& e, const detail::add_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::add_immediates&)
{
using default_ops::eval_subtract;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_subtract(m_backend, canonical_value(e.left().value()));
eval_subtract(m_backend, canonical_value(e.right().value()));
}
template <class Exp>
- void do_subtract(const Exp& e, const detail::subtract_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::subtract_immediates&)
{
using default_ops::eval_add;
using default_ops::eval_subtract;
@@ -1371,32 +1895,33 @@ private:
eval_add(m_backend, canonical_value(e.right().value()));
}
template <class Exp, class unknown>
- void do_subtract(const Exp& e, const unknown&)
+ BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const unknown&)
{
self_type temp(e);
do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
}
template <class Exp>
- void do_multiplies(const Exp& e, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::terminal&)
{
using default_ops::eval_multiply;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_multiply(m_backend, canonical_value(e.value()));
}
template <class Exp>
- void do_multiplies(const Exp& e, const detail::negate&)
+ BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::negate&)
{
- typedef typename Exp::left_type left_type;
+ using left_type = typename Exp::left_type;
do_multiplies(e.left(), typename left_type::tag_type());
m_backend.negate();
}
template <class Exp>
- void do_multiplies(const Exp& e, const detail::multiplies&)
+ BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiplies&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_multiplies(e.left(), typename left_type::tag_type());
do_multiplies(e.right(), typename right_type::tag_type());
}
@@ -1405,19 +1930,20 @@ private:
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
//
template <class Exp>
- typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
- do_multiplies(const Exp& e, const detail::divides&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
+ do_multiplies(const Exp& e, const detail::divides&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_multiplies(e.left(), typename left_type::tag_type());
do_divide(e.right(), typename right_type::tag_type());
}
template <class Exp>
- void do_multiplies(const Exp& e, const detail::multiply_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiply_immediates&)
{
using default_ops::eval_multiply;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_multiply(m_backend, canonical_value(e.left().value()));
eval_multiply(m_backend, canonical_value(e.right().value()));
}
@@ -1426,33 +1952,36 @@ private:
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
//
template <class Exp>
- typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
- do_multiplies(const Exp& e, const detail::divide_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
+ do_multiplies(const Exp& e, const detail::divide_immediates&)
{
- using default_ops::eval_multiply;
using default_ops::eval_divide;
+ using default_ops::eval_multiply;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_multiply(m_backend, canonical_value(e.left().value()));
eval_divide(m_backend, canonical_value(e.right().value()));
}
template <class Exp, class unknown>
- void do_multiplies(const Exp& e, const unknown&)
+ BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const unknown&)
{
using default_ops::eval_multiply;
+ boost::multiprecision::detail::maybe_promote_precision(this);
self_type temp(e);
eval_multiply(m_backend, temp.m_backend);
}
template <class Exp>
- void do_divide(const Exp& e, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::terminal&)
{
using default_ops::eval_divide;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_divide(m_backend, canonical_value(e.value()));
}
template <class Exp>
- void do_divide(const Exp& e, const detail::negate&)
+ BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::negate&)
{
- typedef typename Exp::left_type left_type;
+ using left_type = typename Exp::left_type;
do_divide(e.left(), typename left_type::tag_type());
m_backend.negate();
}
@@ -1461,11 +1990,11 @@ private:
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
//
template <class Exp>
- typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
- do_divide(const Exp& e, const detail::multiplies&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
+ do_divide(const Exp& e, const detail::multiplies&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_divide(e.left(), typename left_type::tag_type());
do_divide(e.right(), typename right_type::tag_type());
}
@@ -1474,11 +2003,11 @@ private:
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
//
template <class Exp>
- typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
- do_divide(const Exp& e, const detail::divides&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
+ do_divide(const Exp& e, const detail::divides&)
{
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_divide(e.left(), typename left_type::tag_type());
do_multiplies(e.right(), typename right_type::tag_type());
}
@@ -1487,10 +2016,11 @@ private:
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
//
template <class Exp>
- typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
- do_divides(const Exp& e, const detail::multiply_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
+ do_divides(const Exp& e, const detail::multiply_immediates&)
{
using default_ops::eval_divide;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_divide(m_backend, canonical_value(e.left().value()));
eval_divide(m_backend, canonical_value(e.right().value()));
}
@@ -1499,110 +2029,114 @@ private:
// the disable_if dependent on the template argument (the size of 1 can never occur in practice).
//
template <class Exp>
- typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
- do_divides(const Exp& e, const detail::divide_immediates&)
+ BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
+ do_divides(const Exp& e, const detail::divide_immediates&)
{
- using default_ops::eval_multiply;
using default_ops::eval_divide;
+ using default_ops::eval_multiply;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_divide(m_backend, canonical_value(e.left().value()));
mutiply(m_backend, canonical_value(e.right().value()));
}
template <class Exp, class unknown>
- void do_divide(const Exp& e, const unknown&)
+ BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const unknown&)
{
using default_ops::eval_multiply;
+ boost::multiprecision::detail::maybe_promote_precision(this);
self_type temp(e);
eval_divide(m_backend, temp.m_backend);
}
template <class Exp>
- void do_modulus(const Exp& e, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const detail::terminal&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
using default_ops::eval_modulus;
+ boost::multiprecision::detail::maybe_promote_precision(this);
eval_modulus(m_backend, canonical_value(e.value()));
}
template <class Exp, class Unknown>
- void do_modulus(const Exp& e, const Unknown&)
+ BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const Unknown&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
using default_ops::eval_modulus;
+ boost::multiprecision::detail::maybe_promote_precision(this);
self_type temp(e);
eval_modulus(m_backend, canonical_value(temp));
}
template <class Exp>
- void do_bitwise_and(const Exp& e, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::terminal&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
using default_ops::eval_bitwise_and;
eval_bitwise_and(m_backend, canonical_value(e.value()));
}
template <class Exp>
- void do_bitwise_and(const Exp& e, const detail::bitwise_and&)
+ BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::bitwise_and&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_bitwise_and(e.left(), typename left_type::tag_type());
do_bitwise_and(e.right(), typename right_type::tag_type());
}
template <class Exp, class unknown>
- void do_bitwise_and(const Exp& e, const unknown&)
+ BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const unknown&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
using default_ops::eval_bitwise_and;
self_type temp(e);
eval_bitwise_and(m_backend, temp.m_backend);
}
template <class Exp>
- void do_bitwise_or(const Exp& e, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::terminal&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
using default_ops::eval_bitwise_or;
eval_bitwise_or(m_backend, canonical_value(e.value()));
}
template <class Exp>
- void do_bitwise_or(const Exp& e, const detail::bitwise_or&)
+ BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::bitwise_or&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_bitwise_or(e.left(), typename left_type::tag_type());
do_bitwise_or(e.right(), typename right_type::tag_type());
}
template <class Exp, class unknown>
- void do_bitwise_or(const Exp& e, const unknown&)
+ BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const unknown&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
using default_ops::eval_bitwise_or;
self_type temp(e);
eval_bitwise_or(m_backend, temp.m_backend);
}
template <class Exp>
- void do_bitwise_xor(const Exp& e, const detail::terminal&)
+ BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::terminal&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
using default_ops::eval_bitwise_xor;
eval_bitwise_xor(m_backend, canonical_value(e.value()));
}
template <class Exp>
- void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&)
+ BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
- typedef typename Exp::left_type left_type;
- typedef typename Exp::right_type right_type;
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
+ using left_type = typename Exp::left_type ;
+ using right_type = typename Exp::right_type;
do_bitwise_xor(e.left(), typename left_type::tag_type());
do_bitwise_xor(e.right(), typename right_type::tag_type());
}
template <class Exp, class unknown>
- void do_bitwise_xor(const Exp& e, const unknown&)
+ BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const unknown&)
{
- BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
+ static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
using default_ops::eval_bitwise_xor;
self_type temp(e);
eval_bitwise_xor(m_backend, temp.m_backend);
@@ -1610,112 +2144,118 @@ private:
// Tests if the expression contains a reference to *this:
template <class Exp>
- BOOST_MP_FORCEINLINE bool contains_self(const Exp& e)const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e) const noexcept
{
return contains_self(e, typename Exp::arity());
}
template <class Exp>
- BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 0> const&) const noexcept
{
return is_realy_self(e.value());
}
template <class Exp>
- BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<1> const&)const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 1> const&) const noexcept
{
- typedef typename Exp::left_type child_type;
+ using child_type = typename Exp::left_type;
return contains_self(e.left(), typename child_type::arity());
}
template <class Exp>
- BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<2> const&)const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 2> const&) const noexcept
{
- typedef typename Exp::left_type child0_type;
- typedef typename Exp::right_type child1_type;
- return contains_self(e.left(), typename child0_type::arity())
- || contains_self(e.right(), typename child1_type::arity());
+ using child0_type = typename Exp::left_type ;
+ using child1_type = typename Exp::right_type;
+ return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.right(), typename child1_type::arity());
}
template <class Exp>
- BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<3> const&)const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 3> const&) const noexcept
{
- typedef typename Exp::left_type child0_type;
- typedef typename Exp::middle_type child1_type;
- typedef typename Exp::right_type child2_type;
- return contains_self(e.left(), typename child0_type::arity())
- || contains_self(e.middle(), typename child1_type::arity())
- || contains_self(e.right(), typename child2_type::arity());
+ using child0_type = typename Exp::left_type ;
+ using child1_type = typename Exp::middle_type;
+ using child2_type = typename Exp::right_type ;
+ return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.middle(), typename child1_type::arity()) || contains_self(e.right(), typename child2_type::arity());
}
// Test if the expression is a reference to *this:
template <class Exp>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e)const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp& e) const noexcept
{
return is_self(e, typename Exp::arity());
}
template <class Exp>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp& e, std::integral_constant<int, 0> const&) const noexcept
{
return is_realy_self(e.value());
}
template <class Exp, int v>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp&, mpl::int_<v> const&)const BOOST_NOEXCEPT
+ BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp&, std::integral_constant<int, v> const&) const noexcept
{
return false;
}
template <class Val>
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const Val&)const BOOST_NOEXCEPT{ return false; }
- BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const self_type& v)const BOOST_NOEXCEPT{ return &v == this; }
+ BOOST_MP_FORCEINLINE constexpr bool is_realy_self(const Val&) const noexcept { return false; }
+ BOOST_MP_FORCEINLINE constexpr bool is_realy_self(const self_type& v) const noexcept { return &v == this; }
- static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT { return v.backend(); }
+ static BOOST_MP_FORCEINLINE constexpr const Backend& function_arg_value(const self_type& v) noexcept { return v.backend(); }
+ template <class Other, expression_template_option ET2>
+ static BOOST_MP_FORCEINLINE constexpr const Other& function_arg_value(const number<Other, ET2>& v) noexcept { return v.backend(); }
template <class V>
- static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const V& function_arg_value(const V& v) BOOST_NOEXCEPT { return v; }
+ static BOOST_MP_FORCEINLINE constexpr const V& function_arg_value(const V& v) noexcept { return v; }
template <class A1, class A2, class A3, class A4>
- static BOOST_MP_FORCEINLINE const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value(); }
+ static BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) noexcept { return exp.value(); }
template <class A2, class A3, class A4>
- static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value().backend(); }
- Backend m_backend;
+ static BOOST_MP_FORCEINLINE constexpr const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) noexcept { return exp.value().backend(); }
+ Backend m_backend;
-public:
+ public:
//
// These shouldn't really need to be public, or even member functions, but it makes implementing
// the non-member operators way easier if they are:
//
- static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& canonical_value(const self_type& v) BOOST_NOEXCEPT { return v.m_backend; }
+ static BOOST_MP_FORCEINLINE constexpr const Backend& canonical_value(const self_type& v) noexcept { return v.m_backend; }
template <class B2, expression_template_option ET>
- static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const B2& canonical_value(const number<B2, ET>& v) BOOST_NOEXCEPT { return v.backend(); }
+ static BOOST_MP_FORCEINLINE constexpr const B2& canonical_value(const number<B2, ET>& v) noexcept { return v.backend(); }
+ template <class B2, expression_template_option ET>
+ static BOOST_MP_FORCEINLINE constexpr B2&& canonical_value(number<B2, ET>&& v) noexcept { return static_cast<number<B2, ET>&&>(v).backend(); }
template <class V>
- static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR typename boost::disable_if<is_same<typename detail::canonical<V, Backend>::type, V>, typename detail::canonical<V, Backend>::type>::type
- canonical_value(const V& v) BOOST_NOEXCEPT { return static_cast<typename detail::canonical<V, Backend>::type>(v); }
+ static BOOST_MP_FORCEINLINE constexpr typename std::enable_if<!std::is_same<typename detail::canonical<V, Backend>::type, V>::value, typename detail::canonical<V, Backend>::type>::type
+ canonical_value(const V& v) noexcept { return static_cast<typename detail::canonical<V, Backend>::type>(v); }
template <class V>
- static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR typename boost::enable_if<is_same<typename detail::canonical<V, Backend>::type, V>, const V&>::type
- canonical_value(const V& v) BOOST_NOEXCEPT { return v; }
- static BOOST_MP_FORCEINLINE typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v) BOOST_NOEXCEPT { return v.c_str(); }
-
+ static BOOST_MP_FORCEINLINE constexpr typename std::enable_if<std::is_same<typename detail::canonical<V, Backend>::type, V>::value, const V&>::type
+ canonical_value(const V& v) noexcept { return v; }
+ static BOOST_MP_FORCEINLINE typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v) noexcept { return v.c_str(); }
};
template <class Backend, expression_template_option ExpressionTemplates>
-inline std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r)
+inline std::ostream& operator<<(std::ostream& os, const number<Backend, ExpressionTemplates>& r)
{
- std::streamsize d = os.precision();
- std::string s = r.str(d, os.flags());
+ std::streamsize d = os.precision();
+ std::string s = r.str(d, os.flags());
std::streamsize ss = os.width();
- if(ss > static_cast<std::streamsize>(s.size()))
+ if (ss > static_cast<std::streamsize>(s.size()))
{
char fill = os.fill();
- if((os.flags() & std::ios_base::left) == std::ios_base::left)
- s.append(static_cast<std::string::size_type>(ss - s.size()), fill);
+ if ((os.flags() & std::ios_base::left) == std::ios_base::left)
+ s.append(static_cast<std::string::size_type>(ss - static_cast<std::streamsize>(s.size())), fill);
else
- s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - s.size()), fill);
+ s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - static_cast<std::streamsize>(s.size())), fill);
}
return os << s;
}
-namespace detail{
+template <class Backend, expression_template_option ExpressionTemplates>
+std::string to_string(const number<Backend, ExpressionTemplates>& val)
+{
+ return val.str(6, std::ios_base::fixed|std::ios_base::showpoint);
+}
+
+namespace detail {
template <class tag, class A1, class A2, class A3, class A4>
-inline std::ostream& operator << (std::ostream& os, const expression<tag, A1, A2, A3, A4>& r)
+inline std::ostream& operator<<(std::ostream& os, const expression<tag, A1, A2, A3, A4>& r)
{
- typedef typename expression<tag, A1, A2, A3, A4>::result_type value_type;
- value_type temp(r);
+ using value_type = typename expression<tag, A1, A2, A3, A4>::result_type;
+ value_type temp(r);
return os << temp;
}
//
@@ -1729,21 +2269,21 @@ inline std::ostream& operator << (std::ostream& os, const expression<tag, A1, A2
//
inline std::string read_string_while(std::istream& is, std::string const& permitted_chars)
{
- std::ios_base::iostate state = std::ios_base::goodbit;
+ std::ios_base::iostate state = std::ios_base::goodbit;
const std::istream::sentry sentry_check(is);
- std::string result;
+ std::string result;
- if(sentry_check)
+ if (sentry_check)
{
int c = is.rdbuf()->sgetc();
- for(;; c = is.rdbuf()->snextc())
- if(std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))
+ for (;; c = is.rdbuf()->snextc())
+ if (std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))
{ // end of file:
state |= std::ios_base::eofbit;
break;
}
- else if(permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)
+ else if (permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)
{
// Invalid numeric character, stop reading:
//is.rdbuf()->sputbackc(static_cast<char>(c));
@@ -1755,7 +2295,7 @@ inline std::string read_string_while(std::istream& is, std::string const& permit
}
}
- if(!result.size())
+ if (!result.size())
state |= std::ios_base::failbit;
is.setstate(state);
return result;
@@ -1764,43 +2304,58 @@ inline std::string read_string_while(std::istream& is, std::string const& permit
} // namespace detail
template <class Backend, expression_template_option ExpressionTemplates>
-inline std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r)
+inline std::istream& operator>>(std::istream& is, number<Backend, ExpressionTemplates>& r)
{
- bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
- bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
+ bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
+ bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
std::string s;
- switch(boost::multiprecision::number_category<number<Backend, ExpressionTemplates> >::value)
+ switch (boost::multiprecision::number_category<number<Backend, ExpressionTemplates> >::value)
{
case boost::multiprecision::number_kind_integer:
- if(oct_format)
+ if (oct_format)
s = detail::read_string_while(is, "+-01234567");
- else if(hex_format)
+ else if (hex_format)
s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789");
else
s = detail::read_string_while(is, "+-0123456789");
break;
+ case boost::multiprecision::number_kind_rational:
+ if (oct_format)
+ s = detail::read_string_while(is, "+-01234567/");
+ else if (hex_format)
+ s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789/");
+ else
+ s = detail::read_string_while(is, "+-0123456789/");
+ break;
case boost::multiprecision::number_kind_floating_point:
- s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
+ BOOST_IF_CONSTEXPR(std::is_same<number<Backend, ExpressionTemplates>, typename number<Backend, ExpressionTemplates>::value_type>::value)
+ s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
+ else
+ // Interval:
+ s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY{,}");
+ break;
+ case boost::multiprecision::number_kind_complex:
+ s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY,()");
break;
default:
is >> s;
}
- if(s.size())
+ if (s.size())
{
- if(hex_format && (number_category<Backend>::value == number_kind_integer) && ((s[0] != '0') || (s[1] != 'x')))
+ if (hex_format && (number_category<Backend>::value == number_kind_integer) && ((s[0] != '0') || (s[1] != 'x')))
s.insert(s.find_first_not_of("+-"), "0x");
- if(oct_format && (number_category<Backend>::value == number_kind_integer) && (s[0] != '0'))
+ if (oct_format && (number_category<Backend>::value == number_kind_integer) && (s[0] != '0'))
s.insert(s.find_first_not_of("+-"), "0");
r.assign(s);
}
- else if(!is.fail())
+ else if (!is.fail())
is.setstate(std::istream::failbit);
return is;
}
template <class Backend, expression_template_option ExpressionTemplates>
-BOOST_MP_FORCEINLINE void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b)
- BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<number<Backend, ExpressionTemplates>&>() = std::declval<number<Backend, ExpressionTemplates>&>()))
+BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b)
+ noexcept(noexcept(std::declval<number<Backend, ExpressionTemplates>&>() = std::declval<number<Backend, ExpressionTemplates>&>()))
{
a.swap(b);
}
@@ -1808,52 +2363,63 @@ BOOST_MP_FORCEINLINE void swap(number<Backend, ExpressionTemplates>& a, number<B
// Boost.Hash support, just call hash_value for the backend, which may or may not be supported:
//
template <class Backend, expression_template_option ExpressionTemplates>
-inline std::size_t hash_value(const number<Backend, ExpressionTemplates>& val)
+inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const number<Backend, ExpressionTemplates>& val)
{
return hash_value(val.backend());
}
-} // namespace multiprecision
+namespace detail {
+
+BOOST_MP_FORCEINLINE bool istream_peek(std::istream& is, char& c, bool have_hex)
+{
+ int i = is.peek();
+ c = static_cast<char>(i);
+ return (EOF != i) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')));
+}
+
+} // namespace detail
+
+} // namespace multiprecision
template <class T>
class rational;
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
-inline std::istream& operator >> (std::istream& is, rational<multiprecision::number<Backend, ExpressionTemplates> >& r)
+inline std::istream& operator>>(std::istream& is, rational<multiprecision::number<Backend, ExpressionTemplates> >& r)
{
- std::string s1;
+ std::string s1;
multiprecision::number<Backend, ExpressionTemplates> v1, v2;
- char c;
- bool have_hex = false;
- bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
- bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
+ char c;
+ bool have_hex = false;
+ bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
+ bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
- while((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
+ while (multiprecision::detail::istream_peek(is, c, have_hex))
{
- if(c == 'x' || c == 'X')
+ if (c == 'x' || c == 'X')
have_hex = true;
s1.append(1, c);
is.get();
}
- if(hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
+ if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
s1.insert(static_cast<std::string::size_type>(0), "0x");
- if(oct_format && (s1[0] != '0'))
+ if (oct_format && (s1[0] != '0'))
s1.insert(static_cast<std::string::size_type>(0), "0");
v1.assign(s1);
s1.erase();
- if(c == '/')
+ if (c == '/')
{
is.get();
- while((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
+ while (multiprecision::detail::istream_peek(is, c, have_hex))
{
- if(c == 'x' || c == 'X')
+ if (c == 'x' || c == 'X')
have_hex = true;
s1.append(1, c);
is.get();
}
- if(hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
+ if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
s1.insert(static_cast<std::string::size_type>(0), "0x");
- if(oct_format && (s1[0] != '0'))
+ if (oct_format && (s1[0] != '0'))
s1.insert(static_cast<std::string::size_type>(0), "0");
v2.assign(s1);
}
@@ -1864,49 +2430,60 @@ inline std::istream& operator >> (std::istream& is, rational<multiprecision::num
}
template <class T, multiprecision::expression_template_option ExpressionTemplates>
-inline multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
{
return a.numerator();
}
template <class T, multiprecision::expression_template_option ExpressionTemplates>
-inline multiprecision::number<T, ExpressionTemplates> denominator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
+inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> denominator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
{
return a.denominator();
}
-namespace multiprecision
+template <class T, multiprecision::expression_template_option ExpressionTemplates>
+inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const rational<multiprecision::number<T, ExpressionTemplates> >& val)
{
+ std::size_t result = hash_value(val.numerator());
+ boost::multiprecision::detail::hash_combine(result, hash_value(val.denominator()));
+ return result;
+}
+
+namespace multiprecision {
template <class I>
struct component_type<boost::rational<I> >
{
- typedef I type;
+ using type = I;
};
-}
+} // namespace multiprecision
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
-} // namespaces
-
-#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
-
-#include <functional>
+} // namespace boost
namespace std {
- template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
- struct hash<boost::multiprecision::number<Backend, ExpressionTemplates> >
+template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
+struct hash<boost::multiprecision::number<Backend, ExpressionTemplates> >
+{
+ BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::multiprecision::number<Backend, ExpressionTemplates>& val) const { return hash_value(val); }
+};
+template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
+struct hash<boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> > >
+{
+ BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> >& val) const
{
- std::size_t operator()(const boost::multiprecision::number<Backend, ExpressionTemplates>& val)const { return hash_value(val); }
- };
-
-}
+ std::size_t result = hash_value(val.numerator());
+ boost::multiprecision::detail::hash_combine(result, hash_value(val.denominator()));
+ return result;
+ }
+};
-#endif
+} // namespace std
#include <boost/multiprecision/detail/ublas_interop.hpp>
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/rational_adaptor.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/rational_adaptor.hpp
index 4ba5961a11..baa7631268 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/rational_adaptor.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/rational_adaptor.hpp
@@ -1,131 +1,173 @@
///////////////////////////////////////////////////////////////
-// Copyright 2011 John Maddock. Distributed under the Boost
+// Copyright 2020 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_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
-#ifndef BOOST_MATH_RATIONAL_ADAPTER_HPP
-#define BOOST_MATH_RATIONAL_ADAPTER_HPP
+#ifndef BOOST_MP_RATIONAL_ADAPTOR_HPP
+#define BOOST_MP_RATIONAL_ADAPTOR_HPP
-#include <iostream>
-#include <iomanip>
-#include <sstream>
-#include <boost/cstdint.hpp>
-#include <boost/functional/hash_fwd.hpp>
#include <boost/multiprecision/number.hpp>
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable:4512 4127)
-#endif
-#include <boost/rational.hpp>
-#ifdef BOOST_MSVC
-# pragma warning(pop)
-#endif
+#include <boost/multiprecision/detail/hash.hpp>
+#include <boost/multiprecision/detail/float128_functions.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
-namespace boost{
-namespace multiprecision{
-namespace backends{
+namespace boost {
+namespace multiprecision {
+namespace backends {
-template <class IntBackend>
+template <class Backend>
struct rational_adaptor
{
- typedef number<IntBackend> integer_type;
- typedef boost::rational<integer_type> rational_type;
+ //
+ // Each backend need to declare 3 type lists which declare the types
+ // with which this can interoperate. These lists must at least contain
+ // the widest type in each category - so "long long" must be the final
+ // type in the signed_types list for example. Any narrower types if not
+ // present in the list will get promoted to the next wider type that is
+ // in the list whenever mixed arithmetic involving that type is encountered.
+ //
+ typedef typename Backend::signed_types signed_types;
+ typedef typename Backend::unsigned_types unsigned_types;
+ typedef typename Backend::float_types float_types;
- typedef typename IntBackend::signed_types signed_types;
- typedef typename IntBackend::unsigned_types unsigned_types;
- typedef typename IntBackend::float_types float_types;
+ typedef typename std::tuple_element<0, unsigned_types>::type ui_type;
- rational_adaptor() BOOST_MP_NOEXCEPT_IF(noexcept(rational_type())) {}
- rational_adaptor(const rational_adaptor& o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<rational_type&>() = std::declval<const rational_type&>()))
+ static Backend get_one()
+ {
+ Backend t;
+ t = static_cast<ui_type>(1);
+ return t;
+ }
+ static Backend get_zero()
{
- m_value = o.m_value;
+ Backend t;
+ t = static_cast<ui_type>(0);
+ return t;
}
- rational_adaptor(const IntBackend& o) BOOST_MP_NOEXCEPT_IF(noexcept(rational_type(std::declval<const IntBackend&>()))) : m_value(o) {}
- template <class U>
- rational_adaptor(const U& u, typename enable_if_c<is_convertible<U, IntBackend>::value>::type* = 0)
- : m_value(static_cast<integer_type>(u)){}
- template <class U>
- explicit rational_adaptor(const U& u,
- typename enable_if_c<
- boost::multiprecision::detail::is_explicitly_convertible<U, IntBackend>::value && !is_convertible<U, IntBackend>::value
- >::type* = 0)
- : m_value(IntBackend(u)){}
- template <class U>
- typename enable_if_c<(boost::multiprecision::detail::is_explicitly_convertible<U, IntBackend>::value && !is_arithmetic<U>::value), rational_adaptor&>::type operator = (const U& u)
+ static const Backend& one()
{
- m_value = IntBackend(u);
- return *this;
+ static const Backend result(get_one());
+ return result;
+ }
+ static const Backend& zero()
+ {
+ static const Backend result(get_zero());
+ return result;
}
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- rational_adaptor(rational_adaptor&& o) BOOST_MP_NOEXCEPT_IF(noexcept(rational_type(std::declval<rational_type>()))) : m_value(static_cast<rational_type&&>(o.m_value)) {}
- rational_adaptor(IntBackend&& o) BOOST_MP_NOEXCEPT_IF(noexcept(rational_type(std::declval<IntBackend>()))) : m_value(static_cast<IntBackend&&>(o)) {}
- rational_adaptor& operator = (rational_adaptor&& o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<rational_type&>() = std::declval<rational_type>()))
+ void normalize()
{
- m_value = static_cast<rational_type&&>(o.m_value);
- return *this;
+ using default_ops::eval_gcd;
+ using default_ops::eval_eq;
+ using default_ops::eval_divide;
+ using default_ops::eval_get_sign;
+
+ int s = eval_get_sign(m_denom);
+
+ if(s == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
+ }
+ else if (s < 0)
+ {
+ m_num.negate();
+ m_denom.negate();
+ }
+
+ Backend g, t;
+ eval_gcd(g, m_num, m_denom);
+ if (!eval_eq(g, one()))
+ {
+ eval_divide(t, m_num, g);
+ m_num.swap(t);
+ eval_divide(t, m_denom, g);
+ m_denom = std::move(t);
+ }
}
-#endif
- rational_adaptor& operator = (const rational_adaptor& o)
+
+ // We must have a default constructor:
+ rational_adaptor()
+ : m_num(zero()), m_denom(one()) {}
+
+ rational_adaptor(const rational_adaptor& o) : m_num(o.m_num), m_denom(o.m_denom) {}
+ rational_adaptor(rational_adaptor&& o) = default;
+
+ // Optional constructors, we can make this type slightly more efficient
+ // by providing constructors from any type we can handle natively.
+ // These will also cause number<> to be implicitly constructible
+ // from these types unless we make such constructors explicit.
+ //
+ template <class Arithmetic>
+ rational_adaptor(const Arithmetic& val, typename std::enable_if<std::is_constructible<Backend, Arithmetic>::value && !std::is_floating_point<Arithmetic>::value>::type const* = nullptr)
+ : m_num(val), m_denom(one()) {}
+
+ //
+ // Pass-through 2-arg construction of components:
+ //
+ template <class T, class U>
+ rational_adaptor(const T& a, const U& b, typename std::enable_if<std::is_constructible<Backend, T const&>::value && std::is_constructible<Backend, U const&>::value>::type const* = nullptr)
+ : m_num(a), m_denom(b)
{
- m_value = o.m_value;
- return *this;
+ normalize();
}
- rational_adaptor& operator = (const IntBackend& o)
+ template <class T, class U>
+ rational_adaptor(T&& a, const U& b, typename std::enable_if<std::is_constructible<Backend, T>::value && std::is_constructible<Backend, U>::value>::type const* = nullptr)
+ : m_num(static_cast<T&&>(a)), m_denom(b)
{
- m_value = o;
- return *this;
+ normalize();
}
- template <class Int>
- typename enable_if<is_integral<Int>, rational_adaptor&>::type operator = (Int i)
+ template <class T, class U>
+ rational_adaptor(T&& a, U&& b, typename std::enable_if<std::is_constructible<Backend, T>::value && std::is_constructible<Backend, U>::value>::type const* = nullptr)
+ : m_num(static_cast<T&&>(a)), m_denom(static_cast<U&&>(b))
{
- m_value = i;
- return *this;
+ normalize();
}
- template <class Float>
- typename enable_if<is_floating_point<Float>, rational_adaptor&>::type operator = (Float i)
+ template <class T, class U>
+ rational_adaptor(const T& a, U&& b, typename std::enable_if<std::is_constructible<Backend, T>::value && std::is_constructible<Backend, U>::value>::type const* = nullptr)
+ : m_num(a), m_denom(static_cast<U&&>(b))
{
- int e;
- Float f = std::frexp(i, &e);
- f = std::ldexp(f, std::numeric_limits<Float>::digits);
- e -= std::numeric_limits<Float>::digits;
- integer_type num(f);
- integer_type denom(1u);
- if(e > 0)
- {
- num <<= e;
- }
- else if(e < 0)
- {
- denom <<= -e;
- }
- m_value.assign(num, denom);
+ normalize();
+ }
+ //
+ // In the absense of converting constructors, operator= takes the strain.
+ // In addition to the usual suspects, there must be one operator= for each type
+ // listed in signed_types, unsigned_types, and float_types plus a string constructor.
+ //
+ rational_adaptor& operator=(const rational_adaptor& o) = default;
+ rational_adaptor& operator=(rational_adaptor&& o) = default;
+ template <class Arithmetic>
+ inline typename std::enable_if<!std::is_floating_point<Arithmetic>::value, rational_adaptor&>::type operator=(const Arithmetic& i)
+ {
+ m_num = i;
+ m_denom = one();
return *this;
}
- rational_adaptor& operator = (const char* s)
+ rational_adaptor& operator=(const char* s)
{
- std::string s1;
- multiprecision::number<IntBackend> v1, v2;
- char c;
- bool have_hex = false;
+ using default_ops::eval_eq;
+
+ std::string s1;
+ multiprecision::number<Backend> v1, v2;
+ char c;
+ bool have_hex = false;
const char* p = s; // saved for later
- while((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
+ while ((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
{
- if(c == 'x' || c == 'X')
+ if (c == 'x' || c == 'X')
have_hex = true;
s1.append(1, c);
++s;
}
v1.assign(s1);
s1.erase();
- if(c == '/')
+ if (c == '/')
{
++s;
- while((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
+ while ((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
{
- if(c == 'x' || c == 'X')
+ if (c == 'x' || c == 'X')
have_hex = true;
s1.append(1, c);
++s;
@@ -134,108 +176,216 @@ struct rational_adaptor
}
else
v2 = 1;
- if(*s)
+ if (*s)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("Could not parse the string \"") + p + std::string("\" as a valid rational number.")));
+ }
+ multiprecision::number<Backend> gcd;
+ eval_gcd(gcd.backend(), v1.backend(), v2.backend());
+ if (!eval_eq(gcd.backend(), one()))
{
- BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Could not parse the string \"") + p + std::string("\" as a valid rational number.")));
+ v1 /= gcd;
+ v2 /= gcd;
}
- data().assign(v1, v2);
+ num() = std::move(std::move(v1).backend());
+ denom() = std::move(std::move(v2).backend());
return *this;
}
+ template <class Float>
+ typename std::enable_if<std::is_floating_point<Float>::value, rational_adaptor&>::type operator=(Float i)
+ {
+ using default_ops::eval_eq;
+ BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp;
+
+ int e;
+ Float f = frexp(i, &e);
+#ifdef BOOST_HAS_FLOAT128
+ f = ldexp(f, std::is_same<float128_type, Float>::value ? 113 : std::numeric_limits<Float>::digits);
+ e -= std::is_same<float128_type, Float>::value ? 113 : std::numeric_limits<Float>::digits;
+#else
+ f = ldexp(f, std::numeric_limits<Float>::digits);
+ e -= std::numeric_limits<Float>::digits;
+#endif
+ number<Backend> num(f);
+ number<Backend> denom(1u);
+ if (e > 0)
+ {
+ num <<= e;
+ }
+ else if (e < 0)
+ {
+ denom <<= -e;
+ }
+ number<Backend> gcd;
+ eval_gcd(gcd.backend(), num.backend(), denom.backend());
+ if (!eval_eq(gcd.backend(), one()))
+ {
+ num /= gcd;
+ denom /= gcd;
+ }
+ this->num() = std::move(std::move(num).backend());
+ this->denom() = std::move(std::move(denom).backend());
+ return *this;
+ }
+
void swap(rational_adaptor& o)
{
- std::swap(m_value, o.m_value);
+ m_num.swap(o.m_num);
+ m_denom.swap(o.m_denom);
}
- std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
+ std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
{
+ using default_ops::eval_eq;
//
// We format the string ourselves so we can match what GMP's mpq type does:
//
- std::string result = data().numerator().str(digits, f);
- if(data().denominator() != 1)
+ std::string result = num().str(digits, f);
+ if (!eval_eq(denom(), one()))
{
result.append(1, '/');
- result.append(data().denominator().str(digits, f));
+ result.append(denom().str(digits, f));
}
return result;
}
void negate()
{
- m_value = -m_value;
- }
- int compare(const rational_adaptor& o)const
- {
- return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0);
+ m_num.negate();
}
- template <class Arithmatic>
- typename enable_if_c<is_arithmetic<Arithmatic>::value && !is_floating_point<Arithmatic>::value, int>::type compare(Arithmatic i)const
+ int compare(const rational_adaptor& o) const
{
- return m_value > i ? 1 : (m_value < i ? -1 : 0);
+ std::ptrdiff_t s1 = eval_get_sign(*this);
+ std::ptrdiff_t s2 = eval_get_sign(o);
+ if (s1 != s2)
+ {
+ return s1 < s2 ? -1 : 1;
+ }
+ else if (s1 == 0)
+ return 0; // both zero.
+
+ bool neg = false;
+ if (s1 >= 0)
+ {
+ s1 = eval_msb(num()) + eval_msb(o.denom());
+ s2 = eval_msb(o.num()) + eval_msb(denom());
+ }
+ else
+ {
+ Backend t(num());
+ t.negate();
+ s1 = eval_msb(t) + eval_msb(o.denom());
+ t = o.num();
+ t.negate();
+ s2 = eval_msb(t) + eval_msb(denom());
+ neg = true;
+ }
+ s1 -= s2;
+ if (s1 < -1)
+ return neg ? 1 : -1;
+ else if (s1 > 1)
+ return neg ? -1 : 1;
+
+ Backend t1, t2;
+ eval_multiply(t1, num(), o.denom());
+ eval_multiply(t2, o.num(), denom());
+ return t1.compare(t2);
}
- template <class Arithmatic>
- typename enable_if_c<is_floating_point<Arithmatic>::value, int>::type compare(Arithmatic i)const
+ //
+ // Comparison with arithmetic types, default just constructs a temporary:
+ //
+ template <class A>
+ typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, int>::type compare(A i) const
{
- rational_adaptor r;
- r = i;
- return this->compare(r);
+ rational_adaptor t;
+ t = i; // Note: construct directly from i if supported.
+ return compare(t);
}
- rational_type& data() { return m_value; }
- const rational_type& data()const { return m_value; }
+ Backend& num() { return m_num; }
+ const Backend& num()const { return m_num; }
+ Backend& denom() { return m_denom; }
+ const Backend& denom()const { return m_denom; }
+
+ #ifndef BOOST_MP_STANDALONE
template <class Archive>
- void serialize(Archive& ar, const mpl::true_&)
+ void serialize(Archive& ar, const std::integral_constant<bool, true>&)
{
// Saving
- integer_type n(m_value.numerator()), d(m_value.denominator());
- ar & n;
- ar & d;
+ number<Backend> n(num()), d(denom());
+ ar& boost::make_nvp("numerator", n);
+ ar& boost::make_nvp("denominator", d);
}
template <class Archive>
- void serialize(Archive& ar, const mpl::false_&)
+ void serialize(Archive& ar, const std::integral_constant<bool, false>&)
{
// Loading
- integer_type n, d;
- ar & n;
- ar & d;
- m_value.assign(n, d);
+ number<Backend> n, d;
+ ar& boost::make_nvp("numerator", n);
+ ar& boost::make_nvp("denominator", d);
+ num() = n.backend();
+ denom() = d.backend();
}
template <class Archive>
void serialize(Archive& ar, const unsigned int /*version*/)
{
- typedef typename Archive::is_saving tag;
- serialize(ar, tag());
+ using tag = typename Archive::is_saving;
+ using saving_tag = std::integral_constant<bool, tag::value>;
+ serialize(ar, saving_tag());
}
-private:
- rational_type m_value;
+ #endif // BOOST_MP_STANDALONE
+
+ private:
+ Backend m_num, m_denom;
};
-template <class IntBackend>
-inline void eval_add(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o)
+//
+// Helpers:
+//
+template <class T>
+inline constexpr typename std::enable_if<std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_signed, bool>::type
+is_minus_one(const T&)
{
- result.data() += o.data();
+ return false;
}
-template <class IntBackend>
-inline void eval_subtract(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o)
+template <class T>
+inline constexpr typename std::enable_if<!std::numeric_limits<T>::is_specialized || std::numeric_limits<T>::is_signed, bool>::type
+is_minus_one(const T& val)
{
- result.data() -= o.data();
+ return val == -1;
}
-template <class IntBackend>
-inline void eval_multiply(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o)
+
+//
+// Required non-members:
+//
+template <class Backend>
+inline void eval_add(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
{
- result.data() *= o.data();
+ eval_add_subtract_imp(a, a, b, true);
}
-template <class IntBackend>
-inline void eval_divide(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o)
+template <class Backend>
+inline void eval_subtract(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
{
- using default_ops::eval_is_zero;
- if(eval_is_zero(o))
- {
- BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero."));
- }
- result.data() /= o.data();
+ eval_add_subtract_imp(a, a, b, false);
}
+template <class Backend>
+inline void eval_multiply(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
+{
+ eval_multiply_imp(a, a, b.num(), b.denom());
+}
+
+template <class Backend>
+void eval_divide(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
+{
+ using default_ops::eval_divide;
+ rational_adaptor<Backend> t;
+ eval_divide(t, a, b);
+ a = std::move(t);
+}
+//
+// Conversions:
+//
template <class R, class IntBackend>
-inline typename enable_if_c<number_category<R>::value == number_kind_floating_point>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
+inline typename std::enable_if<number_category<R>::value == number_kind_floating_point>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
{
//
// The generic conversion is as good as anything we can write here:
@@ -244,122 +394,903 @@ inline typename enable_if_c<number_category<R>::value == number_kind_floating_po
}
template <class R, class IntBackend>
-inline typename enable_if_c<(number_category<R>::value != number_kind_integer) && (number_category<R>::value != number_kind_floating_point)>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
+inline typename std::enable_if<(number_category<R>::value != number_kind_integer) && (number_category<R>::value != number_kind_floating_point) && !std::is_enum<R>::value>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
{
- typedef typename component_type<number<rational_adaptor<IntBackend> > >::type comp_t;
- comp_t num(backend.data().numerator());
- comp_t denom(backend.data().denominator());
- *result = num.template convert_to<R>();
- *result /= denom.template convert_to<R>();
+ using default_ops::eval_convert_to;
+ R d;
+ eval_convert_to(result, backend.num());
+ eval_convert_to(&d, backend.denom());
+ *result /= d;
}
-template <class R, class IntBackend>
-inline typename enable_if_c<number_category<R>::value == number_kind_integer>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
+template <class R, class Backend>
+inline typename std::enable_if<number_category<R>::value == number_kind_integer>::type eval_convert_to(R* result, const rational_adaptor<Backend>& backend)
{
- typedef typename component_type<number<rational_adaptor<IntBackend> > >::type comp_t;
- comp_t t = backend.data().numerator();
- t /= backend.data().denominator();
- *result = t.template convert_to<R>();
+ using default_ops::eval_divide;
+ using default_ops::eval_convert_to;
+ Backend t;
+ eval_divide(t, backend.num(), backend.denom());
+ eval_convert_to(result, t);
}
-template <class IntBackend>
-inline bool eval_is_zero(const rational_adaptor<IntBackend>& val)
+//
+// Hashing support, not strictly required, but it is used in our tests:
+//
+template <class Backend>
+inline std::size_t hash_value(const rational_adaptor<Backend>& arg)
{
- return eval_is_zero(val.data().numerator().backend());
+ std::size_t result = hash_value(arg.num());
+ std::size_t result2 = hash_value(arg.denom());
+ boost::multiprecision::detail::hash_combine(result, result2);
+ return result;
}
-template <class IntBackend>
-inline int eval_get_sign(const rational_adaptor<IntBackend>& val)
+//
+// assign_components:
+//
+template <class Backend>
+void assign_components(rational_adaptor<Backend>& result, Backend const& a, Backend const& b)
{
- return eval_get_sign(val.data().numerator().backend());
+ using default_ops::eval_gcd;
+ using default_ops::eval_divide;
+ using default_ops::eval_eq;
+ using default_ops::eval_is_zero;
+ using default_ops::eval_get_sign;
+
+ if (eval_is_zero(b))
+ {
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
+ }
+ Backend g;
+ eval_gcd(g, a, b);
+ if (eval_eq(g, rational_adaptor<Backend>::one()))
+ {
+ result.num() = a;
+ result.denom() = b;
+ }
+ else
+ {
+ eval_divide(result.num(), a, g);
+ eval_divide(result.denom(), b, g);
+ }
+ if (eval_get_sign(result.denom()) < 0)
+ {
+ result.num().negate();
+ result.denom().negate();
+ }
}
+//
+// Again for arithmetic types, overload for whatever arithmetic types are directly supported:
+//
+template <class Backend, class Arithmetic1, class Arithmetic2>
+inline void assign_components(rational_adaptor<Backend>& result, const Arithmetic1& a, typename std::enable_if<std::is_arithmetic<Arithmetic1>::value && std::is_arithmetic<Arithmetic2>::value, const Arithmetic2&>::type b)
+{
+ using default_ops::eval_gcd;
+ using default_ops::eval_divide;
+ using default_ops::eval_eq;
+
+ if (b == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
+ }
-template<class IntBackend, class V>
-inline void assign_components(rational_adaptor<IntBackend>& result, const V& v1, const V& v2)
+ Backend g;
+ result.num() = a;
+ eval_gcd(g, result.num(), b);
+ if (eval_eq(g, rational_adaptor<Backend>::one()))
+ {
+ result.denom() = b;
+ }
+ else
+ {
+ eval_divide(result.num(), g);
+ eval_divide(result.denom(), b, g);
+ }
+ if (eval_get_sign(result.denom()) < 0)
+ {
+ result.num().negate();
+ result.denom().negate();
+ }
+}
+template <class Backend, class Arithmetic1, class Arithmetic2>
+inline void assign_components(rational_adaptor<Backend>& result, const Arithmetic1& a, typename std::enable_if<!std::is_arithmetic<Arithmetic1>::value || !std::is_arithmetic<Arithmetic2>::value, const Arithmetic2&>::type b)
{
- result.data().assign(v1, v2);
+ using default_ops::eval_gcd;
+ using default_ops::eval_divide;
+ using default_ops::eval_eq;
+
+ Backend g;
+ result.num() = a;
+ result.denom() = b;
+
+ if (eval_get_sign(result.denom()) == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
+ }
+
+ eval_gcd(g, result.num(), result.denom());
+ if (!eval_eq(g, rational_adaptor<Backend>::one()))
+ {
+ eval_divide(result.num(), g);
+ eval_divide(result.denom(), g);
+ }
+ if (eval_get_sign(result.denom()) < 0)
+ {
+ result.num().negate();
+ result.denom().negate();
+ }
+}
+//
+// Optional comparison operators:
+//
+template <class Backend>
+inline bool eval_is_zero(const rational_adaptor<Backend>& arg)
+{
+ using default_ops::eval_is_zero;
+ return eval_is_zero(arg.num());
}
-template <class IntBackend>
-inline std::size_t hash_value(const rational_adaptor<IntBackend>& val)
+template <class Backend>
+inline int eval_get_sign(const rational_adaptor<Backend>& arg)
{
- std::size_t result = hash_value(val.data().numerator());
- boost::hash_combine(result, val.data().denominator());
- return result;
+ using default_ops::eval_get_sign;
+ return eval_get_sign(arg.num());
}
+template <class Backend>
+inline bool eval_eq(const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
+{
+ using default_ops::eval_eq;
+ return eval_eq(a.num(), b.num()) && eval_eq(a.denom(), b.denom());
+}
-} // namespace backends
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value, bool>::type
+ eval_eq(const rational_adaptor<Backend>& a, Arithmetic b)
+{
+ using default_ops::eval_eq;
+ return eval_eq(a.denom(), rational_adaptor<Backend>::one()) && eval_eq(a.num(), b);
+}
-template<class IntBackend>
-struct expression_template_default<backends::rational_adaptor<IntBackend> > : public expression_template_default<IntBackend> {};
-
-template<class IntBackend>
-struct number_category<backends::rational_adaptor<IntBackend> > : public mpl::int_<number_kind_rational>{};
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value, bool>::type
+ eval_eq(Arithmetic b, const rational_adaptor<Backend>& a)
+{
+ using default_ops::eval_eq;
+ return eval_eq(a.denom(), rational_adaptor<Backend>::one()) && eval_eq(a.num(), b);
+}
-using boost::multiprecision::backends::rational_adaptor;
+//
+// Arithmetic operations, starting with addition:
+//
+template <class Backend, class Arithmetic>
+void eval_add_subtract_imp(rational_adaptor<Backend>& result, const Arithmetic& arg, bool isaddition)
+{
+ using default_ops::eval_multiply;
+ using default_ops::eval_divide;
+ using default_ops::eval_add;
+ using default_ops::eval_gcd;
+ Backend t;
+ eval_multiply(t, result.denom(), arg);
+ if (isaddition)
+ eval_add(result.num(), t);
+ else
+ eval_subtract(result.num(), t);
+ //
+ // There is no need to re-normalize here, we have
+ // (a + bm) / b
+ // and gcd(a + bm, b) = gcd(a, b) = 1
+ //
+ /*
+ eval_gcd(t, result.num(), result.denom());
+ if (!eval_eq(t, rational_adaptor<Backend>::one()) != 0)
+ {
+ Backend t2;
+ eval_divide(t2, result.num(), t);
+ t2.swap(result.num());
+ eval_divide(t2, result.denom(), t);
+ t2.swap(result.denom());
+ }
+ */
+}
-template <class T>
-struct component_type<rational_adaptor<T> >
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
+ eval_add(rational_adaptor<Backend>& result, const Arithmetic& arg)
{
- typedef number<T> type;
-};
+ eval_add_subtract_imp(result, arg, true);
+}
-template <class IntBackend, expression_template_option ET>
-inline number<IntBackend, ET> numerator(const number<rational_adaptor<IntBackend>, ET>& val)
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
+ eval_subtract(rational_adaptor<Backend>& result, const Arithmetic& arg)
{
- return val.backend().data().numerator();
+ eval_add_subtract_imp(result, arg, false);
}
-template <class IntBackend, expression_template_option ET>
-inline number<IntBackend, ET> denominator(const number<rational_adaptor<IntBackend>, ET>& val)
+
+template <class Backend>
+void eval_add_subtract_imp(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b, bool isaddition)
{
- return val.backend().data().denominator();
+ using default_ops::eval_eq;
+ using default_ops::eval_multiply;
+ using default_ops::eval_divide;
+ using default_ops::eval_add;
+ using default_ops::eval_subtract;
+ //
+ // Let a = an/ad
+ // b = bn/bd
+ // g = gcd(ad, bd)
+ // result = rn/rd
+ //
+ // Then:
+ // rn = an * (bd/g) + bn * (ad/g)
+ // rd = ad * (bd/g)
+ // = (ad/g) * (bd/g) * g
+ //
+ // And the whole thing can then be rescaled by
+ // gcd(rn, g)
+ //
+ Backend gcd, t1, t2, t3, t4;
+ //
+ // Begin by getting the gcd of the 2 denominators:
+ //
+ eval_gcd(gcd, a.denom(), b.denom());
+ //
+ // Do we have gcd > 1:
+ //
+ if (!eval_eq(gcd, rational_adaptor<Backend>::one()))
+ {
+ //
+ // Scale the denominators by gcd, and put the results in t1 and t2:
+ //
+ eval_divide(t1, b.denom(), gcd);
+ eval_divide(t2, a.denom(), gcd);
+ //
+ // multiply the numerators by the scale denominators and put the results in t3, t4:
+ //
+ eval_multiply(t3, a.num(), t1);
+ eval_multiply(t4, b.num(), t2);
+ //
+ // Add them up:
+ //
+ if (isaddition)
+ eval_add(t3, t4);
+ else
+ eval_subtract(t3, t4);
+ //
+ // Get the gcd of gcd and our numerator (t3):
+ //
+ eval_gcd(t4, t3, gcd);
+ if (eval_eq(t4, rational_adaptor<Backend>::one()))
+ {
+ result.num() = t3;
+ eval_multiply(result.denom(), t1, a.denom());
+ }
+ else
+ {
+ //
+ // Uncommon case where gcd is not 1, divide the numerator
+ // and the denominator terms by the new gcd. Note we perform division
+ // on the existing gcd value as this is the smallest of the 3 denominator
+ // terms we'll be multiplying together, so there's a good chance it's a
+ // single limb value already:
+ //
+ eval_divide(result.num(), t3, t4);
+ eval_divide(t3, gcd, t4);
+ eval_multiply(t4, t1, t2);
+ eval_multiply(result.denom(), t4, t3);
+ }
+ }
+ else
+ {
+ //
+ // Most common case (approx 60%) where gcd is one:
+ //
+ eval_multiply(t1, a.num(), b.denom());
+ eval_multiply(t2, a.denom(), b.num());
+ if (isaddition)
+ eval_add(result.num(), t1, t2);
+ else
+ eval_subtract(result.num(), t1, t2);
+ eval_multiply(result.denom(), a.denom(), b.denom());
+ }
}
-#ifdef BOOST_NO_SFINAE_EXPR
-namespace detail{
+template <class Backend>
+inline void eval_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
+{
+ eval_add_subtract_imp(result, a, b, true);
+}
+template <class Backend>
+inline void eval_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
+{
+ eval_add_subtract_imp(result, a, b, false);
+}
-template<class U, class IntBackend>
-struct is_explicitly_convertible<U, rational_adaptor<IntBackend> > : public is_explicitly_convertible<U, IntBackend> {};
+template <class Backend, class Arithmetic>
+void eval_add_subtract_imp(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b, bool isaddition)
+{
+ using default_ops::eval_add;
+ using default_ops::eval_subtract;
+ using default_ops::eval_multiply;
+
+ if (&result == &a)
+ return eval_add_subtract_imp(result, b, isaddition);
+ eval_multiply(result.num(), a.denom(), b);
+ if (isaddition)
+ eval_add(result.num(), a.num());
+ else
+ BOOST_IF_CONSTEXPR(std::numeric_limits<Backend>::is_signed == false)
+ {
+ Backend t;
+ eval_subtract(t, a.num(), result.num());
+ result.num() = std::move(t);
+ }
+ else
+ {
+ eval_subtract(result.num(), a.num());
+ result.negate();
+ }
+ result.denom() = a.denom();
+ //
+ // There is no need to re-normalize here, we have
+ // (a + bm) / b
+ // and gcd(a + bm, b) = gcd(a, b) = 1
+ //
+}
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
+ eval_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b)
+{
+ eval_add_subtract_imp(result, a, b, true);
+}
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
+ eval_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b)
+{
+ eval_add_subtract_imp(result, a, b, false);
}
-#endif
+//
+// Multiplication:
+//
+template <class Backend>
+void eval_multiply_imp(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Backend& b_num, const Backend& b_denom)
+{
+ using default_ops::eval_multiply;
+ using default_ops::eval_divide;
+ using default_ops::eval_gcd;
+ using default_ops::eval_get_sign;
+ using default_ops::eval_eq;
-}} // namespaces
+ Backend gcd_left, gcd_right, t1, t2;
+ eval_gcd(gcd_left, a.num(), b_denom);
+ eval_gcd(gcd_right, b_num, a.denom());
+ //
+ // Unit gcd's are the most likely case:
+ //
+ bool b_left = eval_eq(gcd_left, rational_adaptor<Backend>::one());
+ bool b_right = eval_eq(gcd_right, rational_adaptor<Backend>::one());
+ if (b_left && b_right)
+ {
+ eval_multiply(result.num(), a.num(), b_num);
+ eval_multiply(result.denom(), a.denom(), b_denom);
+ }
+ else if (b_left)
+ {
+ eval_divide(t2, b_num, gcd_right);
+ eval_multiply(result.num(), a.num(), t2);
+ eval_divide(t1, a.denom(), gcd_right);
+ eval_multiply(result.denom(), t1, b_denom);
+ }
+ else if (b_right)
+ {
+ eval_divide(t1, a.num(), gcd_left);
+ eval_multiply(result.num(), t1, b_num);
+ eval_divide(t2, b_denom, gcd_left);
+ eval_multiply(result.denom(), a.denom(), t2);
+ }
+ else
+ {
+ eval_divide(t1, a.num(), gcd_left);
+ eval_divide(t2, b_num, gcd_right);
+ eval_multiply(result.num(), t1, t2);
+ eval_divide(t1, a.denom(), gcd_right);
+ eval_divide(t2, b_denom, gcd_left);
+ eval_multiply(result.denom(), t1, t2);
+ }
+ //
+ // We may have b_denom negative if this is actually division, if so just correct things now:
+ //
+ if (eval_get_sign(b_denom) < 0)
+ {
+ result.num().negate();
+ result.denom().negate();
+ }
+}
+
+template <class Backend>
+void eval_multiply(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
+{
+ using default_ops::eval_multiply;
-namespace std{
+ if (&a == &b)
+ {
+ // squaring, gcd's are 1:
+ eval_multiply(result.num(), a.num(), b.num());
+ eval_multiply(result.denom(), a.denom(), b.denom());
+ return;
+ }
+ eval_multiply_imp(result, a, b.num(), b.denom());
+}
-template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
-class numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> > : public std::numeric_limits<boost::multiprecision::number<IntBackend, ExpressionTemplates> >
+template <class Backend, class Arithmetic>
+void eval_multiply_imp(Backend& result_num, Backend& result_denom, Arithmetic arg)
{
- typedef std::numeric_limits<boost::multiprecision::number<IntBackend> > base_type;
- typedef boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend> > number_type;
-public:
- BOOST_STATIC_CONSTEXPR bool is_integer = false;
- BOOST_STATIC_CONSTEXPR bool is_exact = true;
- BOOST_STATIC_CONSTEXPR number_type (min)() { return (base_type::min)(); }
- BOOST_STATIC_CONSTEXPR number_type (max)() { return (base_type::max)(); }
- BOOST_STATIC_CONSTEXPR number_type lowest() { return -(max)(); }
- BOOST_STATIC_CONSTEXPR number_type epsilon() { return base_type::epsilon(); }
- BOOST_STATIC_CONSTEXPR number_type round_error() { return epsilon() / 2; }
- BOOST_STATIC_CONSTEXPR number_type infinity() { return base_type::infinity(); }
- BOOST_STATIC_CONSTEXPR number_type quiet_NaN() { return base_type::quiet_NaN(); }
- BOOST_STATIC_CONSTEXPR number_type signaling_NaN() { return base_type::signaling_NaN(); }
- BOOST_STATIC_CONSTEXPR number_type denorm_min() { return base_type::denorm_min(); }
-};
+ if (arg == 0)
+ {
+ result_num = rational_adaptor<Backend>::zero();
+ result_denom = rational_adaptor<Backend>::one();
+ return;
+ }
+ else if (arg == 1)
+ return;
-#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+ using default_ops::eval_multiply;
+ using default_ops::eval_divide;
+ using default_ops::eval_gcd;
+ using default_ops::eval_convert_to;
-template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_integer;
-template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
-BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_exact;
+ Backend gcd, t;
+ Arithmetic integer_gcd;
+ eval_gcd(gcd, result_denom, arg);
+ eval_convert_to(&integer_gcd, gcd);
+ arg /= integer_gcd;
+ if (boost::multiprecision::detail::unsigned_abs(arg) > 1)
+ {
+ eval_multiply(t, result_num, arg);
+ result_num = std::move(t);
+ }
+ else if (is_minus_one(arg))
+ result_num.negate();
+ if (integer_gcd > 1)
+ {
+ eval_divide(t, result_denom, integer_gcd);
+ result_denom = std::move(t);
+ }
+}
+template <class Backend>
+void eval_multiply_imp(Backend& result_num, Backend& result_denom, Backend arg)
+{
+ using default_ops::eval_multiply;
+ using default_ops::eval_divide;
+ using default_ops::eval_gcd;
+ using default_ops::eval_convert_to;
+ using default_ops::eval_is_zero;
+ using default_ops::eval_eq;
+ using default_ops::eval_get_sign;
-#endif
+ if (eval_is_zero(arg))
+ {
+ result_num = rational_adaptor<Backend>::zero();
+ result_denom = rational_adaptor<Backend>::one();
+ return;
+ }
+ else if (eval_eq(arg, rational_adaptor<Backend>::one()))
+ return;
+
+ Backend gcd, t;
+ eval_gcd(gcd, result_denom, arg);
+ if (!eval_eq(gcd, rational_adaptor<Backend>::one()))
+ {
+ eval_divide(t, arg, gcd);
+ arg = t;
+ }
+ else
+ t = arg;
+ if (eval_get_sign(arg) < 0)
+ t.negate();
+
+ if (!eval_eq(t, rational_adaptor<Backend>::one()))
+ {
+ eval_multiply(t, result_num, arg);
+ result_num = std::move(t);
+ }
+ else if (eval_get_sign(arg) < 0)
+ result_num.negate();
+ if (!eval_eq(gcd, rational_adaptor<Backend>::one()))
+ {
+ eval_divide(t, result_denom, gcd);
+ result_denom = std::move(t);
+ }
+}
+
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
+ eval_multiply(rational_adaptor<Backend>& result, const Arithmetic& arg)
+{
+ eval_multiply_imp(result.num(), result.denom(), arg);
+}
+
+template <class Backend, class Arithmetic>
+typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
+ eval_multiply_imp(rational_adaptor<Backend>& result, const Backend& a_num, const Backend& a_denom, Arithmetic b)
+{
+ if (b == 0)
+ {
+ result.num() = rational_adaptor<Backend>::zero();
+ result.denom() = rational_adaptor<Backend>::one();
+ return;
+ }
+ else if (b == 1)
+ {
+ result.num() = a_num;
+ result.denom() = a_denom;
+ return;
+ }
+
+ using default_ops::eval_multiply;
+ using default_ops::eval_divide;
+ using default_ops::eval_gcd;
+ using default_ops::eval_convert_to;
+
+ Backend gcd;
+ Arithmetic integer_gcd;
+ eval_gcd(gcd, a_denom, b);
+ eval_convert_to(&integer_gcd, gcd);
+ b /= integer_gcd;
+ if (boost::multiprecision::detail::unsigned_abs(b) > 1)
+ eval_multiply(result.num(), a_num, b);
+ else if (is_minus_one(b))
+ {
+ result.num() = a_num;
+ result.num().negate();
+ }
+ else
+ result.num() = a_num;
+ if (integer_gcd > 1)
+ eval_divide(result.denom(), a_denom, integer_gcd);
+ else
+ result.denom() = a_denom;
+}
+template <class Backend>
+inline void eval_multiply_imp(rational_adaptor<Backend>& result, const Backend& a_num, const Backend& a_denom, const Backend& b)
+{
+ result.num() = a_num;
+ result.denom() = a_denom;
+ eval_multiply_imp(result.num(), result.denom(), b);
+}
+
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
+ eval_multiply(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b)
+{
+ if (&result == &a)
+ return eval_multiply(result, b);
+
+ eval_multiply_imp(result, a.num(), a.denom(), b);
+}
+
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
+ eval_multiply(rational_adaptor<Backend>& result, const Arithmetic& b, const rational_adaptor<Backend>& a)
+{
+ return eval_multiply(result, a, b);
+}
+
+//
+// Division:
+//
+template <class Backend>
+inline void eval_divide(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
+{
+ using default_ops::eval_multiply;
+ using default_ops::eval_get_sign;
+
+ if (eval_get_sign(b.num()) == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
+ return;
+ }
+ if (&a == &b)
+ {
+ // Huh? Really?
+ result.num() = result.denom() = rational_adaptor<Backend>::one();
+ return;
+ }
+ if (&result == &b)
+ {
+ rational_adaptor<Backend> t(b);
+ return eval_divide(result, a, t);
+ }
+ eval_multiply_imp(result, a, b.denom(), b.num());
+}
+
+template <class Backend, class Arithmetic>
+inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
+ eval_divide(rational_adaptor<Backend>& result, const Arithmetic& b, const rational_adaptor<Backend>& a)
+{
+ using default_ops::eval_get_sign;
+
+ if (eval_get_sign(a.num()) == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
+ return;
+ }
+ if (&a == &result)
+ {
+ eval_multiply_imp(result.denom(), result.num(), b);
+ result.num().swap(result.denom());
+ }
+ else
+ eval_multiply_imp(result, a.denom(), a.num(), b);
+
+ if (eval_get_sign(result.denom()) < 0)
+ {
+ result.num().negate();
+ result.denom().negate();
+ }
+}
+
+template <class Backend, class Arithmetic>
+typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
+eval_divide(rational_adaptor<Backend>& result, Arithmetic arg)
+{
+ if (arg == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
+ return;
+ }
+ else if (arg == 1)
+ return;
+ else if (is_minus_one(arg))
+ {
+ result.negate();
+ return;
+ }
+ if (eval_get_sign(result) == 0)
+ {
+ return;
+ }
+
+
+ using default_ops::eval_multiply;
+ using default_ops::eval_gcd;
+ using default_ops::eval_convert_to;
+ using default_ops::eval_divide;
+
+ Backend gcd, t;
+ Arithmetic integer_gcd;
+ eval_gcd(gcd, result.num(), arg);
+ eval_convert_to(&integer_gcd, gcd);
+ arg /= integer_gcd;
+
+ eval_multiply(t, result.denom(), boost::multiprecision::detail::unsigned_abs(arg));
+ result.denom() = std::move(t);
+ if (arg < 0)
+ {
+ result.num().negate();
+ }
+ if (integer_gcd > 1)
+ {
+ eval_divide(t, result.num(), integer_gcd);
+ result.num() = std::move(t);
+ }
+}
+template <class Backend>
+void eval_divide(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, Backend arg)
+{
+ using default_ops::eval_multiply;
+ using default_ops::eval_gcd;
+ using default_ops::eval_convert_to;
+ using default_ops::eval_divide;
+ using default_ops::eval_is_zero;
+ using default_ops::eval_eq;
+ using default_ops::eval_get_sign;
+
+ if (eval_is_zero(arg))
+ {
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
+ return;
+ }
+ else if (eval_eq(a, rational_adaptor<Backend>::one()) || (eval_get_sign(a) == 0))
+ {
+ if (&result != &a)
+ result = a;
+ return;
+ }
+
+ Backend gcd, u_arg, t;
+ eval_gcd(gcd, a.num(), arg);
+ bool has_unit_gcd = eval_eq(gcd, rational_adaptor<Backend>::one());
+ if (!has_unit_gcd)
+ {
+ eval_divide(u_arg, arg, gcd);
+ arg = u_arg;
+ }
+ else
+ u_arg = arg;
+ if (eval_get_sign(u_arg) < 0)
+ u_arg.negate();
+
+ eval_multiply(t, a.denom(), u_arg);
+ result.denom() = std::move(t);
+
+ if (!has_unit_gcd)
+ {
+ eval_divide(t, a.num(), gcd);
+ result.num() = std::move(t);
+ }
+ else if (&result != &a)
+ result.num() = a.num();
+
+ if (eval_get_sign(arg) < 0)
+ {
+ result.num().negate();
+ }
+}
+template <class Backend>
+void eval_divide(rational_adaptor<Backend>& result, Backend arg)
+{
+ eval_divide(result, result, arg);
+}
+
+template <class Backend, class Arithmetic>
+typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
+ eval_divide(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, Arithmetic arg)
+{
+ if (&result == &a)
+ return eval_divide(result, arg);
+ if (arg == 0)
+ {
+ BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
+ return;
+ }
+ else if (arg == 1)
+ {
+ result = a;
+ return;
+ }
+ else if (is_minus_one(arg))
+ {
+ result = a;
+ result.num().negate();
+ return;
+ }
+
+ if (eval_get_sign(a) == 0)
+ {
+ result = a;
+ return;
+ }
+
+ using default_ops::eval_multiply;
+ using default_ops::eval_divide;
+ using default_ops::eval_gcd;
+ using default_ops::eval_convert_to;
+
+ Backend gcd;
+ Arithmetic integer_gcd;
+ eval_gcd(gcd, a.num(), arg);
+ eval_convert_to(&integer_gcd, gcd);
+ arg /= integer_gcd;
+ eval_multiply(result.denom(), a.denom(), boost::multiprecision::detail::unsigned_abs(arg));
+
+ if (integer_gcd > 1)
+ {
+ eval_divide(result.num(), a.num(), integer_gcd);
+ }
+ else
+ result.num() = a.num();
+ if (arg < 0)
+ {
+ result.num().negate();
+ }
+}
+//
+// Increment and decrement:
+//
+template <class Backend>
+inline void eval_increment(rational_adaptor<Backend>& arg)
+{
+ using default_ops::eval_add;
+ eval_add(arg.num(), arg.denom());
+}
+template <class Backend>
+inline void eval_decrement(rational_adaptor<Backend>& arg)
+{
+ using default_ops::eval_subtract;
+ eval_subtract(arg.num(), arg.denom());
+}
+//
+// abs:
+//
+template <class Backend>
+inline void eval_abs(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& arg)
+{
+ using default_ops::eval_abs;
+ eval_abs(result.num(), arg.num());
+ result.denom() = arg.denom();
}
+} // namespace backends
+
+//
+// Import the backend into this namespace:
+//
+using boost::multiprecision::backends::rational_adaptor;
+//
+// Define a category for this number type, one of:
+//
+// number_kind_integer
+// number_kind_floating_point
+// number_kind_rational
+// number_kind_fixed_point
+// number_kind_complex
+//
+template<class Backend>
+struct number_category<rational_adaptor<Backend> > : public std::integral_constant<int, number_kind_rational>
+{};
+
+template <class IntBackend>
+struct expression_template_default<backends::rational_adaptor<IntBackend> > : public expression_template_default<IntBackend>
+{};
+
+template <class Backend, expression_template_option ExpressionTemplates>
+struct component_type<number<rational_adaptor<Backend>, ExpressionTemplates> >
+{
+ typedef number<Backend, ExpressionTemplates> type;
+};
+
+template <class IntBackend, expression_template_option ET>
+inline number<IntBackend, ET> numerator(const number<rational_adaptor<IntBackend>, ET>& val)
+{
+ return val.backend().num();
+}
+template <class IntBackend, expression_template_option ET>
+inline number<IntBackend, ET> denominator(const number<rational_adaptor<IntBackend>, ET>& val)
+{
+ return val.backend().denom();
+}
+
+template <class Backend>
+struct is_unsigned_number<rational_adaptor<Backend> > : public is_unsigned_number<Backend>
+{};
+
+
+}} // namespace boost::multiprecision
+
+namespace std {
+
+ template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
+ class numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> > : public std::numeric_limits<boost::multiprecision::number<IntBackend, ExpressionTemplates> >
+ {
+ using base_type = std::numeric_limits<boost::multiprecision::number<IntBackend> >;
+ using number_type = boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend> >;
+
+ public:
+ static constexpr bool is_integer = false;
+ static constexpr bool is_exact = true;
+ static constexpr number_type(min)() { return (base_type::min)(); }
+ static constexpr number_type(max)() { return (base_type::max)(); }
+ static constexpr number_type lowest() { return -(max)(); }
+ static constexpr number_type epsilon() { return base_type::epsilon(); }
+ static constexpr number_type round_error() { return epsilon() / 2; }
+ static constexpr number_type infinity() { return base_type::infinity(); }
+ static constexpr number_type quiet_NaN() { return base_type::quiet_NaN(); }
+ static constexpr number_type signaling_NaN() { return base_type::signaling_NaN(); }
+ static constexpr number_type denorm_min() { return base_type::denorm_min(); }
+ };
+
+ template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
+ constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_integer;
+ template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
+ constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_exact;
+
+} // namespace std
+
#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/explicit_conversion.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/explicit_conversion.hpp
index 0a14f03442..e32534eea8 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/explicit_conversion.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/explicit_conversion.hpp
@@ -4,87 +4,64 @@
// 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_MP_EXPLICIT_CONVERTIBLE_HPP
-#define BOOST_MP_EXPLICIT_CONVERTIBLE_HPP
-
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/utility/declval.hpp>
+#ifndef BOOST_MP_EXPLICIT_CONVERSION_HPP
+#define BOOST_MP_EXPLICIT_CONVERSION_HPP
+#include <type_traits>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/number_base.hpp> // number_category
namespace boost {
- namespace multiprecision {
- namespace detail {
+namespace multiprecision {
+namespace detail {
- template <int N>
- struct dummy_size {};
+template <unsigned int N>
+struct dummy_size
+{};
- template<typename S, typename T>
- struct has_generic_interconversion
- {
- typedef typename mpl::if_c <
- is_number<S>::value && is_number<T>::value,
- typename mpl::if_c <
- number_category<S>::value == number_kind_integer,
- typename mpl::if_c<
- number_category<T>::value == number_kind_integer
- || number_category<T>::value == number_kind_floating_point
- || number_category<T>::value == number_kind_rational
- || number_category<T>::value == number_kind_fixed_point,
- mpl::true_,
- mpl::false_
- >::type,
- typename mpl::if_c<
+template <typename S, typename T>
+struct has_generic_interconversion
+{
+ using type = typename std::conditional<
+ is_number<S>::value && is_number<T>::value,
+ typename std::conditional<
+ number_category<S>::value == number_kind_integer,
+ typename std::conditional<
+ number_category<T>::value == number_kind_integer || number_category<T>::value == number_kind_floating_point || number_category<T>::value == number_kind_rational || number_category<T>::value == number_kind_fixed_point,
+ std::true_type,
+ std::false_type >::type,
+ typename std::conditional<
number_category<S>::value == number_kind_rational,
- typename mpl::if_c<
- number_category<T>::value == number_kind_rational
- || number_category<T>::value == number_kind_rational,
- mpl::true_,
- mpl::false_
- >::type,
- typename mpl::if_c<
- number_category<T>::value == number_kind_floating_point,
- mpl::true_,
- mpl::false_
- >::type
- >::type
- > ::type,
- mpl::false_
- > ::type type;
- };
-
- template<typename S, typename T>
- struct is_explicitly_convertible_imp
- {
-#ifndef BOOST_NO_SFINAE_EXPR
- template<typename S1, typename T1>
- static type_traits::yes_type selector(dummy_size<sizeof(static_cast<T1>(declval<S1>()))>*);
+ typename std::conditional<
+ number_category<T>::value == number_kind_rational || number_category<T>::value == number_kind_rational,
+ std::true_type,
+ std::false_type >::type,
+ typename std::conditional<
+ number_category<T>::value == number_kind_floating_point,
+ std::true_type,
+ std::false_type >::type>::type>::type,
+ std::false_type >::type;
+};
- template<typename S1, typename T1>
- static type_traits::no_type selector(...);
+template <typename S, typename T>
+struct is_explicitly_convertible_imp
+{
+ template <typename S1, typename T1>
+ static int selector(dummy_size<static_cast<unsigned int>(sizeof(new T1(std::declval<S1>())))>*);
- static const bool value = sizeof(selector<S, T>(0)) == sizeof(type_traits::yes_type);
+ template <typename S1, typename T1>
+ static char selector(...);
- typedef boost::integral_constant<bool, value> type;
-#else
- typedef typename has_generic_interconversion<S, T>::type gen_type;
- typedef mpl::bool_<boost::is_convertible<S, T>::value || gen_type::value> type;
-#endif
- };
+ static constexpr bool value = sizeof(selector<S, T>(nullptr)) == sizeof(int);
-template<typename From, typename To>
-struct is_explicitly_convertible : public is_explicitly_convertible_imp<From, To>::type
-{
+ using type = std::integral_constant<bool, value>;
};
-#ifdef BOOST_NO_SFINAE_EXPR
-template<class Backend1, expression_template_option ExpressionTemplates1, class Backend2, expression_template_option ExpressionTemplates2>
-struct is_explicitly_convertible<number<Backend1, ExpressionTemplates1>, number<Backend2, ExpressionTemplates2> >
- : public is_explicitly_convertible<Backend1, Backend2>
+template <typename From, typename To>
+struct is_explicitly_convertible : public is_explicitly_convertible_imp<From, To>::type
{
};
-#endif
-}}} // namespaces
+}}} // namespace boost::multiprecision::detail
#endif
-
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_backend.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_backend.hpp
index 2a26b19df0..46cee4df37 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_backend.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_backend.hpp
@@ -6,58 +6,86 @@
#ifndef BOOST_MP_IS_BACKEND_HPP
#define BOOST_MP_IS_BACKEND_HPP
-#include <boost/mpl/has_xxx.hpp>
-#include <boost/type_traits/conditional.hpp>
-#include <boost/type_traits/is_convertible.hpp>
+#include <type_traits>
#include <boost/multiprecision/detail/number_base.hpp>
-namespace boost{ namespace multiprecision{ namespace detail{
-
- BOOST_MPL_HAS_XXX_TRAIT_DEF(signed_types)
- BOOST_MPL_HAS_XXX_TRAIT_DEF(unsigned_types)
- BOOST_MPL_HAS_XXX_TRAIT_DEF(float_types)
-
- template <class T>
- struct is_backend
- {
- static const bool value = has_signed_types<T>::value && has_unsigned_types<T>::value && has_float_types<T>::value;
- };
-
- template <class Backend>
- struct other_backend
- {
- typedef typename boost::conditional<
- boost::is_same<number<Backend>, number<Backend, et_on> >::value,
- number<Backend, et_off>, number<Backend, et_on> >::type type;
- };
-
- template <class B, class V>
- struct number_from_backend
- {
- typedef typename boost::conditional <
- boost::is_convertible<V, number<B> >::value,
- number<B>,
- typename other_backend<B>::type > ::type type;
- };
-
- template <bool b, class T, class U>
- struct is_first_backend_imp{ static const bool value = false; };
- template <class T, class U>
- struct is_first_backend_imp<true, T, U>{ static const bool value = is_convertible<U, number<T, et_on> >::value || is_convertible<U, number<T, et_off> >::value; };
-
- template <class T, class U>
- struct is_first_backend : is_first_backend_imp<is_backend<T>::value, T, U> {};
-
- template <bool b, class T, class U>
- struct is_second_backend_imp{ static const bool value = false; };
- template <class T, class U>
- struct is_second_backend_imp<true, T, U>{ static const bool value = (is_convertible<T, number<U, et_on> >::value || is_convertible<T, number<U, et_off> >::value) && !is_first_backend<T, U>::value; };
-
- template <class T, class U>
- struct is_second_backend : is_second_backend_imp<is_backend<U>::value, T, U> {};
+namespace boost { namespace multiprecision { namespace detail {
+
+template <class T>
+struct has_signed_types
+{
+ template <class U>
+ static double check(U*, typename U::signed_types* = nullptr);
+ static char check(...);
+ static T* get();
+ static constexpr bool value = sizeof(check(get())) == sizeof(double);
+};
+template <class T>
+struct has_unsigned_types
+{
+ template <class U>
+ static double check(U*, typename U::unsigned_types* = nullptr);
+ static char check(...);
+ static T* get();
+ static constexpr bool value = sizeof(check(get())) == sizeof(double);
+};
+template <class T>
+struct has_float_types
+{
+ template <class U>
+ static double check(U*, typename U::float_types* = nullptr);
+ static char check(...);
+ static T* get();
+ static constexpr bool value = sizeof(check(get())) == sizeof(double);
+};
+
+template <class T>
+struct is_backend : public std::integral_constant<bool, has_signed_types<T>::value && has_unsigned_types<T>::value && has_float_types<T>::value> {};
+
+template <class Backend>
+struct other_backend
+{
+ using type = typename std::conditional<
+ std::is_same<number<Backend>, number<Backend, et_on> >::value,
+ number<Backend, et_off>, number<Backend, et_on> >::type;
+};
+
+template <class B, class V>
+struct number_from_backend
+{
+ using type = typename std::conditional<
+ std::is_convertible<V, number<B> >::value,
+ number<B>,
+ typename other_backend<B>::type>::type;
+};
+
+template <bool b, class T, class U>
+struct is_first_backend_imp : public std::false_type {};
+
+template <class T, class U>
+ struct is_first_backend_imp<true, T, U> : public std::integral_constant < bool, std::is_convertible<U, number<T, et_on> >::value || std::is_convertible<U, number<T, et_off> >::value> {};
+
+template <class T, class U>
+struct is_first_backend : is_first_backend_imp<is_backend<T>::value, T, U>
+{};
+
+template <bool b, class T, class U>
+struct is_second_backend_imp
+{
+ static constexpr bool value = false;
+};
+template <class T, class U>
+struct is_second_backend_imp<true, T, U>
+{
+ static constexpr bool value = (std::is_convertible<T, number<U, et_on> >::value || std::is_convertible<T, number<U, et_off> >::value) && !is_first_backend<T, U>::value;
+};
+
+template <class T, class U>
+struct is_second_backend : is_second_backend_imp<is_backend<U>::value, T, U>
+{};
}
}
-}
+} // namespace boost::multiprecision::detail
#endif // BOOST_MP_IS_BACKEND_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_byte_container.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_byte_container.hpp
index d97428f0f2..998a704214 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_byte_container.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_byte_container.hpp
@@ -6,28 +6,46 @@
#ifndef BOOST_IS_BYTE_CONTAINER_HPP
#define BOOST_IS_BYTE_CONTAINER_HPP
-#include <boost/mpl/has_xxx.hpp>
-#include <boost/type_traits/is_integral.hpp>
+#include <iterator>
+#include <type_traits>
-namespace boost{ namespace multiprecision{ namespace detail{
+namespace boost { namespace multiprecision { namespace detail {
- BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_value_type, value_type, false)
- BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_const_iterator, const_iterator, false)
+template <class T>
+struct has_member_const_iterator
+{
+ template <class U>
+ static double check(U*, typename U::const_iterator* = nullptr);
+ static char check(...);
+ static T* get();
+ static constexpr bool value = sizeof(check(get())) == sizeof(double);
+};
- template <class C, bool b>
- struct is_byte_container_imp
- {
- static const bool value = boost::is_integral<typename C::value_type>::value && (sizeof(typename C::value_type) == 1);
- };
- template <class C>
- struct is_byte_container_imp<C, false> : public boost::false_type {};
+template <class C, class Iterator>
+struct is_byte_container_imp_2
+{
+ using container_value_type = typename std::remove_cv<typename std::iterator_traits<typename C::const_iterator>::value_type>::type;
+ static constexpr bool value = boost::multiprecision::detail::is_integral<container_value_type>::value && (sizeof(container_value_type) == 1);
+};
- template <class C>
- struct is_byte_container : public is_byte_container_imp<C, has_member_value_type<C>::value && has_member_const_iterator<C>::value> {};
+template <class C>
+struct is_byte_container_imp_2<C, void> : public std::false_type
+{};
+template <class C, bool b>
+struct is_byte_container_imp : public is_byte_container_imp_2<C, typename C::const_iterator>
+{
+};
-}}} // namespaces
+template <class C>
+struct is_byte_container_imp<C, false> : public std::false_type
+{};
-#endif // BOOST_IS_BYTE_CONTAINER_HPP
+template <class C>
+struct is_byte_container : public is_byte_container_imp<C, has_member_const_iterator<C>::value>
+{};
+
+}}} // namespace boost::multiprecision::detail
+#endif // BOOST_IS_BYTE_CONTAINER_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_complex.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_complex.hpp
new file mode 100644
index 0000000000..73da1f04e1
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_complex.hpp
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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_MP_IS_COMPLEX_HPP
+#define BOOST_MP_IS_COMPLEX_HPP
+
+#include <type_traits>
+#include <complex>
+
+namespace boost { namespace multiprecision { namespace detail {
+
+template <class T> struct is_complex : public std::integral_constant<bool, false> {};
+
+template <class T> struct is_complex<std::complex<T> > : public std::integral_constant<bool, true> {};
+
+}
+}
+} // namespace boost::multiprecision::detail
+
+#endif // BOOST_MP_IS_BACKEND_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_convertible_arithmetic.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_convertible_arithmetic.hpp
new file mode 100644
index 0000000000..cf17aa88f8
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_convertible_arithmetic.hpp
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2021 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_IS_CONVERTIBLE_ARITHMETIC_HPP
+#define BOOST_IS_CONVERTIBLE_ARITHMETIC_HPP
+
+#include <type_traits>
+#include <boost/multiprecision/detail/number_base.hpp>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+namespace boost { namespace multiprecision { namespace detail {
+
+template <class V, class Backend>
+struct is_convertible_arithmetic
+{
+ static constexpr bool value = boost::multiprecision::detail::is_arithmetic<V>::value;
+};
+//
+// For extension types, we don't *require* interoperability,
+// so only enable it if we can convert the type to the backend
+// losslessly, ie not via conversion to a narrower type.
+// Note that backends with templated constructors/=operators
+// will not be selected here, so these need to either specialize
+// this trait, or provide a proper non-template constructor/=operator
+// for the extension types it supports.
+//
+#ifdef BOOST_HAS_FLOAT128
+template <class Backend>
+struct is_convertible_arithmetic<float128_type, Backend>
+{
+ static constexpr bool value = std::is_assignable<Backend, convertible_to<float128_type>>::value;
+};
+#endif
+#ifdef BOOST_HAS_INT128
+template <class Backend>
+struct is_convertible_arithmetic<int128_type, Backend>
+{
+ static constexpr bool value = std::is_assignable<Backend, convertible_to<int128_type>>::value;
+};
+template <class Backend>
+struct is_convertible_arithmetic<uint128_type, Backend>
+{
+ static constexpr bool value = std::is_assignable<Backend, convertible_to<uint128_type>>::value;
+};
+#endif
+
+}}} // namespace boost::multiprecision::detail
+
+#endif // BOOST_IS_BYTE_CONTAINER_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_restricted_conversion.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_restricted_conversion.hpp
index ff8f7f63cb..a36dc4ebc9 100644
--- a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_restricted_conversion.hpp
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_restricted_conversion.hpp
@@ -4,45 +4,44 @@
// 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_MP_RESTRICTED_CONVERSION_HPP
-#define BOOST_MP_RESTRICTED_CONVERSION_HPP
+#ifndef BOOST_MP_IS_RESTRICTED_CONVERSION_HPP
+#define BOOST_MP_IS_RESTRICTED_CONVERSION_HPP
#include <boost/multiprecision/traits/explicit_conversion.hpp>
-#include <boost/mpl/if.hpp>
#include <boost/multiprecision/detail/number_base.hpp>
-namespace boost{ namespace multiprecision{ namespace detail{
-
+namespace boost { namespace multiprecision { namespace detail {
template <class From, class To>
struct is_lossy_conversion
{
- typedef typename mpl::if_c<
- ((number_category<From>::value == number_kind_floating_point) && (number_category<To>::value == number_kind_integer))
- /* || ((number_category<From>::value == number_kind_floating_point) && (number_category<To>::value == number_kind_rational))*/
- || ((number_category<From>::value == number_kind_rational) && (number_category<To>::value == number_kind_integer))
- || ((number_category<From>::value == number_kind_fixed_point) && (number_category<To>::value == number_kind_integer))
- || (number_category<From>::value == number_kind_unknown)
- || (number_category<To>::value == number_kind_unknown),
- mpl::true_,
- mpl::false_
- >::type type;
- static const bool value = type::value;
+ static constexpr bool category_conditional_is_true =
+ ( (static_cast<boost::multiprecision::number_category_type>(number_category<From>::value) == number_kind_floating_point)
+ && (static_cast<boost::multiprecision::number_category_type>(number_category<To >::value) == number_kind_integer))
+ || ( (static_cast<boost::multiprecision::number_category_type>(number_category<From>::value) == number_kind_rational)
+ && (static_cast<boost::multiprecision::number_category_type>(number_category<To >::value) == number_kind_integer))
+ || ( (static_cast<boost::multiprecision::number_category_type>(number_category<From>::value) == number_kind_fixed_point)
+ && (static_cast<boost::multiprecision::number_category_type>(number_category<To >::value) == number_kind_integer))
+ || (static_cast<boost::multiprecision::number_category_type>(number_category<From>::value) == number_kind_unknown)
+ || (static_cast<boost::multiprecision::number_category_type>(number_category<To >::value) == number_kind_unknown);
+
+ using type = typename std::conditional<category_conditional_is_true,
+ std::integral_constant<bool, true>,
+ std::integral_constant<bool, false>>::type;
+
+ static constexpr bool value = type::value;
};
-template<typename From, typename To>
+template <typename From, typename To>
struct is_restricted_conversion
{
- typedef typename mpl::if_c<
- ((is_explicitly_convertible<From, To>::value && !is_convertible<From, To>::value)
- || is_lossy_conversion<From, To>::value),
- mpl::true_,
- mpl::false_
- >::type type;
- static const bool value = type::value;
+ using type = typename std::conditional<
+ ((is_explicitly_convertible<From, To>::value && !std::is_convertible<From, To>::value) || is_lossy_conversion<From, To>::value),
+ std::integral_constant<bool, true>,
+ std::integral_constant<bool, false>>::type;
+ static constexpr const bool value = type::value;
};
-}}} // namespaces
-
-#endif // BOOST_MP_RESTRICTED_CONVERSION_HPP
+}}} // namespace boost::multiprecision::detail
+#endif // BOOST_MP_IS_RESTRICTED_CONVERSION_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_variable_precision.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_variable_precision.hpp
new file mode 100644
index 0000000000..f42fb2c645
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/is_variable_precision.hpp
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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_MP_IS_VARIABLE_PRECISION_HPP
+#define BOOST_MP_IS_VARIABLE_PRECISION_HPP
+
+#include <boost/multiprecision/detail/number_base.hpp>
+
+namespace boost { namespace multiprecision { namespace detail {
+
+template <class Backend>
+struct is_variable_precision : public std::integral_constant<bool, false>
+{};
+
+template <class Backend, expression_template_option ExpressionTemplates>
+struct is_variable_precision<number<Backend, ExpressionTemplates> > : public is_variable_precision<Backend>
+{};
+
+}
+}
+} // namespace boost::multiprecision::detail
+
+#endif // BOOST_MP_IS_BACKEND_HPP
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/max_digits10.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/max_digits10.hpp
new file mode 100644
index 0000000000..8e6d2371c8
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/max_digits10.hpp
@@ -0,0 +1,79 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2012 John Maddock. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_MP_MAX_DIGITS10_HPP
+#define BOOST_MP_MAX_DIGITS10_HPP
+
+namespace boost {
+namespace multiprecision {
+namespace detail {
+
+template <unsigned digits>
+struct calc_max_digits10
+{
+ static constexpr unsigned max_digits_10(unsigned d)
+ {
+ //
+ // We need ceil(log10(2) * d) + 1 decimal places to
+ // guarantee round tripping, see: https://www.exploringbinary.com/number-of-digits-required-for-round-trip-conversions/
+ // and references therein. Since log10(2) is irrational, then d*log10(2) will
+ // never be exactly an integer so we can replace by trunc(log10(2) * d) + 2
+ // and avoid the call to ceil:
+ //
+ return static_cast<unsigned>(0.301029995663981195213738894724493026768189881462108541310 * d) + 2;
+ }
+ static constexpr unsigned value = max_digits_10(digits);
+};
+
+template <std::size_t digits>
+struct calc_max_digits10_s
+{
+ static constexpr std::size_t max_digits_10(std::size_t d)
+ {
+ //
+ // We need ceil(log10(2) * d) + 1 decimal places to
+ // guarantee round tripping, see: https://www.exploringbinary.com/number-of-digits-required-for-round-trip-conversions/
+ // and references therein. Since log10(2) is irrational, then d*log10(2) will
+ // never be exactly an integer so we can replace by trunc(log10(2) * d) + 2
+ // and avoid the call to ceil:
+ //
+ return static_cast<std::size_t>(static_cast<std::size_t>(0.301029995663981195213738894724493026768189881462108541310 * static_cast<double>(d)) + 2u);
+ }
+ static constexpr std::size_t value = max_digits_10(digits);
+};
+
+template <unsigned digits>
+struct calc_digits10
+{
+ static constexpr unsigned digits_10(unsigned d)
+ {
+ //
+ // We need floor(log10(2) * (d-1)), see:
+ // https://www.exploringbinary.com/number-of-digits-required-for-round-trip-conversions/
+ // and references therein.
+ //
+ return static_cast<unsigned>(0.301029995663981195213738894724493026768189881462108541310 * static_cast<double>(d - 1u));
+ }
+ static constexpr unsigned value = digits_10(digits);
+};
+
+template <std::size_t digits>
+struct calc_digits10_s
+{
+ static constexpr std::size_t digits_10(std::size_t d)
+ {
+ //
+ // We need floor(log10(2) * (d-1)), see:
+ // https://www.exploringbinary.com/number-of-digits-required-for-round-trip-conversions/
+ // and references therein.
+ //
+ return static_cast<std::size_t>(0.301029995663981195213738894724493026768189881462108541310 * static_cast<double>(d - 1u));
+ }
+ static constexpr std::size_t value = digits_10(digits);
+};
+
+}}} // namespace boost::multiprecision::detail
+
+#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/std_integer_traits.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/std_integer_traits.hpp
new file mode 100644
index 0000000000..e8fafde181
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/std_integer_traits.hpp
@@ -0,0 +1,72 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2012 John Maddock. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_MP_STD_INTEGER_TRAITS_HPP
+#define BOOST_MP_STD_INTEGER_TRAITS_HPP
+
+#include <type_traits>
+#include <boost/multiprecision/detail/standalone_config.hpp>
+
+namespace boost {
+namespace multiprecision {
+namespace detail {
+
+template <class T>
+struct is_signed : public std::is_signed<T> {};
+template <class T>
+struct is_unsigned : public std::is_unsigned<T> {};
+template <class T>
+struct is_integral : public std::is_integral<T> {};
+template <class T>
+struct is_arithmetic : public std::is_arithmetic<T> {};
+template <class T>
+struct make_unsigned : public std::make_unsigned<T> {};
+template <class T>
+struct make_signed : public std::make_signed<T> {};
+
+#ifdef BOOST_HAS_INT128
+
+template <>
+struct is_signed<int128_type> : public std::integral_constant<bool, true> {};
+template <>
+struct is_signed<uint128_type> : public std::integral_constant<bool, false> {};
+template <>
+struct is_unsigned<int128_type> : public std::integral_constant<bool, false> {};
+template <>
+struct is_unsigned<uint128_type> : public std::integral_constant<bool, true> {};
+template <>
+struct is_integral<int128_type> : public std::integral_constant<bool, true> {};
+template <>
+struct is_integral<uint128_type> : public std::integral_constant<bool, true> {};
+template <>
+struct is_arithmetic<int128_type> : public std::integral_constant<bool, true> {};
+template <>
+struct is_arithmetic<uint128_type> : public std::integral_constant<bool, true> {};
+template <>
+struct make_unsigned<int128_type>
+{
+ using type = uint128_type;
+};
+template <>
+struct make_unsigned<uint128_type>
+{
+ using type = uint128_type;
+};
+template <>
+struct make_signed<int128_type>
+{
+ using type = int128_type;
+};
+template <>
+struct make_signed<uint128_type>
+{
+ using type = int128_type;
+};
+
+#endif
+
+}}} // namespace boost::multiprecision::detail
+
+#endif
diff --git a/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/transcendental_reduction_type.hpp b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/transcendental_reduction_type.hpp
new file mode 100644
index 0000000000..c433a6376a
--- /dev/null
+++ b/contrib/restricted/boost/multiprecision/include/boost/multiprecision/traits/transcendental_reduction_type.hpp
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2020 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_MP_TRANSCENDENTAL_REDUCTION_TYPE_HPP
+#define BOOST_MP_TRANSCENDENTAL_REDUCTION_TYPE_HPP
+
+namespace boost { namespace multiprecision { namespace detail {
+
+template <class T>
+struct transcendental_reduction_type
+{
+ using type = T;
+};
+
+}
+}
+} // namespace boost::multiprecision::detail
+
+#endif // BOOST_MP_TRANSCENDENTAL_REDUCTION_TYPE_HPP