update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -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

View File

@@ -0,0 +1,62 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright 2017 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_ATOMIC_HPP
#define BOOST_MP_DETAIL_ATOMIC_HPP
#include <boost/multiprecision/detail/standalone_config.hpp>
#ifdef BOOST_HAS_THREADS
# include <atomic>
# define BOOST_MATH_ATOMIC_NS std
namespace boost {
namespace multiprecision {
namespace detail {
#if ATOMIC_INT_LOCK_FREE == 2
using atomic_counter_type = std::atomic<int>;
using atomic_unsigned_type = std::atomic<unsigned>;
using atomic_integer_type = int;
using atomic_unsigned_integer_type = unsigned;
#elif ATOMIC_SHORT_LOCK_FREE == 2
using atomic_counter_type = std::atomic<short>;
using atomic_unsigned_type = std::atomic<unsigned short>;
using atomic_integer_type = short;
using atomic_unsigned_integer_type = unsigned short;
#elif ATOMIC_LONG_LOCK_FREE == 2
using atomic_unsigned_integer_type = std::atomic<long>;
using atomic_unsigned_type = std::atomic<unsigned long>;
using atomic_unsigned_integer_type = unsigned long;
using atomic_integer_type = long;
#elif ATOMIC_LLONG_LOCK_FREE == 2
using atomic_unsigned_integer_type = std::atomic<long long>;
using atomic_unsigned_type = std::atomic<unsigned long long>;
using atomic_integer_type = long long;
using atomic_unsigned_integer_type = unsigned long long;
#else
#define BOOST_MT_NO_ATOMIC_INT
#endif
}
}}
#else // BOOST_HAS_THREADS
#define BOOST_MT_NO_ATOMIC_INT
#endif // BOOST_HAS_THREADS
namespace boost { namespace multiprecision { namespace detail {
#ifdef BOOST_MT_NO_ATOMIC_INT
using precision_type = unsigned;
#else
using precision_type = atomic_unsigned_type;
#endif
} } }
#endif // BOOST_MP_DETAIL_ATOMIC_HPP

View File

@@ -1,39 +0,0 @@
// Copyright (c) 2011 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_MP_BIG_LANCZOS
#define BOOST_MP_BIG_LANCZOS
#include <boost/math/bindings/detail/big_lanczos.hpp>
namespace boost{ namespace math{
namespace lanczos{
template <class T, class Policy>
struct lanczos;
template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
struct lanczos<multiprecision::number<Backend, ExpressionTemplates>, Policy>
{
typedef typename boost::math::policies::precision<multiprecision::number<Backend, ExpressionTemplates>, Policy>::type precision_type;
typedef typename mpl::if_c<
precision_type::value && (precision_type::value <= 73),
lanczos13UDT,
typename mpl::if_c<
precision_type::value&& (precision_type::value <= 122),
lanczos22UDT,
undefined_lanczos
>::type
>::type type;
};
} // namespace lanczos
}} // namespaces
#endif

View File

@@ -1,27 +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/predef/other/endian.h>
#include <boost/cstdint.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;
@@ -30,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;
@@ -41,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);
@@ -60,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);
@@ -78,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;
#if BOOST_ENDIAN_LITTLE_BYTE
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;
#if BOOST_ENDIAN_LITTLE_BYTE
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

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +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_
// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_DIGITS_HPP
#define BOOST_MP_DIGITS_HPP
#ifndef BOOST_MP_DETAIL_DIGITS_HPP
#define BOOST_MP_DETAIL_DIGITS_HPP
namespace boost{ namespace multiprecision{ namespace detail{
namespace boost { namespace multiprecision { namespace detail {
inline unsigned long digits10_2_2(unsigned long d10)
inline constexpr unsigned long digits10_2_2(unsigned long d10)
{
return (d10 * 1000uL) / 301uL + ((d10 * 1000uL) % 301 ? 2u : 1u);
}
inline unsigned long digits2_2_10(unsigned long d2)
inline constexpr unsigned long digits2_2_10(unsigned long d2)
{
return (d2 * 301uL) / 1000uL;
}
}}} // namespaces
#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

View File

@@ -6,24 +6,39 @@
//
#ifndef BOOST_MP_DETAIL_DYNAMIC_ARRAY_HPP
#define BOOST_MP_DETAIL_DYNAMIC_ARRAY_HPP
#define BOOST_MP_DETAIL_DYNAMIC_ARRAY_HPP
#include <vector>
#include <boost/multiprecision/detail/rebind.hpp>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <vector>
namespace boost { namespace multiprecision { namespace backends { namespace detail
{
template <class value_type, const boost::uint32_t elem_number, class my_allocator>
struct dynamic_array : public std::vector<value_type, typename rebind<value_type, my_allocator>::type>
{
dynamic_array() :
std::vector<value_type, typename rebind<value_type, my_allocator>::type>(static_cast<typename std::vector<value_type, typename rebind<value_type, my_allocator>::type>::size_type>(elem_number), static_cast<value_type>(0))
{
}
#include <boost/multiprecision/detail/rebind.hpp>
value_type* data() { return &(*(this->begin())); }
const value_type* data() const { return &(*(this->begin())); }
};
} } } } // namespace boost::multiprecision::backends::detail
namespace boost { namespace multiprecision { namespace backends { namespace detail {
template <class ValueType, const std::uint32_t ElemNumber, class my_allocator>
struct dynamic_array : public std::vector<ValueType, typename rebind<ValueType, my_allocator>::type>
{
private:
using base_class_type = std::vector<ValueType, typename rebind<ValueType, my_allocator>::type>;
public:
dynamic_array()
: base_class_type(static_cast<typename base_class_type::size_type>(ElemNumber),
static_cast<typename base_class_type::value_type>(0u)) { }
dynamic_array(std::initializer_list<std::uint32_t> lst)
: base_class_type(static_cast<typename base_class_type::size_type>(ElemNumber),
static_cast<typename base_class_type::value_type>(0u))
{
std::copy(lst.begin(),
lst.begin() + (std::min)(std::size_t(lst.size()), std::size_t(ElemNumber)),
data());
}
typename base_class_type::value_type* data() { return &(*(this->begin())); }
const typename base_class_type::value_type* data() const { return &(*(this->begin())); }
};
}}}} // namespace boost::multiprecision::backends::detail
#endif // BOOST_MP_DETAIL_DYNAMIC_ARRAY_HPP

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,95 @@
// (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;
using std::nextafter;
#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); }
inline __float128 nextafter(__float128 a, __float128 b) throw() { return nextafterq(a, b); }
#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::multiprecision::float128_procs::nextafter; 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

View File

@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// 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
//
// Generic routines for converting floating point values to and from decimal strings.
// Note that these use "naive" algorithms which result in rounding error - so they
@@ -12,72 +12,75 @@
#ifndef BOOST_MP_FLOAT_STRING_CVT_HPP
#define BOOST_MP_FLOAT_STRING_CVT_HPP
#include <string>
#include <cctype>
#include <boost/multiprecision/detail/no_exceptions_support.hpp>
#include <boost/multiprecision/detail/assert.hpp>
namespace boost{ namespace multiprecision{ namespace detail{
namespace boost { namespace multiprecision { namespace detail {
template <class I>
inline void round_string_up_at(std::string& s, int pos, I& expon)
inline void round_string_up_at(std::string& s, std::ptrdiff_t pos, I& expon)
{
//
// Rounds up a string representation of a number at pos:
//
if(pos < 0)
if (pos < 0)
{
s.insert(static_cast<std::string::size_type>(0), 1, '1');
s.erase(s.size() - 1);
++expon;
}
else if(s[pos] == '9')
else if (s[static_cast<std::size_t>(pos)] == '9')
{
s[pos] = '0';
s[static_cast<std::size_t>(pos)] = '0';
round_string_up_at(s, pos - 1, expon);
}
else
{
if((pos == 0) && (s[pos] == '0') && (s.size() == 1))
if ((pos == 0) && (s[static_cast<std::size_t>(pos)] == '0') && (s.size() == 1))
++expon;
++s[pos];
++s[static_cast<std::size_t>(pos)];
}
}
template <class Backend>
std::string convert_to_string(Backend b, std::streamsize digits, std::ios_base::fmtflags f)
{
using default_ops::eval_log10;
using default_ops::eval_floor;
using default_ops::eval_pow;
using default_ops::eval_convert_to;
using default_ops::eval_multiply;
using default_ops::eval_divide;
using default_ops::eval_subtract;
using default_ops::eval_floor;
using default_ops::eval_fpclassify;
using default_ops::eval_log10;
using default_ops::eval_multiply;
using default_ops::eval_pow;
using default_ops::eval_subtract;
typedef typename mpl::front<typename Backend::unsigned_types>::type ui_type;
typedef typename Backend::exponent_type exponent_type;
using ui_type = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
using exponent_type = typename Backend::exponent_type ;
std::string result;
bool iszero = false;
bool isneg = false;
exponent_type expon = 0;
std::string result;
bool iszero = false;
bool isneg = false;
exponent_type expon = 0;
std::streamsize org_digits = digits;
BOOST_ASSERT(digits > 0);
BOOST_MP_ASSERT(digits > 0);
int fpt = eval_fpclassify(b);
if(fpt == (int)FP_ZERO)
if (fpt == static_cast<int>(FP_ZERO))
{
result = "0";
iszero = true;
}
else if(fpt == (int)FP_INFINITE)
else if (fpt == static_cast<int>(FP_INFINITE))
{
if(b.compare(ui_type(0)) < 0)
if (b.compare(ui_type(0)) < 0)
return "-inf";
else
return ((f & std::ios_base::showpos) == std::ios_base::showpos) ? "+inf" : "inf";
}
else if(fpt == (int)FP_NAN)
else if (fpt == static_cast<int>(FP_NAN))
{
return "nan";
}
@@ -87,7 +90,7 @@ std::string convert_to_string(Backend b, std::streamsize digits, std::ios_base::
// Start by figuring out the exponent:
//
isneg = b.compare(ui_type(0)) < 0;
if(isneg)
if (isneg)
b.negate();
Backend t;
Backend ten;
@@ -96,14 +99,14 @@ std::string convert_to_string(Backend b, std::streamsize digits, std::ios_base::
eval_log10(t, b);
eval_floor(t, t);
eval_convert_to(&expon, t);
if(-expon > std::numeric_limits<number<Backend> >::max_exponent10 - 3)
if (-expon > std::numeric_limits<number<Backend> >::max_exponent10 - 3)
{
int e = -expon / 2;
int e = -expon / 2;
Backend t2;
eval_pow(t2, ten, e);
eval_multiply(t, t2, b);
eval_multiply(t, t2);
if(expon & 1)
if (expon & 1)
eval_multiply(t, ten);
}
else
@@ -114,12 +117,12 @@ std::string convert_to_string(Backend b, std::streamsize digits, std::ios_base::
//
// Make sure we're between [1,10) and adjust if not:
//
if(t.compare(ui_type(1)) < 0)
if (t.compare(ui_type(1)) < 0)
{
eval_multiply(t, ui_type(10));
--expon;
}
else if(t.compare(ui_type(10)) >= 0)
else if (t.compare(ui_type(10)) >= 0)
{
eval_divide(t, ui_type(10));
++expon;
@@ -129,14 +132,14 @@ std::string convert_to_string(Backend b, std::streamsize digits, std::ios_base::
//
// Adjust the number of digits required based on formatting options:
//
if(((f & std::ios_base::fixed) == std::ios_base::fixed) && (expon != -1))
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)
if ((f & std::ios_base::scientific) == std::ios_base::scientific)
++digits;
//
// Extract the digits one at a time:
//
for(unsigned i = 0; i < digits; ++i)
for (unsigned i = 0; i < digits; ++i)
{
eval_floor(digit, t);
eval_convert_to(&cdigit, digit);
@@ -147,41 +150,49 @@ std::string convert_to_string(Backend b, std::streamsize digits, std::ios_base::
//
// Possibly round result:
//
if(digits >= 0)
if (digits >= 0)
{
eval_floor(digit, t);
eval_convert_to(&cdigit, digit);
eval_subtract(t, digit);
if((cdigit == 5) && (t.compare(ui_type(0)) == 0))
if ((cdigit == 5) && (t.compare(ui_type(0)) == 0))
{
// Bankers rounding:
if((*result.rbegin() - '0') & 1)
if ((*result.rbegin() - '0') & 1)
{
round_string_up_at(result, result.size() - 1, expon);
round_string_up_at(result, static_cast<std::ptrdiff_t>(result.size() - 1u), expon);
}
}
else if(cdigit >= 5)
else if (cdigit >= 5)
{
round_string_up_at(result, result.size() - 1, expon);
round_string_up_at(result, static_cast<std::ptrdiff_t>(result.size() - 1u), expon);
}
}
eval_floor(t, b);
if ((t.compare(b) == 0) && (static_cast<std::size_t>(expon + 1) < result.size()))
{
// Input is an integer, sometimes we get a result which is not an integer here as a result of printing too
// many digits, so lets round if required:
round_string_up_at(result, expon + 1, expon);
result.erase(static_cast<std::string::size_type>(expon + 1));
}
}
while((result.size() > digits) && result.size())
while ((static_cast<std::streamsize>(result.size()) > digits) && (result.size() != 0U))
{
// We may get here as a result of rounding...
if(result.size() > 1)
if (result.size() > 1)
result.erase(result.size() - 1);
else
{
if(expon > 0)
if (expon > 0)
--expon; // so we put less padding in the result.
else
++expon;
++digits;
}
}
BOOST_ASSERT(org_digits >= 0);
if(isneg)
BOOST_MP_ASSERT(org_digits >= 0);
if (isneg)
result.insert(static_cast<std::string::size_type>(0), 1, '-');
format_float_string(result, expon, org_digits, f, iszero);
@@ -191,98 +202,102 @@ std::string convert_to_string(Backend b, std::streamsize digits, std::ios_base::
template <class Backend>
void convert_from_string(Backend& b, const char* p)
{
using default_ops::eval_multiply;
using default_ops::eval_add;
using default_ops::eval_pow;
using default_ops::eval_divide;
using default_ops::eval_multiply;
using default_ops::eval_pow;
typedef typename mpl::front<typename Backend::unsigned_types>::type ui_type;
using ui_type = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
b = ui_type(0);
if(!p || (*p == 0))
if (!p || (*p == 0))
return;
bool is_neg = false;
bool is_neg_expon = false;
static const ui_type ten = ui_type(10);
typename Backend::exponent_type expon = 0;
int digits_seen = 0;
typedef std::numeric_limits<number<Backend, et_off> > limits;
static const int max_digits = limits::is_specialized ? limits::max_digits10 + 1 : INT_MAX;
bool is_neg = false;
bool is_neg_expon = false;
constexpr ui_type ten = ui_type(10);
typename Backend::exponent_type expon = 0;
int digits_seen = 0;
if(*p == '+') ++p;
else if(*p == '-')
using limits = std::numeric_limits<number<Backend, et_off>>;
constexpr int max_digits = limits::is_specialized ? limits::max_digits10 + 1 : INT_MAX;
if (*p == '+')
++p;
else if (*p == '-')
{
is_neg = true;
++p;
}
if((std::strcmp(p, "nan") == 0) || (std::strcmp(p, "NaN") == 0) || (std::strcmp(p, "NAN") == 0))
if ((std::strcmp(p, "nan") == 0) || (std::strcmp(p, "NaN") == 0) || (std::strcmp(p, "NAN") == 0))
{
eval_divide(b, ui_type(0));
if(is_neg)
if (is_neg)
b.negate();
return;
}
if((std::strcmp(p, "inf") == 0) || (std::strcmp(p, "Inf") == 0) || (std::strcmp(p, "INF") == 0))
if ((std::strcmp(p, "inf") == 0) || (std::strcmp(p, "Inf") == 0) || (std::strcmp(p, "INF") == 0))
{
b = ui_type(1);
eval_divide(b, ui_type(0));
if(is_neg)
if (is_neg)
b.negate();
return;
}
//
// Grab all the leading digits before the decimal point:
//
while(std::isdigit(*p))
while (std::isdigit(*p))
{
eval_multiply(b, ten);
eval_add(b, ui_type(*p - '0'));
++p;
++digits_seen;
}
if(*p == '.')
if (*p == '.')
{
//
// Grab everything after the point, stop when we've seen
// enough digits, even if there are actually more available:
//
++p;
while(std::isdigit(*p))
while (std::isdigit(*p))
{
eval_multiply(b, ten);
eval_add(b, ui_type(*p - '0'));
++p;
--expon;
if(++digits_seen > max_digits)
if (++digits_seen > max_digits)
break;
}
while(std::isdigit(*p))
while (std::isdigit(*p))
++p;
}
//
// Parse the exponent:
//
if((*p == 'e') || (*p == 'E'))
if ((*p == 'e') || (*p == 'E'))
{
++p;
if(*p == '+') ++p;
else if(*p == '-')
if (*p == '+')
++p;
else if (*p == '-')
{
is_neg_expon = true;
++p;
}
typename Backend::exponent_type e2 = 0;
while(std::isdigit(*p))
while (std::isdigit(*p))
{
e2 *= 10;
e2 += (*p - '0');
++p;
}
if(is_neg_expon)
if (is_neg_expon)
e2 = -e2;
expon += e2;
}
if(expon)
if (expon)
{
// Scale by 10^expon, note that 10^expon can be
// outside the range of our number type, even though the
@@ -290,7 +305,7 @@ void convert_from_string(Backend& b, const char* p)
// the calculation in two:
Backend t;
t = ten;
if(expon > limits::min_exponent10 + 2)
if (expon > limits::min_exponent10 + 2)
{
eval_pow(t, t, expon);
eval_multiply(b, t);
@@ -304,15 +319,15 @@ void convert_from_string(Backend& b, const char* p)
eval_multiply(b, t);
}
}
if(is_neg)
if (is_neg)
b.negate();
if(*p)
if (*p)
{
// Unexpected input in string:
BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected characters in string being interpreted as a float128."));
BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unexpected characters in string being interpreted as a float128."));
}
}
}}} // namespaces
}}} // namespace boost::multiprecision::detail
#endif

View File

@@ -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

View File

@@ -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,60 +201,29 @@ 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_ldexp(result, result, static_cast<int>(k - 1u));
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 T result;
static BOOST_MP_THREAD_LOCAL long digits = 0;
#ifndef BOOST_MP_USING_THREAD_LOCAL
static BOOST_MP_THREAD_LOCAL bool b = false;
constant_initializer<T, &get_constant_ln2<T> >::do_nothing();
if(!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
b = true;
#else
if ((digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
#endif
boost::multiprecision::detail::maybe_promote_precision(&result);
calc_log2(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value());
digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
@@ -264,19 +234,11 @@ const T& get_constant_ln2()
template <class T>
const T& get_constant_e()
{
static BOOST_MP_THREAD_LOCAL T result;
static BOOST_MP_THREAD_LOCAL T result;
static BOOST_MP_THREAD_LOCAL long digits = 0;
#ifndef BOOST_MP_USING_THREAD_LOCAL
static BOOST_MP_THREAD_LOCAL bool b = false;
constant_initializer<T, &get_constant_e<T> >::do_nothing();
if (!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
b = true;
#else
if ((digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
#endif
boost::multiprecision::detail::maybe_promote_precision(&result);
calc_e(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value());
digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
@@ -287,47 +249,40 @@ const T& get_constant_e()
template <class T>
const T& get_constant_pi()
{
static BOOST_MP_THREAD_LOCAL T result;
static BOOST_MP_THREAD_LOCAL T result;
static BOOST_MP_THREAD_LOCAL long digits = 0;
#ifndef BOOST_MP_USING_THREAD_LOCAL
static BOOST_MP_THREAD_LOCAL bool b = false;
constant_initializer<T, &get_constant_pi<T> >::do_nothing();
if (!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
b = true;
#else
if ((digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
#endif
boost::multiprecision::detail::maybe_promote_precision(&result);
calc_pi(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value());
digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
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 BOOST_MP_THREAD_LOCAL T result;
static BOOST_MP_THREAD_LOCAL T result;
static BOOST_MP_THREAD_LOCAL long digits = 0;
#ifndef BOOST_MP_USING_THREAD_LOCAL
static BOOST_MP_THREAD_LOCAL bool b = false;
constant_initializer<T, &get_constant_one_over_epsilon<T> >::do_nothing();
if (!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
b = true;
#else
if ((digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
#endif
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();
}
return result;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
///////////////////////////////////////////////////////////////////////////////
// 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)
{
T t = boost::multiprecision::detail::impl::trunc(arg);
if (t > LLONG_MAX)
{
BOOST_MP_THROW_EXCEPTION(std::domain_error("arg cannot be converted into a long long"));
}
return static_cast<long long>(t);
}
template <typename T>
inline int itrunc BOOST_PREVENT_MACRO_SUBSTITUTION (const T arg)
{
T t = boost::multiprecision::detail::impl::trunc(arg);
if (t > static_cast<T>(INT_MAX))
{
BOOST_MP_THROW_EXCEPTION(std::domain_error("arg cannot be converted into an int"));
}
return static_cast<int>(t);
}
#endif
}}} // Namespaces
#endif // BOOST_MP_DETAIL_FUNCTIONS_TRUNC_HPP

View File

@@ -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;
}
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);
if(c == (int)FP_ZERO)
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;
//
// 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;
}
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);
constexpr int shift = std::numeric_limits<std::intmax_t>::digits - 1;
static const int shift = std::numeric_limits<boost::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);
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));
}
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;
}
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,40 +484,43 @@ 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);
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)
{
val.backend().negate();
neg = true;
}
while(e > 0)
while (e > 0)
{
exponent_type s = (std::min)(e, shift);
val = ldexp(val, s);
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;
@@ -503,21 +531,23 @@ void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<2>
}
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;
@@ -528,71 +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 mpl::true_&, const 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_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
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 mpl::false_&, const mpl::true_&)
void generic_interconvert_complex_to_scalar(To& to, const From& from, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
{
typedef typename component_type<number<From> >::type component_number;
typedef typename component_number::backend_type component_backend;
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, mpl::true_(), mpl::true_());
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 mpl::false_&, const mpl::false_&)
void generic_interconvert_complex_to_scalar(To& to, const From& from, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&)
{
typedef typename component_type<number<From> >::type component_number;
typedef typename component_number::backend_type component_backend;
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, mpl::true_(), mpl::true_());
generic_interconvert(to, r, mpl::int_<number_category<To>::value>(), mpl::int_<number_category<To>::value>());
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>());
}
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_complex>& /*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_complex>& /*from_type*/)
{
typedef typename component_type<number<From> >::type component_number;
typedef typename component_number::backend_type component_backend;
using component_number = typename component_type<number<From> >::type;
using component_backend = typename component_number::backend_type ;
generic_interconvert_complex_to_scalar(to, from, mpl::bool_<boost::is_same<component_backend, To>::value>(), mpl::bool_<boost::is_constructible<To, const component_backend&>::value>());
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 mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_complex>& /*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_complex>& /*from_type*/)
{
typedef typename component_type<number<From> >::type component_number;
typedef typename component_number::backend_type component_backend;
using component_number = typename component_type<number<From> >::type;
using component_backend = typename component_number::backend_type ;
generic_interconvert_complex_to_scalar(to, from, mpl::bool_<boost::is_same<component_backend, To>::value>(), mpl::bool_<boost::is_constructible<To, const component_backend&>::value>());
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!!");
}
}
}
} // namespaces
} // namespace boost::multiprecision::detail
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#endif // BOOST_MP_GENERIC_INTERCONVERT_HPP
#endif // BOOST_MP_GENERIC_INTERCONVERT_HPP

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////
// 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
//
// We used to use lexical_cast internally for quick conversions from integers
// to strings, but that breaks if the global locale is something other than "C".
// See https://github.com/boostorg/multiprecision/issues/167.
//
#ifndef BOOST_MP_DETAIL_ITOS_HPP
#define BOOST_MP_DETAIL_ITOS_HPP
namespace boost { namespace multiprecision { namespace detail {
template <class Integer>
std::string itos(Integer val)
{
if (!val) return "0";
std::string result;
bool isneg = false;
if (val < 0)
{
val = -val;
isneg = true;
}
while (val)
{
result.insert(result.begin(), char('0' + (val % 10)));
val /= 10;
}
if (isneg)
result.insert(result.begin(), '-');
return result;
}
}}} // namespace boost::multiprecision::detail
#endif

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,188 +3,311 @@
// 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_PRECISION_HPP
#define BOOST_MP_PRECISION_HPP
#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{
namespace boost { namespace multiprecision { namespace detail {
template <class B, boost::multiprecision::expression_template_option ET>
inline BOOST_CONSTEXPR unsigned current_precision_of_last_chance_imp(const boost::multiprecision::number<B, ET>&, const mpl::false_&)
{
return std::numeric_limits<boost::multiprecision::number<B, ET> >::digits10;
}
template <class B, boost::multiprecision::expression_template_option ET>
inline unsigned current_precision_of_last_chance_imp(const boost::multiprecision::number<B, ET>& val, const mpl::true_&)
{
//
// 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 val.is_zero() ? 1 : digits2_2_10(msb(abs(val)) - lsb(abs(val)) + 1);
}
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 B, boost::multiprecision::expression_template_option ET>
inline unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>& n, const mpl::true_&)
{
return n.precision();
}
template <class B, boost::multiprecision::expression_template_option ET>
inline BOOST_CONSTEXPR unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>& val, const mpl::false_&)
{
return current_precision_of_last_chance_imp(val,
mpl::bool_<
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>());
}
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;
template <class Terminal>
inline BOOST_CONSTEXPR unsigned current_precision_of(const Terminal&)
{
return std::numeric_limits<Terminal>::digits10;
}
return (R::thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision) ? std::numeric_limits<first_float>::digits10 : 0;
}
template <class Terminal, std::size_t N>
inline BOOST_CONSTEXPR unsigned current_precision_of(const Terminal(&)[N])
{ // For string literals:
return 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 B, boost::multiprecision::expression_template_option ET>
inline BOOST_CONSTEXPR unsigned current_precision_of(const boost::multiprecision::number<B, ET>& n)
{
return current_precision_of_imp(n, boost::multiprecision::detail::is_variable_precision<boost::multiprecision::number<B, ET> >());
}
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 tag, class Arg1>
inline BOOST_CONSTEXPR unsigned current_precision_of(const expression<tag, Arg1, void, void, void>& expr)
{
return current_precision_of(expr.left_ref());
}
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 Arg1>
inline BOOST_CONSTEXPR unsigned current_precision_of(const expression<terminal, Arg1, void, void, void>& expr)
{
return current_precision_of(expr.value());
}
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 tag, class Arg1, class Arg2>
inline BOOST_CONSTEXPR unsigned current_precision_of(const expression<tag, Arg1, Arg2, void, void>& expr)
{
return (std::max)(current_precision_of(expr.left_ref()), current_precision_of(expr.right_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 tag, class Arg1, class Arg2, class Arg3>
inline BOOST_CONSTEXPR unsigned current_precision_of(const expression<tag, Arg1, Arg2, Arg3, void>& expr)
{
return (std::max)((std::max)(current_precision_of(expr.left_ref()), current_precision_of(expr.right_ref())), current_precision_of(expr.middle_ref()));
}
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)
#pragma warning(disable : 4130)
#endif
template <class R, bool = boost::multiprecision::detail::is_variable_precision<R>::value>
struct scoped_default_precision
{
template <class T>
BOOST_CONSTEXPR scoped_default_precision(const T&) {}
template <class T, class U>
BOOST_CONSTEXPR scoped_default_precision(const T&, const U&) {}
template <class T, class U, class V>
BOOST_CONSTEXPR scoped_default_precision(const T&, const U&, const V&) {}
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_ASSERT("This function should never be called!!" == 0);
return 0;
}
};
//
// 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_CXX14_CONSTEXPR scoped_default_precision(const T& a)
{
init(current_precision_of(a));
}
template <class T, class U>
BOOST_CXX14_CONSTEXPR scoped_default_precision(const T& a, const U& b)
{
init((std::max)(current_precision_of(a), current_precision_of(b)));
}
template <class T, class U, class V>
BOOST_CXX14_CONSTEXPR scoped_default_precision(const T& a, const U& b, const V& c)
{
init((std::max)((std::max)(current_precision_of(a), current_precision_of(b)), current_precision_of(c)));
}
~scoped_default_precision()
{
R::default_precision(m_old_prec);
}
BOOST_CXX14_CONSTEXPR unsigned precision()const
{
return m_new_prec;
}
private:
BOOST_CXX14_CONSTEXPR void init(unsigned p)
{
m_old_prec = R::default_precision();
if (p)
{
R::default_precision(p);
m_new_prec = p;
}
else
m_new_prec = m_old_prec;
}
unsigned m_old_prec, m_new_prec;
};
template <class R>
struct scoped_default_precision<R, true>
{
template <class T>
inline void maybe_promote_precision(T*, const mpl::false_&){}
template <class T>
inline void maybe_promote_precision(T* obj, const mpl::true_&)
BOOST_MP_CXX14_CONSTEXPR scoped_default_precision(const T& a)
{
if (obj->precision() != T::default_precision())
{
obj->precision(T::default_precision());
}
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;
}
template <class T>
inline void maybe_promote_precision(T* obj)
static constexpr bool has_uniform_precision()
{
maybe_promote_precision(obj, boost::multiprecision::detail::is_variable_precision<T>());
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)
#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)
#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_IS_BACKEND_HPP
#endif // BOOST_MP_DETAIL_PRECISION_HPP

View File

@@ -6,19 +6,14 @@
//
#ifndef BOOST_MP_DETAIL_REBIND_HPP
#define 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
{
#ifndef BOOST_NO_CXX11_ALLOCATOR
typedef typename std::allocator_traits<my_allocator>::template rebind_alloc<value_type> type;
#else
typedef typename my_allocator::template rebind<value_type>::other type;
#endif
};
} } } } // namespace boost::multiprecision::backends::detail
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

View File

@@ -0,0 +1,148 @@
///////////////////////////////////////////////////////////////
// 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
#ifdef __has_include
# if __has_include(<boost/config.hpp>)
# include <boost/config.hpp>
# include <boost/config/workaround.hpp>
# else
# error "Boost.Config is considered a requirement to use Boost.Multiprecision in standalone mode. A package is provided at https://github.com/boostorg/multiprecision/releases"
# endif
#else
// Provides the less helpful fatal error: 'boost/config.hpp' file not found if not available
# include <boost/config.hpp>
# include <boost/config/workaround.hpp>
#endif
// 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
#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
#endif // BOOST_MP_STANDALONE_CONFIG_HPP

View File

@@ -0,0 +1,42 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright 2021 John Maddock.
// Copyright Christopher Kormanyos 2021. 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_STATIC_ARRAY_HPP
#define BOOST_MP_DETAIL_STATIC_ARRAY_HPP
#include <array>
#include <cstddef>
#include <cstdint>
#include <initializer_list>
namespace boost { namespace multiprecision { namespace backends { namespace detail {
template <class ValueType, const std::uint32_t ElemNumber>
struct static_array : public std::array<ValueType, std::size_t(ElemNumber)>
{
private:
using base_class_type = std::array<ValueType, std::size_t(ElemNumber)>;
public:
static_array() noexcept
{
base_class_type::fill(typename base_class_type::value_type(0u));
}
static_array(std::initializer_list<std::uint32_t> lst) noexcept
{
std::copy(lst.begin(),
lst.begin() + (std::min)(std::size_t(lst.size()), std::size_t(ElemNumber)),
base_class_type::begin());
std::fill(base_class_type::begin() + (std::min)(std::size_t(lst.size()), std::size_t(ElemNumber)),
base_class_type::end(),
typename base_class_type::value_type(0u));
}
};
}}}} // namespace boost::multiprecision::backends::detail
#endif // BOOST_MP_DETAIL_STATIC_ARRAY_HPP

View File

@@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright 2023 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_STRING_HELPERS_HPP
#define BOOST_MP_DETAIL_STRING_HELPERS_HPP
#include <algorithm>
#include <cstring>
namespace boost { namespace multiprecision { namespace detail {
struct is_in_string
{
const char* begin;
const char* end;
is_in_string(const char* p) : begin(p), end(p + std::strlen(p)) {}
bool operator()(char s) { return std::find(begin, end, s) != end; }
};
struct is_not_in_string
{
const char* begin;
const char* end;
is_not_in_string(const char* p) : begin(p), end(p + std::strlen(p)) {}
bool operator()(char s) { return std::find(begin, end, s) == end; }
};
template <class Iterator>
std::size_t find_first_of(Iterator begin, Iterator end, const char* what)
{
return std::find_if(begin, end, is_in_string(what)) - begin;
}
template <class Iterator>
std::size_t find_first_not_of(Iterator begin, Iterator end, const char* what)
{
return std::find_if(begin, end, is_not_in_string(what)) - begin;
}
}}} // namespace boost::multiprecision::detail
#endif // BOOST_MP_DETAIL_STRING_HELPERS_HPP

View File

@@ -0,0 +1,80 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright 2021 John Maddock.
// Copyright Christopher Kormanyos 2021. 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_TABLES_HPP
#define BOOST_MP_DETAIL_TABLES_HPP
#include <algorithm>
#include <array>
#include <cstdint>
namespace boost { namespace multiprecision { namespace backends { namespace detail {
struct a029750
{
static constexpr std::uint32_t a029750_as_constexpr(const std::uint32_t value)
{
// Sloane's A029750 List of numbers of the form 2^k times 1, 3, 5 or 7.
// CoefficientList[Series[-(x + 1)^2 (x^2 + 1)^2/(2 x^4 - 1), {x, 0, 78}], x]
return ((value <= UINT32_C( 32)) ? UINT32_C( 32) : ((value <= UINT32_C( 40)) ? UINT32_C( 40) : ((value <= UINT32_C( 48)) ? UINT32_C( 48) : ((value <= UINT32_C( 56)) ? UINT32_C( 56) :
((value <= UINT32_C( 64)) ? UINT32_C( 64) : ((value <= UINT32_C( 80)) ? UINT32_C( 80) : ((value <= UINT32_C( 96)) ? UINT32_C( 96) : ((value <= UINT32_C( 112)) ? UINT32_C( 112) :
((value <= UINT32_C( 128)) ? UINT32_C( 128) : ((value <= UINT32_C( 160)) ? UINT32_C( 160) : ((value <= UINT32_C( 192)) ? UINT32_C( 192) : ((value <= UINT32_C( 224)) ? UINT32_C( 224) :
((value <= UINT32_C( 256)) ? UINT32_C( 256) : ((value <= UINT32_C( 320)) ? UINT32_C( 320) : ((value <= UINT32_C( 384)) ? UINT32_C( 384) : ((value <= UINT32_C( 448)) ? UINT32_C( 448) :
((value <= UINT32_C( 512)) ? UINT32_C( 512) : ((value <= UINT32_C( 640)) ? UINT32_C( 640) : ((value <= UINT32_C( 768)) ? UINT32_C( 768) : ((value <= UINT32_C( 896)) ? UINT32_C( 896) :
((value <= UINT32_C( 1024)) ? UINT32_C( 1024) : ((value <= UINT32_C( 1280)) ? UINT32_C( 1280) : ((value <= UINT32_C( 1536)) ? UINT32_C( 1536) : ((value <= UINT32_C( 1792)) ? UINT32_C( 1792) :
((value <= UINT32_C( 2048)) ? UINT32_C( 2048) : ((value <= UINT32_C( 2560)) ? UINT32_C( 2560) : ((value <= UINT32_C( 3072)) ? UINT32_C( 3072) : ((value <= UINT32_C( 3584)) ? UINT32_C( 3584) :
((value <= UINT32_C( 4096)) ? UINT32_C( 4096) : ((value <= UINT32_C( 5120)) ? UINT32_C( 5120) : ((value <= UINT32_C( 6144)) ? UINT32_C( 6144) : ((value <= UINT32_C( 7168)) ? UINT32_C( 7168) :
((value <= UINT32_C( 8192)) ? UINT32_C( 8192) : ((value <= UINT32_C( 10240)) ? UINT32_C( 10240) : ((value <= UINT32_C( 12288)) ? UINT32_C( 12288) : ((value <= UINT32_C( 14336)) ? UINT32_C( 14336) :
((value <= UINT32_C( 16384)) ? UINT32_C( 16384) : ((value <= UINT32_C( 20480)) ? UINT32_C( 20480) : ((value <= UINT32_C( 24576)) ? UINT32_C( 24576) : ((value <= UINT32_C( 28672)) ? UINT32_C( 28672) :
((value <= UINT32_C( 32768)) ? UINT32_C( 32768) : ((value <= UINT32_C( 40960)) ? UINT32_C( 40960) : ((value <= UINT32_C( 49152)) ? UINT32_C( 49152) : ((value <= UINT32_C( 57344)) ? UINT32_C( 57344) :
((value <= UINT32_C( 65536)) ? UINT32_C( 65536) : ((value <= UINT32_C( 81920)) ? UINT32_C( 81920) : ((value <= UINT32_C( 98304)) ? UINT32_C( 98304) : ((value <= UINT32_C( 114688)) ? UINT32_C( 114688) :
((value <= UINT32_C( 131072)) ? UINT32_C( 131072) : ((value <= UINT32_C( 163840)) ? UINT32_C( 163840) : ((value <= UINT32_C( 196608)) ? UINT32_C( 196608) : ((value <= UINT32_C( 229376)) ? UINT32_C( 229376) :
((value <= UINT32_C( 262144)) ? UINT32_C( 262144) : ((value <= UINT32_C( 327680)) ? UINT32_C( 327680) : ((value <= UINT32_C( 393216)) ? UINT32_C( 393216) : ((value <= UINT32_C( 458752)) ? UINT32_C( 458752) :
((value <= UINT32_C( 524288)) ? UINT32_C( 524288) : ((value <= UINT32_C( 655360)) ? UINT32_C( 655360) : ((value <= UINT32_C( 786432)) ? UINT32_C( 786432) : ((value <= UINT32_C( 917504)) ? UINT32_C( 917504) :
((value <= UINT32_C(1048576)) ? UINT32_C(1048576) : ((value <= UINT32_C(1310720)) ? UINT32_C(1310720) : ((value <= UINT32_C(1572864)) ? UINT32_C(1572864) : ((value <= UINT32_C(1835008)) ? UINT32_C(1835008) : UINT32_C(0x7FFFFFFF)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
}
static std::uint32_t a029750_as_runtime_value(const std::uint32_t value)
{
// Sloane's A029750 List of numbers of the form 2^k times 1, 3, 5 or 7.
// CoefficientList[Series[-(x + 1)^2 (x^2 + 1)^2/(2 x^4 - 1), {x, 0, 78}], x]
constexpr std::array<std::uint32_t, 65U> a029750_data =
{{
UINT32_C( 32), UINT32_C( 40), UINT32_C( 48), UINT32_C( 56),
UINT32_C( 64), UINT32_C( 80), UINT32_C( 96), UINT32_C( 112),
UINT32_C( 128), UINT32_C( 160), UINT32_C( 192), UINT32_C( 224),
UINT32_C( 256), UINT32_C( 320), UINT32_C( 384), UINT32_C( 448),
UINT32_C( 512), UINT32_C( 640), UINT32_C( 768), UINT32_C( 896),
UINT32_C( 1024), UINT32_C( 1280), UINT32_C( 1536), UINT32_C( 1792),
UINT32_C( 2048), UINT32_C( 2560), UINT32_C( 3072), UINT32_C( 3584),
UINT32_C( 4096), UINT32_C( 5120), UINT32_C( 6144), UINT32_C( 7168),
UINT32_C( 8192), UINT32_C( 10240), UINT32_C( 12288), UINT32_C( 14336),
UINT32_C( 16384), UINT32_C( 20480), UINT32_C( 24576), UINT32_C( 28672),
UINT32_C( 32768), UINT32_C( 40960), UINT32_C( 49152), UINT32_C( 57344),
UINT32_C( 65536), UINT32_C( 81920), UINT32_C( 98304), UINT32_C( 114688),
UINT32_C( 131072), UINT32_C( 163840), UINT32_C( 196608), UINT32_C( 229376),
UINT32_C( 262144), UINT32_C( 327680), UINT32_C( 393216), UINT32_C( 458752),
UINT32_C( 524288), UINT32_C( 655360), UINT32_C( 786432), UINT32_C( 917504),
UINT32_C( 1048576), UINT32_C(1310720), UINT32_C(1572864), UINT32_C(1835008),
UINT32_C(0x7FFFFFFF)
}};
const std::array<std::uint32_t, 65U>::const_iterator it =
std::lower_bound(a029750_data.cbegin(), a029750_data.cend(), value);
return ((it != a029750_data.cend()) ? *it : UINT32_C(0xFFFFFFFF));
}
};
constexpr std::uint32_t pow10_maker(std::uint32_t n)
{
// Make the constant power of 10^n.
return ((n == UINT32_C(0)) ? UINT32_C(1) : pow10_maker(n - UINT32_C(1)) * UINT32_C(10));
}
}}}} // namespace boost::multiprecision::backends::detail
#endif // BOOST_MP_DETAIL_TABLES_HPP

View File

@@ -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

View File

@@ -0,0 +1,212 @@
///////////////////////////////////////////////////////////////
// Copyright Jens Maurer 2000-2021
// Copyright Steven Watanabe 2011-2021
// Copyright John Maddock 2015-2021
// Copyright Matt Borland 2021
// 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
//
// This is a C++11 compliant port of Boost.Random's implementation
// of uniform_int_distribution. See their comments for detailed
// descriptions
#ifndef BOOST_MP_UNIFORM_INT_DISTRIBUTION_HPP
#define BOOST_MP_UNIFORM_INT_DISTRIBUTION_HPP
#include <limits>
#include <type_traits>
#include <boost/multiprecision/detail/standalone_config.hpp>
#include <boost/multiprecision/detail/assert.hpp>
#include <boost/multiprecision/traits/std_integer_traits.hpp>
namespace boost { namespace multiprecision {
namespace detail {
template <typename T, bool intrinsic>
struct make_unsigned_impl
{
using type = typename boost::multiprecision::detail::make_unsigned<T>::type;
};
template <typename T>
struct make_unsigned_impl<T, false>
{
using type = T;
};
template <typename T>
struct make_unsigned_mp
{
using type = typename make_unsigned_impl<T, boost::multiprecision::detail::is_integral<T>::value>::type;
};
template <typename Engine, typename T>
T generate_uniform_int (Engine& eng, T min_value, T max_value)
{
using range_type = typename boost::multiprecision::detail::make_unsigned_mp<T>::type;
using base_result = typename Engine::result_type;
using base_unsigned = typename boost::multiprecision::detail::make_unsigned_mp<base_result>::type;
const range_type range = max_value - min_value;
const base_result bmin = (eng.min)();
const base_unsigned brange = (eng.max)() - (eng.min)();
if(range == 0)
{
return min_value;
}
else if (brange < range)
{
for(;;)
{
range_type limit;
if(range == (std::numeric_limits<range_type>::max)())
{
limit = range / (range_type(brange) + 1);
if(range % (range_type(brange) + 1) == range_type(brange))
{
++limit;
}
}
else
{
limit = (range + 1) / (range_type(brange) + 1);
}
range_type result = 0;
range_type mult = 1;
while (mult <= limit)
{
result += static_cast<range_type>(static_cast<range_type>(eng() - bmin) * mult);
if(mult * range_type(brange) == range - mult + 1)
{
return(result);
}
mult *= range_type(brange)+range_type(1);
}
range_type result_increment = generate_uniform_int(eng, range_type(0), range_type(range/mult));
if(std::numeric_limits<range_type>::is_bounded && ((std::numeric_limits<range_type>::max)() / mult < result_increment))
{
continue;
}
result_increment *= mult;
result += result_increment;
if(result < result_increment)
{
continue;
}
if(result > range)
{
continue;
}
return result + min_value;
}
}
else
{
using mixed_range_type =
typename std::conditional<std::numeric_limits<range_type>::is_specialized && std::numeric_limits<base_unsigned>::is_specialized &&
(std::numeric_limits<range_type>::digits >= std::numeric_limits<base_unsigned>::digits),
range_type, base_unsigned>::type;
mixed_range_type bucket_size;
if(brange == (std::numeric_limits<base_unsigned>::max)())
{
bucket_size = static_cast<mixed_range_type>(brange) / (static_cast<mixed_range_type>(range)+1);
if(static_cast<mixed_range_type>(brange) % (static_cast<mixed_range_type>(range)+1) == static_cast<mixed_range_type>(range))
{
++bucket_size;
}
}
else
{
bucket_size = static_cast<mixed_range_type>(brange + 1) / (static_cast<mixed_range_type>(range)+1);
}
for(;;)
{
mixed_range_type result = eng() - bmin;
result /= bucket_size;
if(result <= static_cast<mixed_range_type>(range))
{
return result + min_value;
}
}
}
}
} // Namespace detail
template <typename Integer = int>
class uniform_int_distribution
{
private:
Integer min_;
Integer max_;
public:
class param_type
{
private:
Integer min_;
Integer max_;
public:
explicit param_type(Integer min_val, Integer max_val) : min_ {min_val}, max_ {max_val}
{
BOOST_MP_ASSERT(min_ <= max_);
}
Integer a() const { return min_; }
Integer b() const { return max_; }
};
explicit uniform_int_distribution(Integer min_arg, Integer max_arg) : min_ {min_arg}, max_ {max_arg}
{
BOOST_MP_ASSERT(min_ <= max_);
}
explicit uniform_int_distribution(const param_type& param_arg) : min_ {param_arg.a()}, max_ {param_arg.b()} {}
Integer min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return min_; }
Integer max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return max_; }
Integer a() const { return min_; }
Integer b() const { return max_; }
param_type param() const { return param_type(min_, max_); }
void param(const param_type& param_arg)
{
min_ = param_arg.a();
max_ = param_arg.b();
}
template <typename Engine>
Integer operator() (Engine& eng) const
{
return detail::generate_uniform_int(eng, min_, max_);
}
template <typename Engine>
Integer operator() (Engine& eng, const param_type& param_arg) const
{
return detail::generate_uniform_int(eng, param_arg.a(), param_arg.b());
}
};
}} // Namespaces
#endif // BOOST_MP_UNIFORM_INT_DISTRIBUTION_HPP

View File

@@ -6,105 +6,369 @@
//
#ifndef BOOST_MP_UTYPE_HELPER_HPP
#define BOOST_MP_UTYPE_HELPER_HPP
#define BOOST_MP_UTYPE_HELPER_HPP
#include <limits>
#include <boost/cstdint.hpp>
#include <limits>
#include <cstdint>
namespace boost { namespace multiprecision {
namespace detail
{
template<const unsigned> struct utype_helper { typedef boost::uint64_t exact; };
template<> struct utype_helper<0U> { typedef boost::uint8_t exact; };
template<> struct utype_helper<1U> { typedef boost::uint8_t exact; };
template<> struct utype_helper<2U> { typedef boost::uint8_t exact; };
template<> struct utype_helper<3U> { typedef boost::uint8_t exact; };
template<> struct utype_helper<4U> { typedef boost::uint8_t exact; };
template<> struct utype_helper<5U> { typedef boost::uint8_t exact; };
template<> struct utype_helper<6U> { typedef boost::uint8_t exact; };
template<> struct utype_helper<7U> { typedef boost::uint8_t exact; };
template<> struct utype_helper<8U> { typedef boost::uint8_t exact; };
namespace boost {
namespace multiprecision {
namespace detail {
template <const unsigned>
struct utype_helper
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<0U>
{
using exact = boost::uint8_t;
};
template <>
struct utype_helper<1U>
{
using exact = boost::uint8_t;
};
template <>
struct utype_helper<2U>
{
using exact = boost::uint8_t;
};
template <>
struct utype_helper<3U>
{
using exact = boost::uint8_t;
};
template <>
struct utype_helper<4U>
{
using exact = boost::uint8_t;
};
template <>
struct utype_helper<5U>
{
using exact = boost::uint8_t;
};
template <>
struct utype_helper<6U>
{
using exact = boost::uint8_t;
};
template <>
struct utype_helper<7U>
{
using exact = boost::uint8_t;
};
template <>
struct utype_helper<8U>
{
using exact = boost::uint8_t;
};
template<> struct utype_helper<9U> { typedef boost::uint16_t exact; };
template<> struct utype_helper<10U> { typedef boost::uint16_t exact; };
template<> struct utype_helper<11U> { typedef boost::uint16_t exact; };
template<> struct utype_helper<12U> { typedef boost::uint16_t exact; };
template<> struct utype_helper<13U> { typedef boost::uint16_t exact; };
template<> struct utype_helper<14U> { typedef boost::uint16_t exact; };
template<> struct utype_helper<15U> { typedef boost::uint16_t exact; };
template<> struct utype_helper<16U> { typedef boost::uint16_t exact; };
template <>
struct utype_helper<9U>
{
using exact = std::uint16_t;
};
template <>
struct utype_helper<10U>
{
using exact = std::uint16_t;
};
template <>
struct utype_helper<11U>
{
using exact = std::uint16_t;
};
template <>
struct utype_helper<12U>
{
using exact = std::uint16_t;
};
template <>
struct utype_helper<13U>
{
using exact = std::uint16_t;
};
template <>
struct utype_helper<14U>
{
using exact = std::uint16_t;
};
template <>
struct utype_helper<15U>
{
using exact = std::uint16_t;
};
template <>
struct utype_helper<16U>
{
using exact = std::uint16_t;
};
template<> struct utype_helper<17U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<18U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<19U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<20U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<21U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<22U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<23U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<24U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<25U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<26U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<27U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<28U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<29U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<30U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<31U> { typedef boost::uint32_t exact; };
template<> struct utype_helper<32U> { typedef boost::uint32_t exact; };
template <>
struct utype_helper<17U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<18U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<19U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<20U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<21U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<22U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<23U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<24U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<25U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<26U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<27U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<28U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<29U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<30U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<31U>
{
using exact = std::uint32_t;
};
template <>
struct utype_helper<32U>
{
using exact = std::uint32_t;
};
template<> struct utype_helper<33U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<34U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<35U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<36U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<37U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<38U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<39U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<40U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<41U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<42U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<43U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<44U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<45U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<46U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<47U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<48U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<49U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<50U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<51U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<52U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<53U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<54U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<55U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<56U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<57U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<58U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<59U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<60U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<61U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<62U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<63U> { typedef boost::uint64_t exact; };
template<> struct utype_helper<64U> { typedef boost::uint64_t exact; };
template <>
struct utype_helper<33U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<34U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<35U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<36U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<37U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<38U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<39U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<40U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<41U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<42U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<43U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<44U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<45U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<46U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<47U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<48U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<49U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<50U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<51U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<52U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<53U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<54U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<55U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<56U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<57U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<58U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<59U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<60U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<61U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<62U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<63U>
{
using exact = std::uint64_t;
};
template <>
struct utype_helper<64U>
{
using exact = std::uint64_t;
};
template<class unsigned_type>
int utype_prior(unsigned_type ui)
{
// TBD: Implement a templated binary search for this.
int priority_bit;
template <class unsigned_type>
int utype_prior(unsigned_type ui)
{
// TBD: Implement a templated binary search for this.
int priority_bit;
unsigned_type priority_mask = unsigned_type(unsigned_type(1U) << (std::numeric_limits<unsigned_type>::digits - 1));
unsigned_type priority_mask = unsigned_type(unsigned_type(1U) << (std::numeric_limits<unsigned_type>::digits - 1));
for(priority_bit = std::numeric_limits<unsigned_type>::digits - 1; priority_bit >= 0; --priority_bit)
{
if(unsigned_type(priority_mask & ui) != unsigned_type(0U))
for (priority_bit = std::numeric_limits<unsigned_type>::digits - 1; priority_bit >= 0; --priority_bit)
{
if (unsigned_type(priority_mask & ui) != unsigned_type(0U))
{
break;
break;
}
priority_mask >>= 1;
}
}
return priority_bit;
}
return priority_bit;
}
} } }
}}} // namespace boost::multiprecision::detail
#endif // BOOST_MP_UTYPE_HELPER_HPP