| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048 |
- ///////////////////////////////////////////////////////////////
- // Copyright 2013 John Maddock. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
- #ifndef BOOST_MATH_CPP_BIN_FLOAT_HPP
- #define BOOST_MATH_CPP_BIN_FLOAT_HPP
- #include <boost/multiprecision/cpp_int.hpp>
- #include <boost/multiprecision/integer.hpp>
- #include <boost/math/special_functions/trunc.hpp>
- #include <boost/multiprecision/detail/float_string_cvt.hpp>
- //
- // Some includes we need from Boost.Math, since we rely on that library to provide these functions:
- //
- #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>
- #ifdef BOOST_HAS_FLOAT128
- #include <quadmath.h>
- #endif
- namespace boost{ namespace multiprecision{ namespace backends{
- enum digit_base_type
- {
- digit_base_2 = 2,
- digit_base_10 = 10
- };
- #ifdef BOOST_MSVC
- #pragma warning(push)
- #pragma warning(disable:4522 6326) // multiple assignment operators specified, comparison of two constants
- #endif
- namespace detail{
- template <class U>
- inline typename enable_if_c<is_unsigned<U>::value, bool>::type is_negative(U) { return false; }
- template <class S>
- inline typename disable_if_c<is_unsigned<S>::value, bool>::type is_negative(S s) { return s < 0; }
- template <class Float, int, bool = number_category<Float>::value == number_kind_floating_point>
- struct is_cpp_bin_float_implicitly_constructible_from_type
- {
- static const bool value = false;
- };
- template <class Float, int bit_count>
- struct is_cpp_bin_float_implicitly_constructible_from_type<Float, bit_count, true>
- {
- static const bool value = (std::numeric_limits<Float>::digits <= (int)bit_count)
- && (std::numeric_limits<Float>::radix == 2)
- && std::numeric_limits<Float>::is_specialized
- #ifdef BOOST_HAS_FLOAT128
- && !boost::is_same<Float, __float128>::value
- #endif
- && (is_floating_point<Float>::value || is_number<Float>::value)
- ;
- };
- template <class Float, int, bool = number_category<Float>::value == number_kind_floating_point>
- struct is_cpp_bin_float_explicitly_constructible_from_type
- {
- static const bool value = false;
- };
- template <class Float, int bit_count>
- struct is_cpp_bin_float_explicitly_constructible_from_type<Float, bit_count, true>
- {
- static const bool value = (std::numeric_limits<Float>::digits > (int)bit_count)
- && (std::numeric_limits<Float>::radix == 2)
- && std::numeric_limits<Float>::is_specialized
- #ifdef BOOST_HAS_FLOAT128
- && !boost::is_same<Float, __float128>::value
- #endif
- ;
- };
- }
- template <unsigned Digits, digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0>
- class cpp_bin_float
- {
- public:
- static const unsigned bit_count = DigitBase == digit_base_2 ? Digits : (Digits * 1000uL) / 301uL + (((Digits * 1000uL) % 301) ? 2u : 1u);
- typedef cpp_int_backend<is_void<Allocator>::value ? bit_count : 0, bit_count, is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> rep_type;
- typedef cpp_int_backend<is_void<Allocator>::value ? 2 * bit_count : 0, 2 * bit_count, is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> double_rep_type;
- typedef typename rep_type::signed_types signed_types;
- typedef typename rep_type::unsigned_types unsigned_types;
- typedef boost::mpl::list<float, double, long double> float_types;
- typedef Exponent exponent_type;
- static const exponent_type max_exponent_limit = boost::integer_traits<exponent_type>::const_max - 2 * static_cast<exponent_type>(bit_count);
- static const exponent_type min_exponent_limit = boost::integer_traits<exponent_type>::const_min + 2 * static_cast<exponent_type>(bit_count);
- BOOST_STATIC_ASSERT_MSG(MinExponent >= min_exponent_limit, "Template parameter MinExponent is too negative for our internal logic to function correctly, sorry!");
- BOOST_STATIC_ASSERT_MSG(MaxExponent <= max_exponent_limit, "Template parameter MaxExponent is too large for our internal logic to function correctly, sorry!");
- BOOST_STATIC_ASSERT_MSG(MinExponent <= 0, "Template parameter MinExponent can not be positive!");
- BOOST_STATIC_ASSERT_MSG(MaxExponent >= 0, "Template parameter MaxExponent can not be negative!");
- static const exponent_type max_exponent = MaxExponent == 0 ? max_exponent_limit : MaxExponent;
- static const exponent_type min_exponent = MinExponent == 0 ? min_exponent_limit : MinExponent;
- static const exponent_type exponent_zero = max_exponent + 1;
- static const exponent_type exponent_infinity = max_exponent + 2;
- static const exponent_type exponent_nan = max_exponent + 3;
- private:
- rep_type m_data;
- exponent_type m_exponent;
- bool m_sign;
- public:
- cpp_bin_float() BOOST_MP_NOEXCEPT_IF(noexcept(rep_type())) : m_data(), m_exponent(exponent_zero), m_sign(false) {}
- cpp_bin_float(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(rep_type(std::declval<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 boost::enable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0)
- {
- *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 boost::disable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0)
- : m_exponent(o.exponent()), m_sign(o.sign())
- {
- *this = o;
- }
- template <class Float>
- cpp_bin_float(const Float& f,
- typename boost::enable_if_c<detail::is_cpp_bin_float_implicitly_constructible_from_type<Float, bit_count>::value>::type const* = 0)
- : m_data(), m_exponent(0), m_sign(false)
- {
- this->assign_float(f);
- }
- template <class Float>
- explicit cpp_bin_float(const Float& f,
- typename boost::enable_if_c<detail::is_cpp_bin_float_explicitly_constructible_from_type<Float, bit_count>::value>::type const* = 0)
- : m_data(), m_exponent(0), m_sign(false)
- {
- this->assign_float(f);
- }
- #ifdef BOOST_HAS_FLOAT128
- template <class Float>
- cpp_bin_float(const Float& f,
- typename boost::enable_if_c<
- boost::is_same<Float, __float128>::value
- && ((int)bit_count >= 113)
- >::type const* = 0)
- : m_data(), m_exponent(0), m_sign(false)
- {
- this->assign_float(f);
- }
- template <class Float>
- explicit cpp_bin_float(const Float& f,
- typename boost::enable_if_c<
- boost::is_same<Float, __float128>::value
- && ((int)bit_count < 113)
- >::type const* = 0)
- : m_data(), m_exponent(0), m_sign(false)
- {
- this->assign_float(f);
- }
- #endif
- cpp_bin_float& operator=(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<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 <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_HAS_FLOAT128
- template <class Float>
- typename boost::enable_if_c<
- (number_category<Float>::value == number_kind_floating_point)
- //&& (std::numeric_limits<Float>::digits <= (int)bit_count)
- && ((std::numeric_limits<Float>::radix == 2) || (boost::is_same<Float, __float128>::value)), cpp_bin_float&>::type
- operator=(const Float& f)
- #else
- template <class Float>
- typename boost::enable_if_c<
- (number_category<Float>::value == number_kind_floating_point)
- //&& (std::numeric_limits<Float>::digits <= (int)bit_count)
- && (std::numeric_limits<Float>::radix == 2), cpp_bin_float&>::type
- operator=(const Float& f)
- #endif
- {
- return assign_float(f);
- }
- #ifdef BOOST_HAS_FLOAT128
- template <class Float>
- typename boost::enable_if_c<boost::is_same<Float, __float128>::value, cpp_bin_float& >::type assign_float(Float f)
- {
- using default_ops::eval_add;
- typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
- if(f == 0)
- {
- m_data = limb_type(0);
- m_sign = (signbitq(f) > 0);
- m_exponent = exponent_zero;
- return *this;
- }
- else if(isnanq(f))
- {
- m_data = limb_type(0);
- m_sign = false;
- m_exponent = exponent_nan;
- return *this;
- }
- else if(isinfq(f))
- {
- m_data = limb_type(0);
- m_sign = (f < 0);
- m_exponent = exponent_infinity;
- return *this;
- }
- if(f < 0)
- {
- *this = -f;
- this->negate();
- return *this;
- }
- typedef typename mpl::front<unsigned_types>::type ui_type;
- m_data = static_cast<ui_type>(0u);
- m_sign = false;
- m_exponent = 0;
- static const int bits = sizeof(int) * CHAR_BIT - 1;
- int e;
- f = frexpq(f, &e);
- while(f)
- {
- f = ldexpq(f, bits);
- e -= bits;
- int ipart = (int)truncq(f);
- f -= ipart;
- m_exponent += bits;
- cpp_bin_float t;
- t = static_cast<bf_int_type>(ipart);
- eval_add(*this, t);
- }
- m_exponent += static_cast<Exponent>(e);
- return *this;
- }
- #endif
- #ifdef BOOST_HAS_FLOAT128
- template <class Float>
- typename boost::enable_if_c<is_floating_point<Float>::value && !is_same<Float, __float128>::value, cpp_bin_float&>::type assign_float(Float f)
- #else
- template <class Float>
- typename boost::enable_if_c<is_floating_point<Float>::value, cpp_bin_float&>::type assign_float(Float f)
- #endif
- {
- BOOST_MATH_STD_USING
- using default_ops::eval_add;
- typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
- switch((boost::math::fpclassify)(f))
- {
- case FP_ZERO:
- m_data = limb_type(0);
- m_sign = ((boost::math::signbit)(f) > 0);
- m_exponent = exponent_zero;
- return *this;
- case FP_NAN:
- m_data = limb_type(0);
- m_sign = false;
- m_exponent = exponent_nan;
- return *this;
- case FP_INFINITE:
- m_data = limb_type(0);
- m_sign = (f < 0);
- m_exponent = exponent_infinity;
- return *this;
- }
- if(f < 0)
- {
- *this = -f;
- this->negate();
- return *this;
- }
- typedef typename mpl::front<unsigned_types>::type ui_type;
- m_data = static_cast<ui_type>(0u);
- m_sign = false;
- m_exponent = 0;
- static const int bits = sizeof(int) * CHAR_BIT - 1;
- int e;
- f = frexp(f, &e);
- while(f)
- {
- f = ldexp(f, bits);
- e -= bits;
- #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
- int ipart = itrunc(f);
- #else
- int ipart = static_cast<int>(f);
- #endif
- 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);
- return *this;
- }
- template <class Float>
- typename boost::enable_if_c<
- (number_category<Float>::value == number_kind_floating_point)
- && !boost::is_floating_point<Float>::value
- && is_number<Float>::value,
- cpp_bin_float&>::type assign_float(Float f)
- {
- BOOST_MATH_STD_USING
- using default_ops::eval_add;
- using default_ops::eval_get_sign;
- using default_ops::eval_convert_to;
- using default_ops::eval_subtract;
- typedef typename boost::multiprecision::detail::canonical<int, Float>::type f_int_type;
- typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
- switch(eval_fpclassify(f))
- {
- case FP_ZERO:
- m_data = limb_type(0);
- m_sign = ((boost::math::signbit)(f) > 0);
- m_exponent = exponent_zero;
- return *this;
- case FP_NAN:
- m_data = limb_type(0);
- m_sign = false;
- m_exponent = exponent_nan;
- return *this;
- case FP_INFINITE:
- m_data = limb_type(0);
- m_sign = (f < 0);
- m_exponent = exponent_infinity;
- return *this;
- }
- if(eval_get_sign(f) < 0)
- {
- f.negate();
- *this = f;
- this->negate();
- return *this;
- }
- typedef typename mpl::front<unsigned_types>::type ui_type;
- m_data = static_cast<ui_type>(0u);
- m_sign = false;
- m_exponent = 0;
- static const int bits = sizeof(int) * CHAR_BIT - 1;
- int e;
- eval_frexp(f, f, &e);
- while(eval_get_sign(f) != 0)
- {
- eval_ldexp(f, f, bits);
- e -= bits;
- int ipart;
- eval_convert_to(&ipart, f);
- eval_subtract(f, static_cast<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 = ((boost::math::signbit)(f) > 0);
- }
- else if(eval_get_sign(m_data) == 0)
- {
- m_exponent = exponent_zero;
- m_sign = ((boost::math::signbit)(f) > 0);
- }
- return *this;
- }
- template <class I>
- typename boost::enable_if<is_integral<I>, 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
- {
- typedef typename make_unsigned<I>::type ui_type;
- ui_type fi = static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(i));
- typedef typename boost::multiprecision::detail::canonical<ui_type, rep_type>::type ar_type;
- m_data = static_cast<ar_type>(fi);
- unsigned shift = msb(fi);
- 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_ASSERT(eval_bit_test(m_data, bit_count-1));
- m_sign = detail::is_negative(i);
- }
- return *this;
- }
- cpp_bin_float& operator=(const char *s);
- void swap(cpp_bin_float &o) BOOST_NOEXCEPT
- {
- m_data.swap(o.m_data);
- std::swap(m_exponent, o.m_exponent);
- std::swap(m_sign, o.m_sign);
- }
- std::string str(std::streamsize dig, std::ios_base::fmtflags f) const;
- void negate()
- {
- if(m_exponent != exponent_nan)
- m_sign = !m_sign;
- }
- int compare(const cpp_bin_float &o) const BOOST_NOEXCEPT
- {
- if(m_sign != o.m_sign)
- return (m_exponent == exponent_zero) && (m_exponent == o.m_exponent) ? 0 : m_sign ? -1 : 1;
- int result;
- if(m_exponent == exponent_nan)
- return -1;
- else if(m_exponent != o.m_exponent)
- {
- if(m_exponent == exponent_zero)
- result = -1;
- else if(o.m_exponent == exponent_zero)
- result = 1;
- else
- 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 BOOST_NOEXCEPT
- {
- cpp_bin_float b;
- b = o;
- return compare(b);
- }
- rep_type& bits() { return m_data; }
- const rep_type& bits()const { return m_data; }
- exponent_type& exponent() { return m_exponent; }
- const exponent_type& exponent()const { return m_exponent; }
- bool& sign() { return m_sign; }
- const bool& sign()const { return m_sign; }
- void check_invariants()
- {
- using default_ops::eval_bit_test;
- using default_ops::eval_is_zero;
- if((m_exponent <= max_exponent) && (m_exponent >= min_exponent))
- {
- BOOST_ASSERT(eval_bit_test(m_data, bit_count - 1));
- }
- else
- {
- BOOST_ASSERT(m_exponent > max_exponent);
- BOOST_ASSERT(m_exponent <= exponent_nan);
- BOOST_ASSERT(eval_is_zero(m_data));
- }
- }
- template<class Archive>
- void serialize(Archive & ar, const unsigned int /*version*/)
- {
- ar & boost::serialization::make_nvp("data", m_data);
- ar & boost::serialization::make_nvp("exponent", m_exponent);
- ar & boost::serialization::make_nvp("sign", m_sign);
- }
- };
- #ifdef BOOST_MSVC
- #pragma warning(pop)
- #endif
- template <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, int 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_msb;
- using default_ops::eval_lsb;
- using default_ops::eval_left_shift;
- using default_ops::eval_bit_test;
- using default_ops::eval_right_shift;
- using default_ops::eval_increment;
- using default_ops::eval_get_sign;
- // cancellation may have resulted in arg being all zeros:
- if(eval_get_sign(arg) == 0)
- {
- res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
- res.sign() = false;
- res.bits() = static_cast<limb_type>(0u);
- return;
- }
- int msb = eval_msb(arg);
- if(static_cast<int>(bits_to_keep) > msb + 1)
- {
- // Must have had cancellation in subtraction,
- // or be converting from a narrower type, so shift left:
- res.bits() = arg;
- eval_left_shift(res.bits(), bits_to_keep - msb - 1);
- res.exponent() -= static_cast<Exponent>(bits_to_keep - msb - 1);
- }
- else if(static_cast<int>(bits_to_keep) < msb + 1)
- {
- // We have more bits_to_keep than we need, so round as required,
- // first get the rounding bit:
- bool roundup = eval_bit_test(arg, msb - bits_to_keep);
- // Then check for a tie:
- if(roundup && (msb - bits_to_keep == (int)eval_lsb(arg)))
- {
- // Ties round towards even:
- if(!eval_bit_test(arg, msb - bits_to_keep + 1))
- roundup = false;
- }
- // Shift off the bits_to_keep we don't need:
- eval_right_shift(arg, msb - bits_to_keep + 1);
- res.exponent() += static_cast<Exponent>(msb - bits_to_keep + 1);
- if(roundup)
- {
- eval_increment(arg);
- if(bits_to_keep)
- {
- if(eval_bit_test(arg, bits_to_keep))
- {
- // This happens very very rairly, all the bits left after
- // truncation must be 1's and we're rounding up an order of magnitude:
- eval_right_shift(arg, 1u);
- ++res.exponent();
- }
- }
- else
- {
- // We get here when bits_to_keep is zero but we're rounding up,
- // as a result we end up with a single digit that is a 1:
- ++bits_to_keep;
- }
- }
- if(bits_to_keep != cpp_bin_float<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, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - bits_to_keep);
- res.exponent() -= static_cast<Exponent>(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_ASSERT(((int)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>
- inline void do_eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
- {
- if(a.exponent() < b.exponent())
- {
- bool s = a.sign();
- do_eval_add(res, b, a);
- if(res.sign() != s)
- res.negate();
- return;
- }
- using default_ops::eval_add;
- using default_ops::eval_bit_test;
- typedef typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type exponent_type;
- typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
- // Special cases first:
- switch(a.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
- {
- bool s = a.sign();
- res = b;
- res.sign() = s;
- return;
- }
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::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.
- }
- switch(b.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
- res = a;
- return;
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- res = b;
- if(res.sign())
- res.negate();
- return; // result is infinite.
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- res = b;
- return; // result is a NaN.
- }
- BOOST_STATIC_ASSERT(boost::integer_traits<exponent_type>::const_max - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent);
- bool s = a.sign();
- dt = a.bits();
- if(a.exponent() > (int)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_ASSERT(e_diff >= 0);
- eval_left_shift(dt, e_diff);
- res.exponent() = a.exponent() - e_diff;
- eval_add(dt, b.bits());
- }
-
- copy_and_round(res, dt);
- res.check_invariants();
- if(res.sign() != s)
- res.negate();
- }
- template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
- inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
- {
- using default_ops::eval_subtract;
- using default_ops::eval_bit_test;
- using default_ops::eval_decrement;
- typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
-
- // Special cases first:
- switch(a.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
- if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
- res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
- else
- {
- bool s = a.sign();
- res = b;
- if(res.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero)
- res.sign() = false;
- else if(res.sign() == s)
- res.negate();
- }
- return;
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- if((b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan) || (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity))
- 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, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- res = a;
- return; // result is still a NaN.
- }
- switch(b.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
- res = a;
- return;
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
- res.sign() = !a.sign();
- res.bits() = static_cast<limb_type>(0u);
- return; // result is a NaN.
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- res = b;
- return; // result is still a NaN.
- }
- bool s = a.sign();
- if((a.exponent() > b.exponent()) || ((a.exponent() == b.exponent()) && a.bits().compare(b.bits()) >= 0))
- {
- dt = a.bits();
- if(a.exponent() <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent())
- {
- typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
- eval_left_shift(dt, e_diff);
- res.exponent() = a.exponent() - e_diff;
- eval_subtract(dt, b.bits());
- }
- else if(a.exponent() == (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent() + 1)
- {
- if(eval_lsb(b.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
- {
- eval_left_shift(dt, 1);
- eval_decrement(dt);
- res.exponent() = a.exponent() - 1;
- }
- else
- res.exponent() = a.exponent();
- }
- else
- res.exponent() = a.exponent();
- }
- else
- {
- dt = b.bits();
- if(b.exponent() <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + a.exponent())
- {
- typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
- eval_left_shift(dt, -e_diff);
- res.exponent() = b.exponent() + e_diff;
- eval_subtract(dt, a.bits());
- }
- else if(b.exponent() == (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + a.exponent() + 1)
- {
- if(eval_lsb(a.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
- {
- eval_left_shift(dt, 1);
- eval_decrement(dt);
- res.exponent() = b.exponent() - 1;
- }
- else
- res.exponent() = b.exponent();
- }
- else
- res.exponent() = b.exponent();
- s = !s;
- }
-
- copy_and_round(res, dt);
- if(res.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::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>
- inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &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>
- inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a)
- {
- return eval_add(res, res, a);
- }
- template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
- inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &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>
- inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a)
- {
- return eval_subtract(res, res, a);
- }
- template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
- inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
- {
- using default_ops::eval_bit_test;
- using default_ops::eval_multiply;
- // Special cases first:
- switch(a.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
- {
- if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
- res = b;
- else if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::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, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- switch(b.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::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, Allocator, Exponent, MinE, MaxE>::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, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- res = a;
- return;
- }
- if(b.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::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>
- inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a)
- {
- eval_multiply(res, res, a);
- }
- template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
- inline typename enable_if_c<is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const U &b)
- {
- using default_ops::eval_bit_test;
- using default_ops::eval_multiply;
- // Special cases first:
- switch(a.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
- {
- bool s = a.sign();
- res = a;
- res.sign() = s;
- return;
- }
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::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, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- res = a;
- return;
- }
- typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
- typedef typename boost::multiprecision::detail::canonical<U, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::type canon_ui_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() = a.sign();
- }
- template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
- inline typename enable_if_c<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 S>
- inline typename enable_if_c<is_signed<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const S &b)
- {
- typedef typename make_unsigned<S>::type ui_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 enable_if_c<is_signed<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>
- inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &v)
- {
- #ifdef BOOST_MSVC
- #pragma warning(push)
- #pragma warning(disable:6326) // comparison of two constants
- #endif
- using default_ops::eval_subtract;
- using default_ops::eval_qr;
- using default_ops::eval_bit_test;
- using default_ops::eval_get_sign;
- using default_ops::eval_increment;
- //
- // Special cases first:
- //
- switch(u.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
- {
- switch(v.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:
- res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
- return;
- }
- bool s = u.sign() != v.sign();
- res = u;
- res.sign() = s;
- return;
- }
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- {
- switch(v.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
- return;
- }
- bool s = u.sign() != v.sign();
- res = u;
- res.sign() = s;
- return;
- }
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
- return;
- }
- switch(v.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::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, Allocator, Exponent, MinE, MaxE>::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, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
- return;
- }
- // We can scale u and v so that both are integers, then perform integer
- // division to obtain quotient q and remainder r, such that:
- //
- // q * v + r = u
- //
- // and hense:
- //
- // q + r/v = u/v
- //
- // From this, assuming q has cpp_bin_float<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.
- //
- static const 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_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.
- //
- BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
- static const 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() -= 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>
- inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
- {
- eval_divide(res, res, arg);
- }
- template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
- inline typename enable_if_c<is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const U &v)
- {
- #ifdef BOOST_MSVC
- #pragma warning(push)
- #pragma warning(disable:6326) // comparison of two constants
- #endif
- using default_ops::eval_subtract;
- using default_ops::eval_qr;
- using default_ops::eval_bit_test;
- using default_ops::eval_get_sign;
- using default_ops::eval_increment;
- //
- // Special cases first:
- //
- switch(u.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::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, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- res = u;
- return;
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
- return;
- }
- 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:
- //
- int gb = 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, 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.
- //
- static const 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_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.
- //
- BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
- static const 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() -= 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 enable_if_c<is_unsigned<U>::value>::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 S>
- inline typename enable_if_c<is_signed<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const S &v)
- {
- typedef typename make_unsigned<S>::type ui_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 enable_if_c<is_signed<S>::value>::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 <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
- inline void eval_convert_to(boost::long_long_type *res, 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:
- *res = 0;
- return;
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- *res = (std::numeric_limits<boost::long_long_type>::max)();
- if(arg.sign())
- *res = -*res;
- return;
- }
- typedef typename mpl::if_c < 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;
- 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((std::numeric_limits<boost::long_long_type>::min)()) <= 0))
- {
- *res = (std::numeric_limits<boost::long_long_type>::min)();
- return;
- }
- else if(!arg.sign() && (arg.compare((std::numeric_limits<boost::long_long_type>::max)()) >= 0))
- {
- *res = (std::numeric_limits<boost::long_long_type>::max)();
- return;
- }
- if (shift < 0)
- {
- if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - shift <= std::numeric_limits<boost::long_long_type>::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<boost::long_long_type>::max)();
- return;
- }
- }
- else
- {
- eval_right_shift(man, 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(boost::ulong_long_type *res, 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:
- *res = 0;
- return;
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- *res = (std::numeric_limits<boost::ulong_long_type>::max)();
- return;
- }
- typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
- typedef typename mpl::if_c < 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_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;
- }
- else if(shift < 0)
- {
- if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - shift <= std::numeric_limits<boost::ulong_long_type>::digits)
- {
- // We have more bits in ulong_long_type than the float, so it's OK to left shift:
- eval_convert_to(res, man);
- *res <<= -shift;
- return;
- }
- *res = (std::numeric_limits<boost::ulong_long_type>::max)();
- return;
- }
- eval_right_shift(man, shift);
- eval_convert_to(res, man);
- }
- template <class Float, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
- inline typename boost::enable_if_c<boost::is_float<Float>::value>::type eval_convert_to(Float *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &original_arg)
- {
- typedef cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE> conv_type;
- typedef typename common_type<typename conv_type::exponent_type, int>::type common_exp_type;
- //
- // 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:
- *res = std::numeric_limits<Float>::quiet_NaN();
- return;
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- *res = (std::numeric_limits<Float>::infinity)();
- if(original_arg.sign())
- *res = -*res;
- return;
- }
- //
- // Check for super large exponent that must be converted to infinity:
- //
- if(original_arg.exponent() > std::numeric_limits<Float>::max_exponent)
- {
- *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 = std::numeric_limits<Float>::digits;
- if(original_arg.exponent() < std::numeric_limits<Float>::min_exponent - 1)
- {
- common_exp_type diff = original_arg.exponent();
- diff -= 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<std::numeric_limits<Float>::digits, digit_base_2, Allocator, Exponent, MinE, MaxE> 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, (int)digits_to_round_to);
- common_exp_type e = arg.exponent();
- e -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1;
- static const unsigned limbs_needed = std::numeric_limits<Float>::digits / (sizeof(*arg.bits().limbs()) * CHAR_BIT)
- + (std::numeric_limits<Float>::digits % (sizeof(*arg.bits().limbs()) * CHAR_BIT) ? 1 : 0);
- unsigned first_limb_needed = arg.bits().size() - limbs_needed;
- *res = 0;
- e += first_limb_needed * sizeof(*arg.bits().limbs()) * CHAR_BIT;
- while(first_limb_needed < arg.bits().size())
- {
- *res += std::ldexp(static_cast<Float>(arg.bits().limbs()[first_limb_needed]), static_cast<int>(e));
- ++first_limb_needed;
- e += 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;
- }
- 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_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;
- }
- 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 enable_if_c<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)
- {
- typedef typename make_signed<I>::type si_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 enable_if_c<is_signed<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>
- 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>
- 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;
- }
- 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_integer_sqrt;
- using default_ops::eval_bit_test;
- using default_ops::eval_increment;
- switch(arg.exponent())
- {
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- errno = EDOM;
- // 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;
- }
- 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;
- 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;
- // 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;
- }
- typedef typename mpl::if_c < 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_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(), shift);
- if(fractional && res.sign())
- {
- eval_increment(res.bits());
- if(eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
- {
- // Must have extended result by one bit in the increment:
- --shift;
- ++res.exponent();
- }
- }
- eval_left_shift(res.bits(), 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;
- // 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;
- }
- typedef typename mpl::if_c < 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_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;
- eval_right_shift(res.bits(), shift);
- if(fractional && !res.sign())
- {
- eval_increment(res.bits());
- if(eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
- {
- // Must have extended result by one bit in the increment:
- --shift;
- ++res.exponent();
- }
- }
- eval_left_shift(res.bits(), shift);
- }
- 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::hash_combine(result, val.exponent());
- boost::hash_combine(result, val.sign());
- return result;
- }
- } // namespace backends
- #ifdef BOOST_NO_SFINAE_EXPR
- namespace detail{
- template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2, unsigned D2, backends::digit_base_type B2, class A2, class E2, E2 M3, E2 M4>
- struct is_explicitly_convertible<backends::cpp_bin_float<D1, B1, A1, E1, M1, M2>, backends::cpp_bin_float<D2, B2, A2, E2, M3, M4> > : public mpl::true_ {};
- template<class FloatT, unsigned D2, backends::digit_base_type B2, class A2, class E2, E2 M3, E2 M4>
- struct is_explicitly_convertible<FloatT, backends::cpp_bin_float<D2, B2, A2, E2, M3, M4> > : public boost::is_floating_point<FloatT> {};
- }
- #endif
- 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;
- }
- using backends::cpp_bin_float;
- using backends::digit_base_2;
- using backends::digit_base_10;
- 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 boost::mpl::int_<boost::multiprecision::number_kind_floating_point>{};
- template<unsigned Digits, backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
- struct expression_template_default<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >
- {
- static const expression_template_option value = is_void<Allocator>::value ? et_off : et_on;
- };
- typedef number<backends::cpp_bin_float<50> > cpp_bin_float_50;
- typedef number<backends::cpp_bin_float<100> > cpp_bin_float_100;
- typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> cpp_bin_float_single;
- typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023>, et_off> cpp_bin_float_double;
- typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended;
- typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad;
- typedef number<backends::cpp_bin_float<237, backends::digit_base_2, void, boost::int32_t, -262142, 262143>, et_off> cpp_bin_float_oct;
- } // namespace multiprecision
- namespace math {
- using boost::multiprecision::signbit;
- using boost::multiprecision::copysign;
- } // 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> >
- {
- typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> number_type;
- public:
- BOOST_STATIC_CONSTEXPR bool is_specialized = true;
- static number_type (min)()
- {
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- value.first = true;
- typedef typename boost::mpl::front<typename number_type::backend_type::unsigned_types>::type ui_type;
- value.second.backend() = ui_type(1u);
- value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
- }
- return value.second;
- }
- static number_type (max)()
- {
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- value.first = true;
- if(boost::is_void<Allocator>::value)
- eval_complement(value.second.backend().bits(), value.second.backend().bits());
- else
- {
- // We jump through hoops here using the backend type directly just to keep VC12 happy
- // (ie compiler workaround, for very strange compiler bug):
- using boost::multiprecision::default_ops::eval_add;
- using boost::multiprecision::default_ops::eval_decrement;
- using boost::multiprecision::default_ops::eval_left_shift;
- typedef typename number_type::backend_type::rep_type int_backend_type;
- typedef typename boost::mpl::front<typename int_backend_type::unsigned_types>::type ui_type;
- int_backend_type i;
- i = ui_type(1u);
- eval_left_shift(i, boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1);
- int_backend_type j(i);
- eval_decrement(i);
- eval_add(j, i);
- value.second.backend().bits() = j;
- }
- value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
- }
- return value.second;
- }
- BOOST_STATIC_CONSTEXPR number_type lowest()
- {
- return -(max)();
- }
- BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count;
- BOOST_STATIC_CONSTEXPR int digits10 = (digits - 1) * 301 / 1000;
- // Is this really correct???
- BOOST_STATIC_CONSTEXPR int max_digits10 = (digits * 301 / 1000) + 3;
- BOOST_STATIC_CONSTEXPR bool is_signed = true;
- BOOST_STATIC_CONSTEXPR bool is_integer = false;
- BOOST_STATIC_CONSTEXPR bool is_exact = false;
- BOOST_STATIC_CONSTEXPR int radix = 2;
- static number_type epsilon()
- {
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- // We jump through hoops here just to keep VC12 happy (ie compiler workaround, for very strange compiler bug):
- typedef typename boost::mpl::front<typename number_type::backend_type::unsigned_types>::type ui_type;
- value.first = true;
- value.second.backend() = ui_type(1u);
- value.second = ldexp(value.second, 1 - (int)digits);
- }
- return value.second;
- }
- // What value should this be????
- static number_type round_error()
- {
- // returns 0.5
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- value.first = true;
- // We jump through hoops here just to keep VC12 happy (ie compiler workaround, for very strange compiler bug):
- typedef typename boost::mpl::front<typename number_type::backend_type::unsigned_types>::type ui_type;
- value.second.backend() = ui_type(1u);
- value.second = ldexp(value.second, -1);
- }
- return value.second;
- }
- BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
- BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent10 = (min_exponent / 1000) * 301L;
- BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
- BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent10 = (max_exponent / 1000) * 301L;
- BOOST_STATIC_CONSTEXPR bool has_infinity = true;
- BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
- BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
- BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
- BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
- static number_type infinity()
- {
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- value.first = true;
- value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
- }
- return value.second;
- }
- static number_type quiet_NaN()
- {
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- value.first = true;
- value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan;
- }
- return value.second;
- }
- BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
- {
- return number_type(0);
- }
- BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); }
- BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
- BOOST_STATIC_CONSTEXPR bool is_bounded = true;
- BOOST_STATIC_CONSTEXPR bool is_modulo = false;
- BOOST_STATIC_CONSTEXPR bool traps = true;
- BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
- BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
- private:
- struct data_initializer
- {
- data_initializer()
- {
- std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::epsilon();
- std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::round_error();
- (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::min)();
- (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::max)();
- std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity();
- std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN();
- }
- void do_nothing()const{}
- };
- static const data_initializer initializer;
- };
- template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
- const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::initializer;
- #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
- template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_signaling_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>
- BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm;
- template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST 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>
- BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::round_style;
- #endif
- } // namespace std
- #endif
|