2025-07-06 20:43:53 +03:00
////////////////////////////////////////////////////////////////
2025-10-03 13:44:19 +03:00
// Copyright 2013 - 2025 John Maddock.
// Copyright 2022 - 2025 Christopher Kormanyos.
2025-07-06 20:43:53 +03:00
// Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt
// or copy at https://www.boost.org/LICENSE_1_0.txt)
# ifndef BOOST_MP_CPP_BIN_FLOAT_HPP
# define BOOST_MP_CPP_BIN_FLOAT_HPP
# include <cmath>
# include <cstdint>
# include <limits>
# include <type_traits>
# include <boost/multiprecision/cpp_int.hpp>
# include <boost/multiprecision/integer.hpp>
# include <boost/multiprecision/detail/standalone_config.hpp>
# include <boost/multiprecision/detail/fpclassify.hpp>
# include <boost/multiprecision/detail/float_string_cvt.hpp>
# include <boost/multiprecision/traits/max_digits10.hpp>
# include <boost/multiprecision/detail/hash.hpp>
# include <boost/multiprecision/detail/no_exceptions_support.hpp>
# include <boost/multiprecision/detail/assert.hpp>
# include <boost/multiprecision/detail/float128_functions.hpp>
# include <boost/multiprecision/detail/functions/trunc.hpp>
//
// Some includes we need from Boost.Math, since we rely on that library to provide these functions:
//
# ifdef BOOST_MP_MATH_AVAILABLE
# include <boost/math/special_functions/asinh.hpp>
# include <boost/math/special_functions/acosh.hpp>
# include <boost/math/special_functions/atanh.hpp>
# include <boost/math/special_functions/cbrt.hpp>
# include <boost/math/special_functions/expm1.hpp>
# include <boost/math/special_functions/gamma.hpp>
# endif
# ifdef BOOST_HAS_FLOAT128
# if __has_include(<quadmath.h>)
# include <quadmath.h>
# define BOOST_MP_HAS_FLOAT128_SUPPORT
# endif
# endif
namespace boost {
namespace multiprecision {
namespace backends {
# ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4522 6326) // multiple assignment operators specified, comparison of two constants
# endif
namespace detail {
template < class U >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_unsigned < U > : : value , bool > : : type is_negative ( U ) { return false ; }
template < class S >
inline typename std : : enable_if < ! boost : : multiprecision : : detail : : is_unsigned < S > : : value , bool > : : type is_negative ( S s ) { return s < 0 ; }
template < class Float , std : : ptrdiff_t , bool = number_category < Float > : : value = = number_kind_floating_point >
struct is_cpp_bin_float_implicitly_constructible_from_type
{
static constexpr bool value = false ;
} ;
template < class Float , std : : ptrdiff_t bit_count >
struct is_cpp_bin_float_implicitly_constructible_from_type < Float , bit_count , true >
{
static constexpr bool value = ( std : : numeric_limits < Float > : : digits < = static_cast < int > ( bit_count ) ) & & ( std : : numeric_limits < Float > : : radix = = 2 ) & & std : : numeric_limits < Float > : : is_specialized
# ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
& & ! std : : is_same < Float , float128_type > : : value
# endif
& & ( std : : is_floating_point < Float > : : value | | is_number < Float > : : value ) ;
} ;
template < class Float , std : : ptrdiff_t , bool = number_category < Float > : : value = = number_kind_floating_point >
struct is_cpp_bin_float_explicitly_constructible_from_type
{
static constexpr bool value = false ;
} ;
template < class Float , std : : ptrdiff_t bit_count >
struct is_cpp_bin_float_explicitly_constructible_from_type < Float , bit_count , true >
{
static constexpr bool value = ( std : : numeric_limits < Float > : : digits > static_cast < int > ( bit_count ) ) & & ( std : : numeric_limits < Float > : : radix = = 2 ) & & std : : numeric_limits < Float > : : is_specialized
# ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
& & ! std : : is_same < Float , float128_type > : : value
# endif
;
} ;
} // namespace detail
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinExponent , Exponent MaxExponent >
class cpp_bin_float
{
public :
static constexpr unsigned bit_count = DigitBase = = digit_base_2 ? Digits : ( Digits * 1000uL ) / 301uL + ( ( ( Digits * 1000uL ) % 301 ) ? 2u : 1u ) ;
using rep_type = cpp_int_backend < std : : is_void < Allocator > : : value ? bit_count : 0 , bit_count , std : : is_void < Allocator > : : value ? unsigned_magnitude : signed_magnitude , unchecked , Allocator > ;
using double_rep_type = cpp_int_backend < std : : is_void < Allocator > : : value ? 2 * bit_count : 0 , 2 * bit_count , std : : is_void < Allocator > : : value ? unsigned_magnitude : signed_magnitude , unchecked , Allocator > ;
using signed_types = typename rep_type : : signed_types ;
using unsigned_types = typename rep_type : : unsigned_types ;
using float_types = std : : tuple < float , double , long double > ;
using exponent_type = Exponent ;
static constexpr exponent_type max_exponent_limit = ( std : : numeric_limits < exponent_type > : : max ) ( ) - 2 * static_cast < exponent_type > ( bit_count ) ;
static constexpr exponent_type min_exponent_limit = ( std : : numeric_limits < exponent_type > : : min ) ( ) + 2 * static_cast < exponent_type > ( bit_count ) ;
static_assert ( MinExponent > = min_exponent_limit , " Template parameter MinExponent is too negative for our internal logic to function correctly, sorry! " ) ;
static_assert ( MaxExponent < = max_exponent_limit , " Template parameter MaxExponent is too large for our internal logic to function correctly, sorry! " ) ;
static_assert ( MinExponent < = 0 , " Template parameter MinExponent can not be positive! " ) ;
static_assert ( MaxExponent > = 0 , " Template parameter MaxExponent can not be negative! " ) ;
static constexpr exponent_type max_exponent = MaxExponent = = 0 ? max_exponent_limit : MaxExponent ;
static constexpr exponent_type min_exponent = MinExponent = = 0 ? min_exponent_limit : MinExponent ;
static constexpr exponent_type exponent_zero = max_exponent + 1 ;
static constexpr exponent_type exponent_infinity = max_exponent + 2 ;
static constexpr exponent_type exponent_nan = max_exponent + 3 ;
private :
rep_type m_data ;
exponent_type m_exponent ;
bool m_sign ;
public :
cpp_bin_float ( ) noexcept ( noexcept ( rep_type ( ) ) ) : m_data ( ) , m_exponent ( exponent_zero ) , m_sign ( false ) { }
cpp_bin_float ( const cpp_bin_float & o ) noexcept ( noexcept ( rep_type ( std : : declval < const rep_type & > ( ) ) ) )
: m_data ( o . m_data ) , m_exponent ( o . m_exponent ) , m_sign ( o . m_sign ) { }
template < unsigned D , digit_base_type B , class A , class E , E MinE , E MaxE >
cpp_bin_float ( const cpp_bin_float < D , B , A , E , MinE , MaxE > & o , typename std : : enable_if < ( bit_count > = cpp_bin_float < D , B , A , E , MinE , MaxE > : : bit_count ) > : : type const * = nullptr )
{
* this = o ;
}
template < unsigned D , digit_base_type B , class A , class E , E MinE , E MaxE >
explicit cpp_bin_float ( const cpp_bin_float < D , B , A , E , MinE , MaxE > & o , typename std : : enable_if < ! ( bit_count > = cpp_bin_float < D , B , A , E , MinE , MaxE > : : bit_count ) > : : type const * = nullptr )
: m_exponent ( o . exponent ( ) ) , m_sign ( o . sign ( ) )
{
* this = o ;
}
// rvalue copy:
template < unsigned D , digit_base_type B , class A , class E , E MinE , E MaxE >
cpp_bin_float ( cpp_bin_float < D , B , A , E , MinE , MaxE > & & o , typename std : : enable_if < ( bit_count > = cpp_bin_float < D , B , A , E , MinE , MaxE > : : bit_count ) > : : type const * = nullptr ) noexcept ( noexcept ( rep_type ( std : : declval < rep_type & & > ( ) ) ) )
{
* this = std : : move ( o ) ;
}
template < unsigned D , digit_base_type B , class A , class E , E MinE , E MaxE >
explicit cpp_bin_float ( cpp_bin_float < D , B , A , E , MinE , MaxE > & & o , typename std : : enable_if < ! ( bit_count > = cpp_bin_float < D , B , A , E , MinE , MaxE > : : bit_count ) > : : type const * = nullptr ) noexcept ( noexcept ( rep_type ( std : : declval < rep_type & & > ( ) ) ) )
: m_exponent ( o . exponent ( ) ) , m_sign ( o . sign ( ) )
{
* this = std : : move ( o ) ;
}
template < class Float >
cpp_bin_float ( const Float & f ,
typename std : : enable_if < detail : : is_cpp_bin_float_implicitly_constructible_from_type < Float , static_cast < std : : ptrdiff_t > ( bit_count ) > : : value > : : type const * = nullptr )
: m_data ( ) , m_exponent ( 0 ) , m_sign ( false )
{
this - > assign_float ( f ) ;
}
template < class Float >
explicit cpp_bin_float ( const Float & f ,
typename std : : enable_if < detail : : is_cpp_bin_float_explicitly_constructible_from_type < Float , static_cast < std : : ptrdiff_t > ( bit_count ) > : : value > : : type const * = nullptr )
: m_data ( ) , m_exponent ( 0 ) , m_sign ( false )
{
this - > assign_float ( f ) ;
}
# ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
template < class Float >
cpp_bin_float ( const Float & f ,
typename std : : enable_if <
std : : is_same < Float , float128_type > : : value & & ( static_cast < int > ( bit_count ) > = 113 ) > : : type const * = nullptr )
: m_data ( ) , m_exponent ( 0 ) , m_sign ( false )
{
this - > assign_float ( f ) ;
}
template < class Float >
explicit cpp_bin_float ( const Float & f ,
typename std : : enable_if <
std : : is_same < Float , float128_type > : : value & & ( static_cast < int > ( bit_count ) < 113 ) > : : type const * = nullptr )
: m_data ( ) , m_exponent ( 0 ) , m_sign ( false )
{
this - > assign_float ( f ) ;
}
# endif
cpp_bin_float & operator = ( const cpp_bin_float & o ) noexcept ( noexcept ( std : : declval < rep_type & > ( ) = std : : declval < const rep_type & > ( ) ) )
{
m_data = o . m_data ;
m_exponent = o . m_exponent ;
m_sign = o . m_sign ;
return * this ;
}
template < class A , class E , E MinE , E MaxE >
cpp_bin_float & operator = ( const cpp_bin_float < Digits , DigitBase , A , E , MinE , MaxE > & o ) noexcept ( noexcept ( std : : declval < rep_type & > ( ) = std : : declval < const rep_type & > ( ) ) )
{
m_data = o . bits ( ) ;
m_sign = o . sign ( ) ;
if ( o . exponent ( ) = = cpp_bin_float < Digits , DigitBase , A , E , MinE , MaxE > : : exponent_zero )
m_exponent = exponent_zero ;
else if ( o . exponent ( ) = = cpp_bin_float < Digits , DigitBase , A , E , MinE , MaxE > : : exponent_nan )
m_exponent = exponent_nan ;
else if ( o . exponent ( ) = = cpp_bin_float < Digits , DigitBase , A , E , MinE , MaxE > : : exponent_infinity )
m_exponent = exponent_infinity ;
else if ( o . exponent ( ) > cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent )
{
// Overflow:
exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity ;
bits ( ) = static_cast < limb_type > ( 0u ) ;
}
else if ( o . exponent ( ) < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : min_exponent )
{
// Underflow:
exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ;
bits ( ) = static_cast < limb_type > ( 0u ) ;
}
else
m_exponent = o . exponent ( ) ;
return * this ;
}
// rvalue copy:
template < class A , class E , E MinE , E MaxE >
cpp_bin_float & operator = ( cpp_bin_float < Digits , DigitBase , A , E , MinE , MaxE > & & o ) noexcept ( noexcept ( std : : declval < rep_type & > ( ) = std : : declval < rep_type & & > ( ) ) )
{
m_data = std : : move ( o . bits ( ) ) ;
m_sign = o . sign ( ) ;
if ( o . exponent ( ) = = cpp_bin_float < Digits , DigitBase , A , E , MinE , MaxE > : : exponent_zero )
m_exponent = exponent_zero ;
else if ( o . exponent ( ) = = cpp_bin_float < Digits , DigitBase , A , E , MinE , MaxE > : : exponent_nan )
m_exponent = exponent_nan ;
else if ( o . exponent ( ) = = cpp_bin_float < Digits , DigitBase , A , E , MinE , MaxE > : : exponent_infinity )
m_exponent = exponent_infinity ;
else if ( o . exponent ( ) > cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent )
{
// Overflow:
exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity ;
bits ( ) = static_cast < limb_type > ( 0u ) ;
}
else if ( o . exponent ( ) < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : min_exponent )
{
// Underflow:
exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ;
bits ( ) = static_cast < limb_type > ( 0u ) ;
}
else
m_exponent = o . exponent ( ) ;
return * this ;
}
template < unsigned D , digit_base_type B , class A , class E , E MinE , E MaxE >
cpp_bin_float & operator = ( const cpp_bin_float < D , B , A , E , MinE , MaxE > & f )
{
switch ( eval_fpclassify ( f ) )
{
case FP_ZERO :
m_data = limb_type ( 0 ) ;
m_sign = f . sign ( ) ;
m_exponent = exponent_zero ;
break ;
case FP_NAN :
m_data = limb_type ( 0 ) ;
m_sign = false ;
m_exponent = exponent_nan ;
break ;
;
case FP_INFINITE :
m_data = limb_type ( 0 ) ;
m_sign = f . sign ( ) ;
m_exponent = exponent_infinity ;
break ;
default :
typename cpp_bin_float < D , B , A , E , MinE , MaxE > : : rep_type b ( f . bits ( ) ) ;
this - > exponent ( ) = f . exponent ( ) + ( E ) bit_count - ( E ) cpp_bin_float < D , B , A , E , MinE , MaxE > : : bit_count ;
this - > sign ( ) = f . sign ( ) ;
copy_and_round ( * this , b ) ;
}
return * this ;
}
# ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
template < class Float >
typename std : : enable_if <
( number_category < Float > : : value = = number_kind_floating_point )
//&& (std::numeric_limits<Float>::digits <= static_cast<int>(bit_count))
& & ( ( std : : numeric_limits < Float > : : radix = = 2 ) | | ( std : : is_same < Float , float128_type > : : value ) ) ,
cpp_bin_float & > : : type
operator = ( const Float & f )
# else
template < class Float >
typename std : : enable_if <
( number_category < Float > : : value = = number_kind_floating_point )
//&& (std::numeric_limits<Float>::digits <= static_cast<int>(bit_count))
& & ( std : : numeric_limits < Float > : : radix = = 2 ) ,
cpp_bin_float & > : : type
operator = ( const Float & f )
# endif
{
return assign_float ( f ) ;
}
# ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
template < class Float >
typename std : : enable_if < std : : is_same < Float , float128_type > : : value & & ( std : : numeric_limits < Float > : : digits > Digits ) , cpp_bin_float & > : : type assign_float ( Float f )
{
cpp_bin_float < 113 , DigitBase , Allocator , Exponent , MinExponent , MaxExponent > bf ( f ) ;
return * this = bf ;
}
template < class Float >
typename std : : enable_if < std : : is_same < Float , float128_type > : : value & & ( std : : numeric_limits < Float > : : digits < = Digits ) , cpp_bin_float & > : : type assign_float ( Float f )
{
using default_ops : : eval_add ;
using bf_int_type = typename boost : : multiprecision : : detail : : canonical < int , cpp_bin_float > : : type ;
if ( f = = 0 )
{
m_data = limb_type ( 0 ) ;
m_sign = ( signbitq ( f ) > 0 ) ;
m_exponent = exponent_zero ;
return * this ;
}
else if ( isnanq ( f ) )
{
m_data = limb_type ( 0 ) ;
m_sign = false ;
m_exponent = exponent_nan ;
return * this ;
}
else if ( isinfq ( f ) )
{
m_data = limb_type ( 0 ) ;
m_sign = ( f < 0 ) ;
m_exponent = exponent_infinity ;
return * this ;
}
if ( f < 0 )
{
* this = - f ;
this - > negate ( ) ;
return * this ;
}
using ui_type = typename std : : tuple_element < 0 , unsigned_types > : : type ;
m_data = static_cast < ui_type > ( 0u ) ;
m_sign = false ;
m_exponent = 0 ;
constexpr std : : ptrdiff_t bits = static_cast < Exponent > ( sizeof ( int ) * CHAR_BIT - 1 ) < MaxExponent - 1 ? sizeof ( int ) * CHAR_BIT - 1 : 3 ;
int e ;
f = frexpq ( f , & e ) ;
while ( f )
{
f = ldexpq ( f , bits ) ;
e - = bits ;
int ipart = static_cast < int > ( truncq ( f ) ) ;
f - = ipart ;
m_exponent + = bits ;
cpp_bin_float t ;
t = static_cast < bf_int_type > ( ipart ) ;
eval_add ( * this , t ) ;
}
m_exponent + = static_cast < Exponent > ( e ) ;
if ( m_exponent > max_exponent )
{
m_exponent = exponent_infinity ;
m_data = static_cast < ui_type > ( 0u ) ;
}
else if ( m_exponent < min_exponent )
{
m_exponent = exponent_zero ;
m_data = static_cast < ui_type > ( 0u ) ;
}
return * this ;
}
# endif
# ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
template < class Float >
typename std : : enable_if < std : : is_floating_point < Float > : : value & & ! std : : is_same < Float , float128_type > : : value & & ( std : : numeric_limits < Float > : : digits > Digits ) , cpp_bin_float & > : : type assign_float ( Float f )
# else
template < class Float >
typename std : : enable_if < std : : is_floating_point < Float > : : value & & ( std : : numeric_limits < Float > : : digits > Digits ) , cpp_bin_float & > : : type assign_float ( Float f )
# endif
{
cpp_bin_float < std : : numeric_limits < Float > : : digits , DigitBase , Allocator , Exponent , MinExponent , MaxExponent > bf ( f ) ;
return * this = bf ;
}
# ifdef BOOST_MP_HAS_FLOAT128_SUPPORT
template < class Float >
typename std : : enable_if < std : : is_floating_point < Float > : : value & & ! std : : is_same < Float , float128_type > : : value & & ( std : : numeric_limits < Float > : : digits < = Digits ) , cpp_bin_float & > : : type assign_float ( Float f )
# else
template < class Float >
typename std : : enable_if < std : : is_floating_point < Float > : : value & & ( std : : numeric_limits < Float > : : digits < = Digits ) , cpp_bin_float & > : : type assign_float ( Float f )
# endif
{
using std : : frexp ;
using std : : ldexp ;
using std : : signbit ;
using default_ops : : eval_add ;
using bf_int_type = typename boost : : multiprecision : : detail : : canonical < int , cpp_bin_float > : : type ;
switch ( BOOST_MP_FPCLASSIFY ( f ) )
{
case FP_ZERO :
m_data = limb_type ( 0 ) ;
m_sign = ( ( signbit ) ( f ) ) ;
m_exponent = exponent_zero ;
return * this ;
case FP_NAN :
m_data = limb_type ( 0 ) ;
m_sign = false ;
m_exponent = exponent_nan ;
return * this ;
case FP_INFINITE :
m_data = limb_type ( 0 ) ;
m_sign = ( f < 0 ) ;
m_exponent = exponent_infinity ;
return * this ;
default :
break ;
}
if ( f < 0 )
{
* this = - f ;
this - > negate ( ) ;
return * this ;
}
using ui_type = typename std : : tuple_element < 0 , unsigned_types > : : type ;
m_data = static_cast < ui_type > ( 0u ) ;
m_sign = false ;
m_exponent = 0 ;
//
// This code picks off the bits in f a few at a time and injects them into *this.
// It does not do roundingm so we must have more digits precision in *this than
// in the floating point value (the normal situation, unless we're emulating another
// type like float16_t).
//
constexpr std : : ptrdiff_t bits = static_cast < std : : ptrdiff_t > ( sizeof ( int ) * CHAR_BIT - 1 ) < static_cast < std : : ptrdiff_t > ( MaxExponent - 1 ) ? static_cast < std : : ptrdiff_t > ( sizeof ( int ) * CHAR_BIT - 1 ) : 3 ;
int e ;
f = frexp ( f , & e ) ;
while ( f ! = static_cast < Float > ( 0.0F ) )
{
f = ldexp ( f , bits ) ;
e - = static_cast < int > ( bits ) ;
int ipart = boost : : multiprecision : : detail : : itrunc ( f ) ;
f - = static_cast < Float > ( ipart ) ;
m_exponent + = static_cast < exponent_type > ( bits ) ;
cpp_bin_float t ;
t = static_cast < bf_int_type > ( ipart ) ;
eval_add ( * this , t ) ;
}
m_exponent + = static_cast < Exponent > ( e ) ;
if ( m_exponent > max_exponent )
{
m_exponent = exponent_infinity ;
m_data = static_cast < ui_type > ( 0u ) ;
}
else if ( m_exponent < min_exponent )
{
m_exponent = exponent_zero ;
m_data = static_cast < ui_type > ( 0u ) ;
}
return * this ;
}
template < class Float >
typename std : : enable_if <
( number_category < Float > : : value = = number_kind_floating_point ) & & ! std : : is_floating_point < Float > : : value & & ( number_category < Float > : : value = = number_kind_floating_point ) ,
cpp_bin_float & > : : type
assign_float ( Float f )
{
using default_ops : : eval_add ;
using default_ops : : eval_convert_to ;
using default_ops : : eval_get_sign ;
using default_ops : : eval_subtract ;
using f_int_type = typename boost : : multiprecision : : detail : : canonical < int , Float > : : type ;
using bf_int_type = typename boost : : multiprecision : : detail : : canonical < int , cpp_bin_float > : : type ;
switch ( eval_fpclassify ( f ) )
{
case FP_ZERO :
m_data = limb_type ( 0 ) ;
m_sign = ( eval_get_sign ( f ) > 0 ) ;
m_exponent = exponent_zero ;
return * this ;
case FP_NAN :
m_data = limb_type ( 0 ) ;
m_sign = false ;
m_exponent = exponent_nan ;
return * this ;
case FP_INFINITE :
m_data = limb_type ( 0 ) ;
m_sign = eval_get_sign ( f ) < 0 ;
m_exponent = exponent_infinity ;
return * this ;
default :
break ;
}
if ( eval_get_sign ( f ) < 0 )
{
f . negate ( ) ;
assign_float ( f ) ;
this - > negate ( ) ;
return * this ;
}
using ui_type = typename std : : tuple_element < 0 , unsigned_types > : : type ;
m_data = static_cast < ui_type > ( 0u ) ;
m_sign = false ;
m_exponent = 0 ;
constexpr std : : ptrdiff_t bits = sizeof ( int ) * CHAR_BIT - 1 ;
int e ;
eval_frexp ( f , f , & e ) ;
while ( eval_get_sign ( f ) ! = 0 )
{
eval_ldexp ( f , f , bits ) ;
e - = bits ;
int ipart ;
eval_convert_to ( & ipart , f ) ;
eval_subtract ( f , static_cast < f_int_type > ( ipart ) ) ;
m_exponent + = bits ;
eval_add ( * this , static_cast < bf_int_type > ( ipart ) ) ;
}
m_exponent + = e ;
if ( m_exponent > max_exponent )
m_exponent = exponent_infinity ;
if ( m_exponent < min_exponent )
{
m_data = limb_type ( 0u ) ;
m_exponent = exponent_zero ;
m_sign = ( eval_get_sign ( f ) > 0 ) ;
}
else if ( eval_get_sign ( m_data ) = = 0 )
{
m_exponent = exponent_zero ;
m_sign = ( eval_get_sign ( f ) > 0 ) ;
}
return * this ;
}
template < class B , expression_template_option et >
cpp_bin_float & assign_float ( const number < B , et > & f )
{
return assign_float ( f . backend ( ) ) ;
}
template < class I >
typename std : : enable_if < boost : : multiprecision : : detail : : is_integral < I > : : value , cpp_bin_float & > : : type operator = ( const I & i )
{
using default_ops : : eval_bit_test ;
if ( ! i )
{
m_data = static_cast < limb_type > ( 0 ) ;
m_exponent = exponent_zero ;
m_sign = false ;
}
else
{
using ui_type = typename boost : : multiprecision : : detail : : make_unsigned < I > : : type ;
ui_type fi = static_cast < ui_type > ( boost : : multiprecision : : detail : : unsigned_abs ( i ) ) ;
using ar_type = typename boost : : multiprecision : : detail : : canonical < ui_type , rep_type > : : type ;
m_data = static_cast < ar_type > ( fi ) ;
std : : size_t shift = msb ( fi ) ;
if ( shift > max_exponent )
{
m_exponent = exponent_infinity ;
m_data = static_cast < limb_type > ( 0 ) ;
}
else if ( shift > = bit_count )
{
m_exponent = static_cast < Exponent > ( shift ) ;
m_data = static_cast < ar_type > ( fi > > ( shift + 1 - bit_count ) ) ;
}
else
{
m_exponent = static_cast < Exponent > ( shift ) ;
eval_left_shift ( m_data , bit_count - shift - 1 ) ;
}
BOOST_MP_ASSERT ( ( m_exponent = = exponent_infinity ) | | eval_bit_test ( m_data , bit_count - 1 ) ) ;
m_sign = detail : : is_negative ( i ) ;
}
return * this ;
}
cpp_bin_float & operator = ( const char * s ) ;
void swap ( cpp_bin_float & o ) noexcept
{
m_data . swap ( o . m_data ) ;
std : : swap ( m_exponent , o . m_exponent ) ;
std : : swap ( m_sign , o . m_sign ) ;
}
std : : string str ( std : : streamsize dig , std : : ios_base : : fmtflags f ) const ;
void negate ( )
{
if ( m_exponent ! = exponent_nan )
m_sign = ! m_sign ;
}
int compare ( const cpp_bin_float & o ) const noexcept
{
if ( m_sign ! = o . m_sign )
return ( m_exponent = = exponent_zero ) & & ( m_exponent = = o . m_exponent ) ? 0 : m_sign ? - 1 : 1 ;
int result ;
if ( m_exponent = = exponent_nan )
return - 1 ;
else if ( m_exponent ! = o . m_exponent )
{
if ( m_exponent = = exponent_zero )
result = - 1 ;
else if ( o . m_exponent = = exponent_zero )
result = 1 ;
else
result = m_exponent > o . m_exponent ? 1 : - 1 ;
}
else
result = m_data . compare ( o . m_data ) ;
if ( m_sign )
result = - result ;
return result ;
}
template < class A >
int compare ( const A & o ) const noexcept
{
cpp_bin_float b ;
b = o ;
return compare ( b ) ;
}
rep_type & bits ( ) { return m_data ; }
const rep_type & bits ( ) const { return m_data ; }
exponent_type & exponent ( ) { return m_exponent ; }
const exponent_type & exponent ( ) const { return m_exponent ; }
bool & sign ( ) { return m_sign ; }
const bool & sign ( ) const { return m_sign ; }
void check_invariants ( )
{
using default_ops : : eval_bit_test ;
using default_ops : : eval_is_zero ;
if ( ( m_exponent < = max_exponent ) & & ( m_exponent > = min_exponent ) )
{
BOOST_MP_ASSERT ( eval_bit_test ( m_data , bit_count - 1 ) ) ;
}
else
{
BOOST_MP_ASSERT ( m_exponent > max_exponent ) ;
BOOST_MP_ASSERT ( m_exponent < = exponent_nan ) ;
BOOST_MP_ASSERT ( eval_is_zero ( m_data ) ) ;
}
}
# ifndef BOOST_MP_STANDALONE
template < class Archive >
void serialize ( Archive & ar , const unsigned int /*version*/ )
{
ar & boost : : make_nvp ( " data " , m_data ) ;
ar & boost : : make_nvp ( " exponent " , m_exponent ) ;
ar & boost : : make_nvp ( " sign " , m_sign ) ;
}
# endif
} ;
# ifdef BOOST_MSVC
# pragma warning(pop)
# endif
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class Int >
inline void copy_and_round ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , Int & arg , std : : ptrdiff_t bits_to_keep = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count )
{
// Precondition: exponent of res must have been set before this function is called
// as we may need to adjust it based on how many bits_to_keep in arg are set.
using default_ops : : eval_bit_test ;
using default_ops : : eval_get_sign ;
using default_ops : : eval_increment ;
using default_ops : : eval_left_shift ;
using default_ops : : eval_lsb ;
using default_ops : : eval_msb ;
using default_ops : : eval_right_shift ;
// cancellation may have resulted in arg being all zeros:
if ( eval_get_sign ( arg ) = = 0 )
{
res . exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ;
res . sign ( ) = false ;
res . bits ( ) = static_cast < limb_type > ( 0u ) ;
return ;
}
std : : ptrdiff_t msb = static_cast < std : : ptrdiff_t > ( eval_msb ( arg ) ) ;
if ( static_cast < std : : ptrdiff_t > ( bits_to_keep ) > msb + 1 )
{
// Must have had cancellation in subtraction,
// or be converting from a narrower type, so shift left:
res . bits ( ) = arg ;
eval_left_shift ( res . bits ( ) , static_cast < double_limb_type > ( bits_to_keep - msb - 1 ) ) ;
res . exponent ( ) - = static_cast < Exponent > ( bits_to_keep - msb - 1 ) ;
}
else if ( static_cast < std : : ptrdiff_t > ( bits_to_keep ) < msb + 1 )
{
// We have more bits_to_keep than we need, so round as required,
// first get the rounding bit:
bool roundup = eval_bit_test ( arg , static_cast < std : : size_t > ( msb - bits_to_keep ) ) ;
// Then check for a tie:
if ( roundup & & ( msb - bits_to_keep = = static_cast < std : : ptrdiff_t > ( eval_lsb ( arg ) ) ) )
{
// Ties round towards even:
if ( ! eval_bit_test ( arg , static_cast < std : : size_t > ( msb - bits_to_keep + 1 ) ) )
roundup = false ;
}
// Shift off the bits_to_keep we don't need:
eval_right_shift ( arg , static_cast < double_limb_type > ( msb - bits_to_keep + 1 ) ) ;
res . exponent ( ) + = static_cast < Exponent > ( msb - bits_to_keep + 1 ) ;
if ( roundup )
{
eval_increment ( arg ) ;
if ( bits_to_keep )
{
if ( eval_bit_test ( arg , static_cast < std : : size_t > ( bits_to_keep ) ) )
{
// This happens very very rairly, all the bits left after
// truncation must be 1's and we're rounding up an order of magnitude:
eval_right_shift ( arg , 1u ) ;
+ + res . exponent ( ) ;
}
}
else
{
// We get here when bits_to_keep is zero but we're rounding up,
// as a result we end up with a single digit that is a 1:
+ + bits_to_keep ;
}
}
if ( bits_to_keep ! = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count )
{
// Normalize result when we're rounding to fewer bits than we can hold, only happens in conversions
// to narrower types:
eval_left_shift ( arg , static_cast < double_limb_type > ( static_cast < std : : ptrdiff_t > ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) - bits_to_keep ) ) ;
res . exponent ( ) - = static_cast < Exponent > ( static_cast < std : : ptrdiff_t > ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) - bits_to_keep ) ;
}
res . bits ( ) = arg ;
}
else
{
res . bits ( ) = arg ;
}
if ( ! bits_to_keep & & ! res . bits ( ) . limbs ( ) [ 0 ] )
{
// We're keeping zero bits and did not round up, so result is zero:
res . exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ;
return ;
}
// Result must be normalized:
BOOST_MP_ASSERT ( ( ( std : : ptrdiff_t ) eval_msb ( res . bits ( ) ) = = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - 1 ) ) ;
if ( res . exponent ( ) > cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent )
{
// Overflow:
res . exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity ;
res . bits ( ) = static_cast < limb_type > ( 0u ) ;
}
else if ( res . exponent ( ) < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : min_exponent )
{
// Underflow:
res . exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ;
res . bits ( ) = static_cast < limb_type > ( 0u ) ;
}
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class BinFloat2 , class BinFloat3 >
inline void do_eval_add ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const BinFloat2 & a , const BinFloat3 & b )
{
if ( a . exponent ( ) < b . exponent ( ) )
{
bool s = a . sign ( ) ;
do_eval_add ( res , b , a ) ;
if ( res . sign ( ) ! = s )
res . negate ( ) ;
return ;
}
using default_ops : : eval_add ;
using default_ops : : eval_bit_test ;
using exponent_type = typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type ;
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : double_rep_type dt ;
// Special cases first:
switch ( a . exponent ( ) )
{
case BinFloat2 : : exponent_zero :
{
bool s = a . sign ( ) ;
res = b ;
res . sign ( ) = s ;
return ;
}
case BinFloat2 : : exponent_infinity :
if ( b . exponent ( ) = = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan )
res = b ;
else
res = a ;
return ; // result is still infinite.
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
res = a ;
return ; // result is still a NaN.
default :
break ;
}
switch ( b . exponent ( ) )
{
case BinFloat3 : : exponent_zero :
res = a ;
return ;
case BinFloat3 : : exponent_infinity :
res = b ;
if ( res . sign ( ) )
res . negate ( ) ;
return ; // result is infinite.
case BinFloat3 : : exponent_nan :
res = b ;
return ; // result is a NaN.
default :
break ;
}
static_assert ( ( std : : numeric_limits < exponent_type > : : max ) ( ) - cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count > cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent , " Exponent range check failed " ) ;
bool s = a . sign ( ) ;
dt = a . bits ( ) ;
if ( a . exponent ( ) > ( std : : ptrdiff_t ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count + b . exponent ( ) )
{
res . exponent ( ) = a . exponent ( ) ;
}
else
{
exponent_type e_diff = a . exponent ( ) - b . exponent ( ) ;
BOOST_MP_ASSERT ( e_diff > = 0 ) ;
eval_left_shift ( dt , static_cast < double_limb_type > ( e_diff ) ) ;
res . exponent ( ) = a . exponent ( ) - e_diff ;
eval_add ( dt , b . bits ( ) ) ;
}
copy_and_round ( res , dt ) ;
res . check_invariants ( ) ;
if ( res . sign ( ) ! = s )
res . negate ( ) ;
}
template < class BinFloat1 , class BinFloat2 , class BinFloat3 >
inline void do_eval_subtract ( BinFloat1 & res , const BinFloat2 & a , const BinFloat3 & b )
{
using default_ops : : eval_bit_test ;
using default_ops : : eval_decrement ;
using default_ops : : eval_subtract ;
typename BinFloat1 : : double_rep_type dt ;
// Special cases first:
switch ( a . exponent ( ) )
{
case BinFloat2 : : exponent_zero :
if ( b . exponent ( ) = = BinFloat3 : : exponent_nan )
res = std : : numeric_limits < number < BinFloat1 > > : : quiet_NaN ( ) . backend ( ) ;
else
{
bool s = a . sign ( ) ;
res = b ;
if ( res . exponent ( ) = = BinFloat1 : : exponent_zero )
res . sign ( ) = false ;
else if ( res . sign ( ) = = s )
res . negate ( ) ;
}
return ;
case BinFloat2 : : exponent_infinity :
if ( ( b . exponent ( ) = = BinFloat3 : : exponent_nan ) | | ( b . exponent ( ) = = BinFloat3 : : exponent_infinity ) )
res = std : : numeric_limits < number < BinFloat1 > > : : quiet_NaN ( ) . backend ( ) ;
else
res = a ;
return ;
case BinFloat2 : : exponent_nan :
res = a ;
return ; // result is still a NaN.
default :
break ;
}
switch ( b . exponent ( ) )
{
case BinFloat3 : : exponent_zero :
res = a ;
return ;
case BinFloat3 : : exponent_infinity :
res . exponent ( ) = BinFloat1 : : exponent_infinity ;
res . sign ( ) = ! a . sign ( ) ;
res . bits ( ) = static_cast < limb_type > ( 0u ) ;
return ; // result is a NaN.
case BinFloat3 : : exponent_nan :
res = b ;
return ; // result is still a NaN.
default :
break ;
}
bool s = a . sign ( ) ;
if ( ( a . exponent ( ) > b . exponent ( ) ) | | ( ( a . exponent ( ) = = b . exponent ( ) ) & & a . bits ( ) . compare ( b . bits ( ) ) > = 0 ) )
{
dt = a . bits ( ) ;
if ( a . exponent ( ) < = ( std : : ptrdiff_t ) BinFloat1 : : bit_count + b . exponent ( ) )
{
typename BinFloat1 : : exponent_type e_diff = a . exponent ( ) - b . exponent ( ) ;
eval_left_shift ( dt , static_cast < double_limb_type > ( e_diff ) ) ;
res . exponent ( ) = a . exponent ( ) - e_diff ;
eval_subtract ( dt , b . bits ( ) ) ;
}
else if ( a . exponent ( ) = = ( std : : ptrdiff_t ) BinFloat1 : : bit_count + b . exponent ( ) + 1 )
{
if ( ( eval_lsb ( a . bits ( ) ) = = BinFloat1 : : bit_count - 1 )
& & ( eval_lsb ( b . bits ( ) ) ! = BinFloat1 : : bit_count - 1 ) )
{
eval_left_shift ( dt , 1 ) ;
eval_decrement ( dt ) ;
res . exponent ( ) = a . exponent ( ) - 1 ;
}
else
res . exponent ( ) = a . exponent ( ) ;
}
else
res . exponent ( ) = a . exponent ( ) ;
}
else
{
dt = b . bits ( ) ;
if ( b . exponent ( ) < = ( std : : ptrdiff_t ) BinFloat1 : : bit_count + a . exponent ( ) )
{
typename BinFloat1 : : exponent_type e_diff = a . exponent ( ) - b . exponent ( ) ;
eval_left_shift ( dt , static_cast < double_limb_type > ( - e_diff ) ) ;
res . exponent ( ) = b . exponent ( ) + e_diff ;
eval_subtract ( dt , a . bits ( ) ) ;
}
else if ( b . exponent ( ) = = ( std : : ptrdiff_t ) BinFloat1 : : bit_count + a . exponent ( ) + 1 )
{
if ( ( eval_lsb ( a . bits ( ) ) ! = BinFloat1 : : bit_count - 1 )
& & eval_lsb ( b . bits ( ) ) )
{
eval_left_shift ( dt , 1 ) ;
eval_decrement ( dt ) ;
res . exponent ( ) = b . exponent ( ) - 1 ;
}
else
res . exponent ( ) = b . exponent ( ) ;
}
else
res . exponent ( ) = b . exponent ( ) ;
s = ! s ;
}
copy_and_round ( res , dt ) ;
if ( res . exponent ( ) = = BinFloat1 : : exponent_zero )
res . sign ( ) = false ;
else if ( res . sign ( ) ! = s )
res . negate ( ) ;
res . check_invariants ( ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 ,
class Allocator3 , class Exponent3 , Exponent MinE3 , Exponent MaxE3 >
inline void eval_add ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & a ,
const cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > & b )
{
if ( a . sign ( ) = = b . sign ( ) )
do_eval_add ( res , a , b ) ;
else
do_eval_subtract ( res , a , b ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 >
inline void eval_add ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & a )
{
return eval_add ( res , res , a ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 ,
class Allocator3 , class Exponent3 , Exponent MinE3 , Exponent MaxE3 >
inline void eval_subtract ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & a ,
const cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > & b )
{
if ( a . sign ( ) ! = b . sign ( ) )
do_eval_add ( res , a , b ) ;
else
do_eval_subtract ( res , a , b ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 >
inline void eval_subtract ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & a )
{
return eval_subtract ( res , res , a ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 ,
class Allocator3 , class Exponent3 , Exponent MinE3 , Exponent MaxE3 >
inline void eval_multiply ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & a ,
const cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > & b )
{
using default_ops : : eval_bit_test ;
using default_ops : : eval_multiply ;
// Special cases first:
switch ( a . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_zero :
{
if ( b . exponent ( ) = = cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_nan )
res = b ;
else if ( b . exponent ( ) = = cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_infinity )
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
else
{
bool s = a . sign ( ) ! = b . sign ( ) ;
res = a ;
res . sign ( ) = s ;
}
return ;
}
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_infinity :
switch ( b . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_zero :
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
break ;
case cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_nan :
res = b ;
break ;
default :
bool s = a . sign ( ) ! = b . sign ( ) ;
res = a ;
res . sign ( ) = s ;
break ;
}
return ;
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_nan :
res = a ;
return ;
default :
break ;
}
if ( b . exponent ( ) > cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : max_exponent )
{
bool s = a . sign ( ) ! = b . sign ( ) ;
res = b ;
res . sign ( ) = s ;
return ;
}
if ( ( a . exponent ( ) > 0 ) & & ( b . exponent ( ) > 0 ) )
{
if ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent + 2 - a . exponent ( ) < b . exponent ( ) )
{
// We will certainly overflow:
bool s = a . sign ( ) ! = b . sign ( ) ;
res . exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity ;
res . sign ( ) = s ;
res . bits ( ) = static_cast < limb_type > ( 0u ) ;
return ;
}
}
if ( ( a . exponent ( ) < 0 ) & & ( b . exponent ( ) < 0 ) )
{
if ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : min_exponent - 2 - a . exponent ( ) > b . exponent ( ) )
{
// We will certainly underflow:
res . exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ;
res . sign ( ) = a . sign ( ) ! = b . sign ( ) ;
res . bits ( ) = static_cast < limb_type > ( 0u ) ;
return ;
}
}
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : double_rep_type dt ;
eval_multiply ( dt , a . bits ( ) , b . bits ( ) ) ;
res . exponent ( ) = a . exponent ( ) + b . exponent ( ) - ( Exponent ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count + 1 ;
copy_and_round ( res , dt ) ;
res . check_invariants ( ) ;
res . sign ( ) = a . sign ( ) ! = b . sign ( ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 >
inline void eval_multiply ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & a )
{
eval_multiply ( res , res , a ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 , class U >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_unsigned < U > : : value > : : type eval_multiply ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & a , const U & b )
{
using default_ops : : eval_bit_test ;
using default_ops : : eval_multiply ;
bool s = a . sign ( ) ; // saved for later in case a and res are the same object.
// Special cases first:
switch ( a . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_zero :
{
res = a ;
res . sign ( ) = s ;
return ;
}
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_infinity :
if ( b = = 0 )
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
else
res = a ;
return ;
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_nan :
res = a ;
return ;
default :
break ;
}
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : double_rep_type dt ;
using canon_ui_type = typename boost : : multiprecision : : detail : : canonical < U , typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : double_rep_type > : : type ;
eval_multiply ( dt , a . bits ( ) , static_cast < canon_ui_type > ( b ) ) ;
res . exponent ( ) = a . exponent ( ) ;
copy_and_round ( res , dt ) ;
res . check_invariants ( ) ;
res . sign ( ) = s ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class U >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_unsigned < U > : : value > : : type eval_multiply ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const U & b )
{
eval_multiply ( res , res , b ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 , class S >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_signed < S > : : value & & boost : : multiprecision : : detail : : is_integral < S > : : value > : : type eval_multiply ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & a , const S & b )
{
using ui_type = typename boost : : multiprecision : : detail : : make_unsigned < S > : : type ;
eval_multiply ( res , a , static_cast < ui_type > ( boost : : multiprecision : : detail : : unsigned_abs ( b ) ) ) ;
if ( b < 0 )
res . negate ( ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class S >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_signed < S > : : value & & boost : : multiprecision : : detail : : is_integral < S > : : value > : : type eval_multiply ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const S & b )
{
eval_multiply ( res , res , b ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 ,
class Allocator3 , class Exponent3 , Exponent MinE3 , Exponent MaxE3 >
inline void eval_divide ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & u ,
const cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > & v )
{
# ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 6326) // comparison of two constants
# endif
using default_ops : : eval_bit_test ;
using default_ops : : eval_get_sign ;
using default_ops : : eval_increment ;
using default_ops : : eval_qr ;
using default_ops : : eval_subtract ;
//
// Special cases first:
//
switch ( u . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_zero :
{
switch ( v . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_zero :
case cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_nan :
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
return ;
default :
break ;
}
bool s = u . sign ( ) ! = v . sign ( ) ;
res = u ;
res . sign ( ) = s ;
return ;
}
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_infinity :
{
switch ( v . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_infinity :
case cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_nan :
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
return ;
default :
break ;
}
bool s = u . sign ( ) ! = v . sign ( ) ;
res = u ;
res . sign ( ) = s ;
return ;
}
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_nan :
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
return ;
default :
break ;
}
switch ( v . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_zero :
{
bool s = u . sign ( ) ! = v . sign ( ) ;
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : infinity ( ) . backend ( ) ;
res . sign ( ) = s ;
return ;
}
case cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_infinity :
res . exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ;
res . bits ( ) = limb_type ( 0 ) ;
res . sign ( ) = u . sign ( ) ! = v . sign ( ) ;
return ;
case cpp_bin_float < Digits , DigitBase , Allocator3 , Exponent3 , MinE3 , MaxE3 > : : exponent_nan :
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
return ;
default :
break ;
}
// We can scale u and v so that both are integers, then perform integer
// division to obtain quotient q and remainder r, such that:
//
// q * v + r = u
//
// and hense:
//
// q + r/v = u/v
//
// From this, assuming q has cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count
// bits we only need to determine whether
// r/v is less than, equal to, or greater than 0.5 to determine rounding -
// this we can do with a shift and comparison.
//
// We can set the exponent and sign of the result up front:
//
if ( ( v . exponent ( ) < 0 ) & & ( u . exponent ( ) > 0 ) )
{
// Check for overflow:
if ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent + v . exponent ( ) < u . exponent ( ) - 1 )
{
res . exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity ;
res . sign ( ) = u . sign ( ) ! = v . sign ( ) ;
res . bits ( ) = static_cast < limb_type > ( 0u ) ;
return ;
}
}
else if ( ( v . exponent ( ) > 0 ) & & ( u . exponent ( ) < 0 ) )
{
// Check for underflow:
if ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : min_exponent + v . exponent ( ) > u . exponent ( ) )
{
// We will certainly underflow:
res . exponent ( ) = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ;
res . sign ( ) = u . sign ( ) ! = v . sign ( ) ;
res . bits ( ) = static_cast < limb_type > ( 0u ) ;
return ;
}
}
res . exponent ( ) = u . exponent ( ) - v . exponent ( ) - 1 ;
res . sign ( ) = u . sign ( ) ! = v . sign ( ) ;
//
// Now get the quotient and remainder:
//
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : double_rep_type t ( u . bits ( ) ) , t2 ( v . bits ( ) ) , q , r ;
eval_left_shift ( t , cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) ;
eval_qr ( t , t2 , q , r ) ;
//
// We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count"
// or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant
// bits in q.
//
constexpr unsigned limb_bits = sizeof ( limb_type ) * CHAR_BIT ;
if ( eval_bit_test ( q , cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) )
{
//
// OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 bits,
// so we already have rounding info,
// we just need to changes things if the last bit is 1 and either the
// remainder is non-zero (ie we do not have a tie) or the quotient would
// be odd if it were shifted to the correct number of bits (ie a tiebreak).
//
BOOST_MP_ASSERT ( ( eval_msb ( q ) = = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) ) ;
if ( ( q . limbs ( ) [ 0 ] & 1u ) & & ( eval_get_sign ( r ) | | ( q . limbs ( ) [ 0 ] & 2u ) ) )
{
eval_increment ( q ) ;
}
}
else
{
//
// We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" bits in q.
// Get rounding info, which we can get by comparing 2r with v.
// We want to call copy_and_round to handle rounding and general cleanup,
// so we'll left shift q and add some fake digits on the end to represent
// how we'll be rounding.
//
using local_exponent_type = typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type ;
BOOST_MP_ASSERT ( ( eval_msb ( q ) = = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - 1 ) ) ;
constexpr unsigned lshift = ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count < limb_bits ) ? 2 : limb_bits ;
eval_left_shift ( q , lshift ) ;
res . exponent ( ) - = static_cast < local_exponent_type > ( lshift ) ;
eval_left_shift ( r , 1u ) ;
int c = r . compare ( v . bits ( ) ) ;
if ( c = = 0 )
q . limbs ( ) [ 0 ] | = static_cast < limb_type > ( 1u ) < < ( lshift - 1 ) ;
else if ( c > 0 )
q . limbs ( ) [ 0 ] | = ( static_cast < limb_type > ( 1u ) < < ( lshift - 1 ) ) + static_cast < limb_type > ( 1u ) ;
}
copy_and_round ( res , q ) ;
# ifdef BOOST_MSVC
# pragma warning(pop)
# endif
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 >
inline void eval_divide ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & arg )
{
eval_divide ( res , res , arg ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 , class U >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_unsigned < U > : : value & & ( std : : numeric_limits < U > : : digits < = Digits ) > : : type eval_divide ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & u , const U & v )
{
# ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 6326) // comparison of two constants
# endif
using default_ops : : eval_bit_test ;
using default_ops : : eval_get_sign ;
using default_ops : : eval_increment ;
using default_ops : : eval_qr ;
using default_ops : : eval_subtract ;
//
// Special cases first:
//
switch ( u . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_zero :
{
if ( v = = 0 )
{
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
return ;
}
bool s = u . sign ( ) ! = ( v < 0 ) ;
res = u ;
res . sign ( ) = s ;
return ;
}
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_infinity :
res = u ;
return ;
case cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > : : exponent_nan :
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
return ;
default :
break ;
}
if ( v = = 0 )
{
bool s = u . sign ( ) ;
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : infinity ( ) . backend ( ) ;
res . sign ( ) = s ;
return ;
}
// We can scale u and v so that both are integers, then perform integer
// division to obtain quotient q and remainder r, such that:
//
// q * v + r = u
//
// and hense:
//
// q + r/v = u/v
//
// From this, assuming q has "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, we only need to determine whether
// r/v is less than, equal to, or greater than 0.5 to determine rounding -
// this we can do with a shift and comparison.
//
// We can set the exponent and sign of the result up front:
//
std : : ptrdiff_t gb = static_cast < std : : ptrdiff_t > ( msb ( v ) ) ;
res . exponent ( ) = u . exponent ( ) - static_cast < Exponent > ( gb ) - static_cast < Exponent > ( 1 ) ;
res . sign ( ) = u . sign ( ) ;
//
// Now get the quotient and remainder:
//
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : double_rep_type t ( u . bits ( ) ) , q , r ;
eval_left_shift ( t , static_cast < double_limb_type > ( gb + 1 ) ) ;
eval_qr ( t , number < typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : double_rep_type > : : canonical_value ( v ) , q , r ) ;
//
// We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q.
//
constexpr unsigned limb_bits = sizeof ( limb_type ) * CHAR_BIT ;
if ( eval_bit_test ( q , cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) )
{
//
// OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, so we already have rounding info,
// we just need to changes things if the last bit is 1 and the
// remainder is non-zero (ie we do not have a tie).
//
BOOST_MP_ASSERT ( ( eval_msb ( q ) = = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) ) ;
if ( ( q . limbs ( ) [ 0 ] & 1u ) & & eval_get_sign ( r ) )
{
eval_increment ( q ) ;
}
}
else
{
//
// We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q.
// Get rounding info, which we can get by comparing 2r with v.
// We want to call copy_and_round to handle rounding and general cleanup,
// so we'll left shift q and add some fake cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count on the end to represent
// how we'll be rounding.
//
using local_exponent_type = typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type ;
BOOST_MP_ASSERT ( ( eval_msb ( q ) = = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - 1 ) ) ;
constexpr unsigned lshift = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count < limb_bits ? 2 : limb_bits ;
eval_left_shift ( q , lshift ) ;
res . exponent ( ) - = static_cast < local_exponent_type > ( lshift ) ;
eval_left_shift ( r , 1u ) ;
int c = r . compare ( number < typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : double_rep_type > : : canonical_value ( v ) ) ;
if ( c = = 0 )
q . limbs ( ) [ 0 ] | = static_cast < limb_type > ( 1u ) < < ( lshift - 1 ) ;
else if ( c > 0 )
q . limbs ( ) [ 0 ] | = ( static_cast < limb_type > ( 1u ) < < ( lshift - 1 ) ) + static_cast < limb_type > ( 1u ) ;
}
copy_and_round ( res , q ) ;
# ifdef BOOST_MSVC
# pragma warning(pop)
# endif
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class U >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_unsigned < U > : : value & & ( std : : numeric_limits < U > : : digits < = Digits ) > : : type eval_divide ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const U & v )
{
eval_divide ( res , res , v ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 , class S >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_signed < S > : : value & & boost : : multiprecision : : detail : : is_integral < S > : : value & & ( std : : numeric_limits < S > : : digits < = Digits ) > : : type eval_divide ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res ,
const cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > & u , const S & v )
{
using ui_type = typename boost : : multiprecision : : detail : : make_unsigned < S > : : type ;
eval_divide ( res , u , static_cast < ui_type > ( boost : : multiprecision : : detail : : unsigned_abs ( v ) ) ) ;
if ( v < 0 )
res . negate ( ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class S >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_signed < S > : : value & & boost : : multiprecision : : detail : : is_integral < S > : : value & & ( std : : numeric_limits < S > : : digits < = Digits ) > : : type eval_divide ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const S & v )
{
eval_divide ( res , res , v ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline int eval_get_sign ( const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
return arg . exponent ( ) = = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ? 0 : arg . sign ( ) ? - 1 : 1 ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline bool eval_is_zero ( const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
return arg . exponent ( ) = = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline bool eval_eq ( const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & a , cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & b )
{
if ( a . exponent ( ) = = b . exponent ( ) )
{
if ( a . exponent ( ) = = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero )
return true ;
return ( a . sign ( ) = = b . sign ( ) ) & & ( a . bits ( ) . compare ( b . bits ( ) ) = = 0 ) & & ( a . exponent ( ) ! = cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan ) ;
}
return false ;
}
template < class I , unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void convert_to_signed_int ( I * res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
static constexpr int digits = std : : numeric_limits < I > : : is_specialized ? std : : numeric_limits < I > : : digits : sizeof ( I ) * CHAR_BIT - 1 ;
static constexpr I max_val = std : : numeric_limits < I > : : is_specialized ? ( std : : numeric_limits < I > : : max ) ( ) : ( ( ( I ( 1 ) < < ( sizeof ( I ) * CHAR_BIT - 2 ) ) - 1 ) < < 1 ) + 1 ;
static constexpr I min_val = std : : numeric_limits < I > : : is_specialized ? ( std : : numeric_limits < I > : : min ) ( ) : - max_val - 1 ;
switch ( arg . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero :
* res = 0 ;
return ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
BOOST_MP_THROW_EXCEPTION ( std : : runtime_error ( " Could not convert NaN to integer. " ) ) ;
return ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity :
* res = max_val ;
if ( arg . sign ( ) )
* res = - * res ;
return ;
default :
break ;
}
using shift_type = typename std : : conditional < sizeof ( typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type ) < sizeof ( int ) , int , typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type > : : type ;
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : rep_type man ( arg . bits ( ) ) ;
shift_type shift = ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - 1 - arg . exponent ( ) ;
if ( shift > ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - 1 )
{
* res = 0 ;
return ;
}
if ( arg . sign ( ) & & ( arg . compare ( min_val ) < = 0 ) )
{
* res = min_val ;
return ;
}
else if ( ! arg . sign ( ) & & ( arg . compare ( max_val ) > = 0 ) )
{
* res = max_val ;
return ;
}
if ( shift < 0 )
{
if ( static_cast < int > ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) - static_cast < int > ( shift ) < = digits )
{
// We have more bits in long_long_type than the float, so it's OK to left shift:
eval_convert_to ( res , man ) ;
* res < < = - shift ;
}
else
{
* res = ( std : : numeric_limits < I > : : max ) ( ) ;
return ;
}
}
else
{
eval_right_shift ( man , static_cast < double_limb_type > ( shift ) ) ;
eval_convert_to ( res , man ) ;
}
if ( arg . sign ( ) )
{
* res = - * res ;
}
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_convert_to ( long long * res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
convert_to_signed_int ( res , arg ) ;
}
# ifdef BOOST_HAS_INT128
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_convert_to ( int128_type * res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
convert_to_signed_int ( res , arg ) ;
}
# endif
template < class I , unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void convert_to_unsigned_int ( I * res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
static constexpr int digits = std : : numeric_limits < I > : : is_specialized ? std : : numeric_limits < I > : : digits : sizeof ( I ) * CHAR_BIT ;
static constexpr I max_val = std : : numeric_limits < I > : : is_specialized ? ( std : : numeric_limits < I > : : max ) ( ) : ~ static_cast < I > ( 0 ) ;
switch ( arg . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero :
* res = 0 ;
return ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
BOOST_MP_THROW_EXCEPTION ( std : : runtime_error ( " Could not convert NaN to integer. " ) ) ;
2025-10-03 13:44:19 +03:00
# if defined(BOOST_NO_EXCEPTIONS)
* res = max_val ;
return ;
# endif
2025-07-06 20:43:53 +03:00
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity :
* res = max_val ;
return ;
default :
break ;
}
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : rep_type man ( arg . bits ( ) ) ;
using shift_type = typename std : : conditional < sizeof ( typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type ) < sizeof ( int ) , int , typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type > : : type ;
2025-10-03 13:44:19 +03:00
const shift_type shift = ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - 1 - arg . exponent ( ) ;
if ( arg . sign ( ) )
{
using si_type = typename boost : : multiprecision : : detail : : make_signed < I > : : type ;
si_type val ;
convert_to_signed_int ( & val , arg ) ;
* res = static_cast < I > ( val ) ;
return ;
}
else if ( shift > ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - 1 )
2025-07-06 20:43:53 +03:00
{
* res = 0 ;
return ;
}
2025-10-03 13:44:19 +03:00
else if ( arg . compare ( max_val ) > = 0 )
{
* res = max_val ;
return ;
}
2025-07-06 20:43:53 +03:00
else if ( shift < 0 )
{
2025-10-03 13:44:19 +03:00
if ( ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - shift < = ( shift_type ) digits )
2025-07-06 20:43:53 +03:00
{
// We have more bits in ulong_long_type than the float, so it's OK to left shift:
eval_convert_to ( res , man ) ;
* res < < = - shift ;
return ;
}
* res = max_val ;
return ;
}
2025-10-03 13:44:19 +03:00
eval_right_shift ( man , static_cast < unsigned > ( shift ) ) ;
2025-07-06 20:43:53 +03:00
eval_convert_to ( res , man ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_convert_to ( unsigned long long * res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
convert_to_unsigned_int ( res , arg ) ;
}
# ifdef BOOST_HAS_INT128
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_convert_to ( uint128_type * res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
convert_to_unsigned_int ( res , arg ) ;
}
# endif
template < class Float , unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline typename std : : enable_if < std : : is_floating_point < Float > : : value > : : type eval_convert_to ( Float * res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & original_arg )
{
using conv_type = cpp_bin_float < std : : numeric_limits < Float > : : digits , digit_base_2 , void , Exponent , MinE , MaxE > ;
using common_exp_type = typename std : : common_type < typename conv_type : : exponent_type , int > : : type ;
static constexpr int float_digits = boost : : multiprecision : : detail : : is_float128 < Float > : : value ? 113 : std : : numeric_limits < Float > : : digits ;
BOOST_MP_FLOAT128_USING using std : : ldexp ;
//
// Special cases first:
//
switch ( original_arg . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero :
* res = 0 ;
if ( original_arg . sign ( ) )
* res = - * res ;
return ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
BOOST_IF_CONSTEXPR ( boost : : multiprecision : : detail : : is_float128 < Float > : : value )
{
* res = static_cast < Float > ( std : : numeric_limits < double > : : quiet_NaN ( ) ) ;
}
else
{
* res = std : : numeric_limits < Float > : : quiet_NaN ( ) ;
}
return ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity :
BOOST_IF_CONSTEXPR ( boost : : multiprecision : : detail : : is_float128 < Float > : : value )
{
* res = static_cast < Float > ( ( std : : numeric_limits < double > : : infinity ) ( ) ) ;
}
else
{
* res = ( std : : numeric_limits < Float > : : infinity ) ( ) ;
}
if ( original_arg . sign ( ) )
* res = - * res ;
return ;
default :
break ;
}
//
// Check for super large exponent that must be converted to infinity:
//
if ( original_arg . exponent ( ) > ( boost : : multiprecision : : detail : : is_float128 < Float > : : value ? 16384 : std : : numeric_limits < Float > : : max_exponent ) )
{
BOOST_IF_CONSTEXPR ( boost : : multiprecision : : detail : : is_float128 < Float > : : value )
{
* res = static_cast < Float > ( std : : numeric_limits < double > : : infinity ( ) ) ;
}
else
{
* res = std : : numeric_limits < Float > : : has_infinity ? std : : numeric_limits < Float > : : infinity ( ) : ( std : : numeric_limits < Float > : : max ) ( ) ;
}
if ( original_arg . sign ( ) )
* res = - * res ;
return ;
}
//
// Figure out how many digits we will have in our result,
// allowing for a possibly denormalized result:
//
common_exp_type digits_to_round_to = float_digits ;
if ( original_arg . exponent ( ) < std : : numeric_limits < Float > : : min_exponent - 1 )
{
common_exp_type diff = original_arg . exponent ( ) ;
diff - = boost : : multiprecision : : detail : : is_float128 < Float > : : value ? - 16382 : std : : numeric_limits < Float > : : min_exponent - 1 ;
digits_to_round_to + = diff ;
}
if ( digits_to_round_to < 0 )
{
// Result must be zero:
* res = 0 ;
if ( original_arg . sign ( ) )
* res = - * res ;
return ;
}
//
// Perform rounding first, then afterwards extract the digits:
//
cpp_bin_float < static_cast < unsigned > ( float_digits ) , digit_base_2 , Allocator , Exponent , 0 , 0 > arg ;
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : rep_type bits ( original_arg . bits ( ) ) ;
arg . exponent ( ) = original_arg . exponent ( ) ;
copy_and_round ( arg , bits , ( std : : ptrdiff_t ) digits_to_round_to ) ;
common_exp_type e = arg . exponent ( ) ;
e - = static_cast < common_exp_type > ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) - 1 ;
constexpr std : : size_t limbs_needed = static_cast < std : : size_t > ( float_digits ) / ( sizeof ( * arg . bits ( ) . limbs ( ) ) * CHAR_BIT ) + ( static_cast < std : : size_t > ( float_digits ) % ( sizeof ( * arg . bits ( ) . limbs ( ) ) * CHAR_BIT ) ? 1 : 0 ) ;
std : : size_t first_limb_needed = arg . bits ( ) . size ( ) - limbs_needed ;
* res = 0 ;
e + = static_cast < common_exp_type > ( first_limb_needed * sizeof ( * arg . bits ( ) . limbs ( ) ) * CHAR_BIT ) ;
while ( first_limb_needed < arg . bits ( ) . size ( ) )
{
* res + = ldexp ( static_cast < Float > ( arg . bits ( ) . limbs ( ) [ first_limb_needed ] ) , static_cast < int > ( e ) ) ;
+ + first_limb_needed ;
e + = static_cast < common_exp_type > ( sizeof ( * arg . bits ( ) . limbs ( ) ) * CHAR_BIT ) ;
}
if ( original_arg . sign ( ) )
* res = - * res ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_frexp ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg , Exponent * e )
{
switch ( arg . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero :
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity :
* e = 0 ;
res = arg ;
return ;
default :
break ;
}
res = arg ;
* e = arg . exponent ( ) + 1 ;
res . exponent ( ) = - 1 ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class I >
inline void eval_frexp ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg , I * pe )
{
Exponent e ;
eval_frexp ( res , arg , & e ) ;
if ( ( e > ( std : : numeric_limits < I > : : max ) ( ) ) | | ( e < ( std : : numeric_limits < I > : : min ) ( ) ) )
{
BOOST_MP_THROW_EXCEPTION ( std : : runtime_error ( " Exponent was outside of the range of the argument type to frexp. " ) ) ;
}
* pe = static_cast < I > ( e ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_ldexp ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg , Exponent e )
{
switch ( arg . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero :
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity :
res = arg ;
return ;
default :
break ;
}
if ( ( e > 0 ) & & ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent - e < arg . exponent ( ) ) )
{
// Overflow:
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : infinity ( ) . backend ( ) ;
res . sign ( ) = arg . sign ( ) ;
}
else if ( ( e < 0 ) & & ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : min_exponent - e > arg . exponent ( ) ) )
{
// Underflow:
res = limb_type ( 0 ) ;
}
else
{
res = arg ;
res . exponent ( ) + = e ;
}
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class I >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_unsigned < I > : : value > : : type eval_ldexp ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg , I e )
{
using si_type = typename boost : : multiprecision : : detail : : make_signed < I > : : type ;
if ( e > static_cast < I > ( ( std : : numeric_limits < si_type > : : max ) ( ) ) )
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : infinity ( ) . backend ( ) ;
else
eval_ldexp ( res , arg , static_cast < si_type > ( e ) ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class I >
inline typename std : : enable_if < boost : : multiprecision : : detail : : is_signed < I > : : value & & boost : : multiprecision : : detail : : is_integral < I > : : value > : : type eval_ldexp ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg , I e )
{
if ( ( e > ( std : : numeric_limits < Exponent > : : max ) ( ) ) | | ( e < ( std : : numeric_limits < Exponent > : : min ) ( ) ) )
{
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : infinity ( ) . backend ( ) ;
if ( e < 0 )
res . negate ( ) ;
}
else
eval_ldexp ( res , arg , static_cast < Exponent > ( e ) ) ;
}
/*
* Sign manipulation
*/
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
unsigned Digits2 , digit_base_type DigitBase2 , class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 >
inline void eval_abs ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits2 , DigitBase2 , Allocator2 , Exponent2 , MinE2 , MaxE2 > & arg )
{
res = arg ;
res . sign ( ) = false ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_abs ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
res = arg ;
res . sign ( ) = false ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE ,
unsigned Digits2 , digit_base_type DigitBase2 , class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 >
inline void eval_fabs ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits2 , DigitBase2 , Allocator2 , Exponent2 , MinE2 , MaxE2 > & arg )
{
res = arg ;
res . sign ( ) = false ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_fabs ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
res = arg ;
res . sign ( ) = false ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline int eval_fpclassify ( const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
switch ( arg . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero :
return FP_ZERO ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity :
return FP_INFINITE ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
return FP_NAN ;
default :
break ;
}
return FP_NORMAL ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_sqrt ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
using default_ops : : eval_bit_test ;
using default_ops : : eval_increment ;
using default_ops : : eval_integer_sqrt ;
switch ( arg . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
errno = EDOM ;
BOOST_MP_FALLTHROUGH ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero :
res = arg ;
return ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity :
if ( arg . sign ( ) )
{
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
errno = EDOM ;
}
else
res = arg ;
return ;
default :
break ;
}
if ( arg . sign ( ) )
{
res = std : : numeric_limits < number < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > > : : quiet_NaN ( ) . backend ( ) ;
errno = EDOM ;
return ;
}
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : double_rep_type t ( arg . bits ( ) ) , r , s ;
eval_left_shift ( t , arg . exponent ( ) & 1 ? cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - 1 ) ;
eval_integer_sqrt ( s , r , t ) ;
if ( ! eval_bit_test ( s , cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) )
{
// We have exactly the right number of cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in the result, round as required:
if ( s . compare ( r ) < 0 )
{
eval_increment ( s ) ;
}
}
typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type ae = arg . exponent ( ) ;
res . exponent ( ) = ae / 2 ;
res . sign ( ) = false ;
if ( ( ae & 1 ) & & ( ae < 0 ) )
- - res . exponent ( ) ;
copy_and_round ( res , s ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_floor ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
using default_ops : : eval_increment ;
switch ( arg . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
errno = EDOM ;
BOOST_MP_FALLTHROUGH ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero :
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity :
res = arg ;
return ;
default :
break ;
}
using shift_type = typename std : : conditional < sizeof ( typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type ) < sizeof ( int ) , int , typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type > : : type ;
shift_type shift =
( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - arg . exponent ( ) - 1 ;
if ( ( arg . exponent ( ) > ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent ) | | ( shift < = 0 ) )
{
// Either arg is already an integer, or a special value:
res = arg ;
return ;
}
if ( shift > = ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count )
{
res = static_cast < signed_limb_type > ( arg . sign ( ) ? - 1 : 0 ) ;
return ;
}
bool fractional = ( shift_type ) eval_lsb ( arg . bits ( ) ) < shift ;
res = arg ;
eval_right_shift ( res . bits ( ) , static_cast < double_limb_type > ( shift ) ) ;
if ( fractional & & res . sign ( ) )
{
eval_increment ( res . bits ( ) ) ;
const std : : ptrdiff_t shift_check =
static_cast < std : : ptrdiff_t > ( static_cast < std : : ptrdiff_t > ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) - 1 - static_cast < std : : ptrdiff_t > ( shift ) ) ;
if ( static_cast < std : : ptrdiff_t > ( eval_msb ( res . bits ( ) ) ) ! = shift_check )
{
// Must have extended result by one bit in the increment:
- - shift ;
+ + res . exponent ( ) ;
}
}
eval_left_shift ( res . bits ( ) , static_cast < double_limb_type > ( shift ) ) ;
}
template < unsigned Digits , digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE >
inline void eval_ceil ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & res , const cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > & arg )
{
using default_ops : : eval_increment ;
switch ( arg . exponent ( ) )
{
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity :
errno = EDOM ;
BOOST_MP_FALLTHROUGH ;
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_zero :
case cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan :
res = arg ;
return ;
default :
break ;
}
using shift_type = typename std : : conditional < sizeof ( typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type ) < sizeof ( int ) , int , typename cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type > : : type ;
shift_type shift = ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - arg . exponent ( ) - 1 ;
if ( ( arg . exponent ( ) > ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent ) | | ( shift < = 0 ) )
{
// Either arg is already an integer, or a special value:
res = arg ;
return ;
}
if ( shift > = ( shift_type ) cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count )
{
bool s = arg . sign ( ) ; // takes care of signed zeros
res = static_cast < signed_limb_type > ( arg . sign ( ) ? 0 : 1 ) ;
res . sign ( ) = s ;
return ;
}
bool fractional = ( shift_type ) eval_lsb ( arg . bits ( ) ) < shift ;
res = arg ;
2025-10-03 13:44:19 +03:00
eval_right_shift ( res . bits ( ) , static_cast < unsigned > ( shift ) ) ;
2025-07-06 20:43:53 +03:00
if ( fractional & & ! res . sign ( ) )
{
eval_increment ( res . bits ( ) ) ;
2025-10-03 13:44:19 +03:00
if ( ( std : : ptrdiff_t ) eval_msb ( res . bits ( ) ) ! = ( std : : ptrdiff_t ) ( static_cast < shift_type > ( cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ) - 1 - shift ) )
2025-07-06 20:43:53 +03:00
{
// Must have extended result by one bit in the increment:
- - shift ;
+ + res . exponent ( ) ;
}
}
2025-10-03 13:44:19 +03:00
eval_left_shift ( res . bits ( ) , static_cast < unsigned > ( shift ) ) ;
2025-07-06 20:43:53 +03:00
}
template < unsigned D1 , backends : : digit_base_type B1 , class A1 , class E1 , E1 M1 , E1 M2 >
int eval_signbit ( const cpp_bin_float < D1 , B1 , A1 , E1 , M1 , M2 > & val )
{
return val . sign ( ) ;
}
template < unsigned D1 , backends : : digit_base_type B1 , class A1 , class E1 , E1 M1 , E1 M2 >
inline std : : size_t hash_value ( const cpp_bin_float < D1 , B1 , A1 , E1 , M1 , M2 > & val )
{
std : : size_t result = hash_value ( val . bits ( ) ) ;
boost : : multiprecision : : detail : : hash_combine ( result , val . exponent ( ) , val . sign ( ) ) ;
return result ;
}
} // namespace backends
namespace detail {
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinExponent , Exponent MaxExponent >
struct transcendental_reduction_type < boost : : multiprecision : : backends : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinExponent , MaxExponent > >
{
//
// The type used for trigonometric reduction needs 3 times the precision of the base type.
// This is double the precision of the original type, plus the largest exponent supported.
// As a practical measure the largest argument supported is 1/eps, as supporting larger
// arguments requires the division of argument by PI/2 to also be done at higher precision,
// otherwise the result (an integer) can not be represented exactly.
//
// See ARGUMENT REDUCTION FOR HUGE ARGUMENTS. K C Ng.
//
using type = boost : : multiprecision : : backends : : cpp_bin_float <
boost : : multiprecision : : backends : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinExponent , MaxExponent > : : bit_count * 3 ,
boost : : multiprecision : : backends : : digit_base_2 ,
Allocator , Exponent , MinExponent , MaxExponent > ;
} ;
# ifdef BOOST_HAS_INT128
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinExponent , Exponent MaxExponent >
struct is_convertible_arithmetic < int128_type , boost : : multiprecision : : backends : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinExponent , MaxExponent > > : public std : : true_type
{ } ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinExponent , Exponent MaxExponent >
struct is_convertible_arithmetic < uint128_type , boost : : multiprecision : : backends : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinExponent , MaxExponent > > : public std : : true_type
{ } ;
# endif
} // namespace detail
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Exponent , Exponent MinE , Exponent MaxE , class Allocator , boost : : multiprecision : : expression_template_option ExpressionTemplates >
inline boost : : multiprecision : : number < boost : : multiprecision : : backends : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates >
copysign BOOST_PREVENT_MACRO_SUBSTITUTION (
const boost : : multiprecision : : number < boost : : multiprecision : : backends : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > & a ,
const boost : : multiprecision : : number < boost : : multiprecision : : backends : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > & b )
{
boost : : multiprecision : : number < boost : : multiprecision : : backends : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > res ( a ) ;
res . backend ( ) . sign ( ) = b . backend ( ) . sign ( ) ;
return res ;
}
template < unsigned Digits , backends : : digit_base_type DigitBase , class Exponent , Exponent MinE , Exponent MaxE , class Allocator >
struct number_category < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > > : public std : : integral_constant < int , boost : : multiprecision : : number_kind_floating_point >
{ } ;
template < unsigned Digits , backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , class Allocator2 , class Exponent2 , Exponent MinE2 , Exponent MaxE2 >
struct is_equivalent_number_type < cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , cpp_bin_float < Digits , DigitBase , Allocator2 , Exponent2 , MinE2 , MaxE2 > >
: public std : : integral_constant < bool , true > { } ;
} // namespace multiprecision
namespace math {
using boost : : multiprecision : : copysign ;
using boost : : multiprecision : : signbit ;
} // namespace math
} // namespace boost
# include <boost/multiprecision/cpp_bin_float/io.hpp>
# include <boost/multiprecision/cpp_bin_float/transcendental.hpp>
namespace std {
//
// numeric_limits [partial] specializations for the types declared in this header:
//
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
class numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > >
{
using number_type = boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > ;
private :
//
// Functions to calculate cached values stored in static values:
//
static number_type get_min ( )
{
using ui_type = typename std : : tuple_element < 0 , typename number_type : : backend_type : : unsigned_types > : : type ;
number_type value ( ui_type ( 1u ) ) ;
value . backend ( ) . exponent ( ) = boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : min_exponent ;
return value ;
}
# ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4127) // conditional expression is constant
# endif
static number_type get_max ( )
{
number_type value ;
BOOST_IF_CONSTEXPR ( std : : is_void < Allocator > : : value )
eval_complement ( value . backend ( ) . bits ( ) , value . backend ( ) . bits ( ) ) ;
else
{
// We jump through hoops here using the backend type directly just to keep VC12 happy
// (ie compiler workaround, for very strange compiler bug):
using boost : : multiprecision : : default_ops : : eval_add ;
using boost : : multiprecision : : default_ops : : eval_decrement ;
using boost : : multiprecision : : default_ops : : eval_left_shift ;
using int_backend_type = typename number_type : : backend_type : : rep_type ;
using ui_type = typename std : : tuple_element < 0 , typename int_backend_type : : unsigned_types > : : type ;
int_backend_type i ;
i = ui_type ( 1u ) ;
eval_left_shift ( i , boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count - 1 ) ;
int_backend_type j ( i ) ;
eval_decrement ( i ) ;
eval_add ( j , i ) ;
value . backend ( ) . bits ( ) = j ;
}
value . backend ( ) . exponent ( ) = boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent ;
return value ;
}
# ifdef BOOST_MSVC
# pragma warning(pop)
# endif
static number_type get_epsilon ( )
{
using ui_type = typename std : : tuple_element < 0 , typename number_type : : backend_type : : unsigned_types > : : type ;
number_type value ( ui_type ( 1u ) ) ;
return ldexp ( value , 1 - static_cast < int > ( digits ) ) ;
}
// What value should this be????
static number_type get_round_error ( )
{
// returns 0.5
return ldexp ( number_type ( 1u ) , - 1 ) ;
}
static number_type get_infinity ( )
{
number_type value ;
value . backend ( ) . exponent ( ) = boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_infinity ;
return value ;
}
static number_type get_quiet_NaN ( )
{
number_type value ;
value . backend ( ) . exponent ( ) = boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_nan ;
return value ;
}
public :
static constexpr bool is_specialized = true ;
static number_type ( min ) ( )
{
// C++11 thread safe static initialization:
static number_type value = get_min ( ) ;
return value ;
}
static number_type ( max ) ( )
{
// C++11 thread safe static initialization:
static number_type value = get_max ( ) ;
return value ;
}
static constexpr number_type lowest ( )
{
return - ( max ) ( ) ;
}
static constexpr int digits = boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : bit_count ;
static constexpr int digits10 = boost : : multiprecision : : detail : : calc_digits10 < static_cast < unsigned > ( digits ) > : : value ;
// Is this really correct???
static constexpr int max_digits10 = boost : : multiprecision : : detail : : calc_max_digits10 < static_cast < unsigned > ( digits ) > : : value ;
static constexpr bool is_signed = true ;
static constexpr bool is_integer = false ;
static constexpr bool is_exact = false ;
static constexpr int radix = 2 ;
static number_type epsilon ( )
{
// C++11 thread safe static initialization:
static number_type value = get_epsilon ( ) ;
return value ;
}
// What value should this be????
static number_type round_error ( )
{
// returns 0.5
// C++11 thread safe static initialization:
static number_type value = get_round_error ( ) ;
return value ;
}
static constexpr typename boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type min_exponent = boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : min_exponent ;
static constexpr typename boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type min_exponent10 = ( min_exponent / 1000 ) * 301L ;
static constexpr typename boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type max_exponent = boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : max_exponent ;
static constexpr typename boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type max_exponent10 = ( max_exponent / 1000 ) * 301L ;
static constexpr bool has_infinity = true ;
static constexpr bool has_quiet_NaN = true ;
static constexpr bool has_signaling_NaN = false ;
# ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4996)
# endif
static constexpr float_denorm_style has_denorm = denorm_absent ;
# ifdef _MSC_VER
# pragma warning(pop)
# endif
static constexpr bool has_denorm_loss = false ;
static number_type infinity ( )
{
// C++11 thread safe static initialization:
static number_type value = get_infinity ( ) ;
return value ;
}
static number_type quiet_NaN ( )
{
// C++11 thread safe static initialization:
static number_type value = get_quiet_NaN ( ) ;
return value ;
}
static constexpr number_type signaling_NaN ( )
{
return number_type ( 0 ) ;
}
static constexpr number_type denorm_min ( ) { return get_min ( ) ; }
static constexpr bool is_iec559 = false ;
static constexpr bool is_bounded = true ;
static constexpr bool is_modulo = false ;
static constexpr bool traps = true ;
static constexpr bool tinyness_before = false ;
static constexpr float_round_style round_style = round_to_nearest ;
} ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr int numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : digits ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr int numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : digits10 ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr int numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : max_digits10 ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : is_signed ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : is_integer ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : is_exact ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr int numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : radix ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr typename boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : min_exponent ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr typename boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : min_exponent10 ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr typename boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : max_exponent ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr typename boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > : : exponent_type numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : max_exponent10 ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : has_infinity ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : has_quiet_NaN ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : has_signaling_NaN ;
# ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4996)
# endif
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr float_denorm_style numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : has_denorm ;
# ifdef _MSC_VER
# pragma warning(pop)
# endif
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : has_denorm_loss ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : is_iec559 ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : is_bounded ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : is_modulo ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : traps ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr bool numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : tinyness_before ;
template < unsigned Digits , boost : : multiprecision : : backends : : digit_base_type DigitBase , class Allocator , class Exponent , Exponent MinE , Exponent MaxE , boost : : multiprecision : : expression_template_option ExpressionTemplates >
constexpr float_round_style numeric_limits < boost : : multiprecision : : number < boost : : multiprecision : : cpp_bin_float < Digits , DigitBase , Allocator , Exponent , MinE , MaxE > , ExpressionTemplates > > : : round_style ;
} // namespace std
# endif