123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622 |
- ///////////////////////////////////////////////////////////////////////////////
- // Copyright 2011 John Maddock. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_MATH_ER_GMP_BACKEND_HPP
- #define BOOST_MATH_ER_GMP_BACKEND_HPP
- #include <boost/multiprecision/number.hpp>
- #include <boost/multiprecision/detail/integer_ops.hpp>
- #include <boost/multiprecision/detail/big_lanczos.hpp>
- #include <boost/multiprecision/detail/digits.hpp>
- #include <boost/math/special_functions/fpclassify.hpp>
- #include <boost/cstdint.hpp>
- #ifdef BOOST_MSVC
- # pragma warning(push)
- # pragma warning(disable:4127)
- #endif
- #include <gmp.h>
- #ifdef BOOST_MSVC
- # pragma warning(pop)
- #endif
- #include <cmath>
- #include <limits>
- #include <climits>
- namespace boost{
- namespace multiprecision{
- namespace backends{
- #ifdef BOOST_MSVC
- // warning C4127: conditional expression is constant
- #pragma warning(push)
- #pragma warning(disable:4127)
- #endif
- template <unsigned digits10>
- struct gmp_float;
- struct gmp_int;
- struct gmp_rational;
- } // namespace backends
- template<>
- struct number_category<backends::gmp_int> : public mpl::int_<number_kind_integer>{};
- template<>
- struct number_category<backends::gmp_rational> : public mpl::int_<number_kind_rational>{};
- template <unsigned digits10>
- struct number_category<backends::gmp_float<digits10> > : public mpl::int_<number_kind_floating_point>{};
- namespace backends{
- //
- // Within this file, the only functions we mark as noexcept are those that manipulate
- // (but don't create) an mpf_t. All other types may allocate at pretty much any time
- // via a user-supplied allocator, and therefore throw.
- //
- namespace detail{
- template <unsigned digits10>
- struct gmp_float_imp
- {
- typedef mpl::list<long, long long> signed_types;
- typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
- typedef mpl::list<double, long double> float_types;
- typedef long exponent_type;
- gmp_float_imp() BOOST_NOEXCEPT {}
- gmp_float_imp(const gmp_float_imp& o)
- {
- //
- // We have to do an init followed by a set here, otherwise *this may be at
- // a lower precision than o: seems like mpf_init_set copies just enough bits
- // to get the right value, but if it's then used in further calculations
- // things go badly wrong!!
- //
- mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- if(o.m_data[0]._mp_d)
- mpf_set(m_data, o.m_data);
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_float_imp(gmp_float_imp&& o) BOOST_NOEXCEPT
- {
- m_data[0] = o.m_data[0];
- o.m_data[0]._mp_d = 0;
- }
- #endif
- gmp_float_imp& operator = (const gmp_float_imp& o)
- {
- if(m_data[0]._mp_d == 0)
- mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- if(o.m_data[0]._mp_d)
- mpf_set(m_data, o.m_data);
- return *this;
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_float_imp& operator = (gmp_float_imp&& o) BOOST_NOEXCEPT
- {
- mpf_swap(m_data, o.m_data);
- return *this;
- }
- #endif
- gmp_float_imp& operator = (unsigned long long i)
- {
- if(m_data[0]._mp_d == 0)
- mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
- unsigned shift = 0;
- mpf_t t;
- mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- mpf_set_ui(m_data, 0);
- while(i)
- {
- mpf_set_ui(t, static_cast<unsigned>(i & mask));
- if(shift)
- mpf_mul_2exp(t, t, shift);
- mpf_add(m_data, m_data, t);
- shift += std::numeric_limits<unsigned>::digits;
- i >>= std::numeric_limits<unsigned>::digits;
- }
- mpf_clear(t);
- return *this;
- }
- gmp_float_imp& operator = (long long i)
- {
- BOOST_MP_USING_ABS
- if(m_data[0]._mp_d == 0)
- mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- bool neg = i < 0;
- *this = static_cast<unsigned long long>(abs(i));
- if(neg)
- mpf_neg(m_data, m_data);
- return *this;
- }
- gmp_float_imp& operator = (unsigned long i)
- {
- if(m_data[0]._mp_d == 0)
- mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- mpf_set_ui(m_data, i);
- return *this;
- }
- gmp_float_imp& operator = (long i)
- {
- if(m_data[0]._mp_d == 0)
- mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- mpf_set_si(m_data, i);
- return *this;
- }
- gmp_float_imp& operator = (double d)
- {
- if(m_data[0]._mp_d == 0)
- mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- mpf_set_d(m_data, d);
- return *this;
- }
- gmp_float_imp& operator = (long double a)
- {
- using std::frexp;
- using std::ldexp;
- using std::floor;
- if(m_data[0]._mp_d == 0)
- mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- if (a == 0) {
- mpf_set_si(m_data, 0);
- return *this;
- }
- if (a == 1) {
- mpf_set_si(m_data, 1);
- return *this;
- }
- BOOST_ASSERT(!(boost::math::isinf)(a));
- BOOST_ASSERT(!(boost::math::isnan)(a));
- int e;
- long double f, term;
- mpf_set_ui(m_data, 0u);
- f = frexp(a, &e);
- static const int shift = std::numeric_limits<int>::digits - 1;
- while(f)
- {
- // extract int sized bits from f:
- f = ldexp(f, shift);
- term = floor(f);
- e -= shift;
- mpf_mul_2exp(m_data, m_data, shift);
- if(term > 0)
- mpf_add_ui(m_data, m_data, static_cast<unsigned>(term));
- else
- mpf_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
- f -= term;
- }
- if(e > 0)
- mpf_mul_2exp(m_data, m_data, e);
- else if(e < 0)
- mpf_div_2exp(m_data, m_data, -e);
- return *this;
- }
- gmp_float_imp& operator = (const char* s)
- {
- if(m_data[0]._mp_d == 0)
- mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
- if(0 != mpf_set_str(m_data, s, 10))
- BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid floating point number.")));
- return *this;
- }
- void swap(gmp_float_imp& o) BOOST_NOEXCEPT
- {
- mpf_swap(m_data, o.m_data);
- }
- std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
- bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
- std::streamsize org_digits(digits);
- if(scientific && digits)
- ++digits;
- std::string result;
- mp_exp_t e;
- void *(*alloc_func_ptr) (size_t);
- void *(*realloc_func_ptr) (void *, size_t, size_t);
- void (*free_func_ptr) (void *, size_t);
- mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
- if(mpf_sgn(m_data) == 0)
- {
- e = 0;
- result = "0";
- if(fixed && digits)
- ++digits;
- }
- else
- {
- char* ps = mpf_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data);
- --e; // To match with what our formatter expects.
- if(fixed && e != -1)
- {
- // Oops we actually need a different number of digits to what we asked for:
- (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
- digits += e + 1;
- if(digits == 0)
- {
- // We need to get *all* the digits and then possibly round up,
- // we end up with either "0" or "1" as the result.
- ps = mpf_get_str (0, &e, 10, 0, m_data);
- --e;
- unsigned offset = *ps == '-' ? 1 : 0;
- if(ps[offset] > '5')
- {
- ++e;
- ps[offset] = '1';
- ps[offset + 1] = 0;
- }
- else if(ps[offset] == '5')
- {
- unsigned i = offset + 1;
- bool round_up = false;
- while(ps[i] != 0)
- {
- if(ps[i] != '0')
- {
- round_up = true;
- break;
- }
- }
- if(round_up)
- {
- ++e;
- ps[offset] = '1';
- ps[offset + 1] = 0;
- }
- else
- {
- ps[offset] = '0';
- ps[offset + 1] = 0;
- }
- }
- else
- {
- ps[offset] = '0';
- ps[offset + 1] = 0;
- }
- }
- else if(digits > 0)
- {
- ps = mpf_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data);
- --e; // To match with what our formatter expects.
- }
- else
- {
- ps = mpf_get_str (0, &e, 10, 1, m_data);
- --e;
- unsigned offset = *ps == '-' ? 1 : 0;
- ps[offset] = '0';
- ps[offset + 1] = 0;
- }
- }
- result = ps;
- (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
- }
- boost::multiprecision::detail::format_float_string(result, e, org_digits, f, mpf_sgn(m_data) == 0);
- return result;
- }
- ~gmp_float_imp() BOOST_NOEXCEPT
- {
- if(m_data[0]._mp_d)
- mpf_clear(m_data);
- }
- void negate() BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- mpf_neg(m_data, m_data);
- }
- int compare(const gmp_float<digits10>& o)const BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d);
- return mpf_cmp(m_data, o.m_data);
- }
- int compare(long i)const BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- return mpf_cmp_si(m_data, i);
- }
- int compare(unsigned long i)const BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- return mpf_cmp_ui(m_data, i);
- }
- template <class V>
- typename enable_if<is_arithmetic<V>, int>::type compare(V v)const
- {
- gmp_float<digits10> d;
- d = v;
- return compare(d);
- }
- mpf_t& data() BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- return m_data;
- }
- const mpf_t& data()const BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- return m_data;
- }
- protected:
- mpf_t m_data;
- static unsigned& get_default_precision() BOOST_NOEXCEPT
- {
- static unsigned val = 50;
- return val;
- }
- };
- } // namespace detail
- struct gmp_int;
- struct gmp_rational;
- template <unsigned digits10>
- struct gmp_float : public detail::gmp_float_imp<digits10>
- {
- gmp_float()
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
- }
- gmp_float(const gmp_float& o) : detail::gmp_float_imp<digits10>(o) {}
- template <unsigned D>
- gmp_float(const gmp_float<D>& o, typename enable_if_c<D <= digits10>::type* = 0);
- template <unsigned D>
- explicit gmp_float(const gmp_float<D>& o, typename disable_if_c<D <= digits10>::type* = 0);
- gmp_float(const gmp_int& o);
- gmp_float(const gmp_rational& o);
- gmp_float(const mpf_t val)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
- mpf_set(this->m_data, val);
- }
- gmp_float(const mpz_t val)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
- mpf_set_z(this->m_data, val);
- }
- gmp_float(const mpq_t val)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
- mpf_set_q(this->m_data, val);
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp<digits10>(static_cast<detail::gmp_float_imp<digits10>&&>(o)) {}
- #endif
- gmp_float& operator=(const gmp_float& o)
- {
- *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10> const&>(o);
- return *this;
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT
- {
- *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10>&&>(o);
- return *this;
- }
- #endif
- template <unsigned D>
- gmp_float& operator=(const gmp_float<D>& o);
- gmp_float& operator=(const gmp_int& o);
- gmp_float& operator=(const gmp_rational& o);
- gmp_float& operator=(const mpf_t val)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
- mpf_set(this->m_data, val);
- return *this;
- }
- gmp_float& operator=(const mpz_t val)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
- mpf_set_z(this->m_data, val);
- return *this;
- }
- gmp_float& operator=(const mpq_t val)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
- mpf_set_q(this->m_data, val);
- return *this;
- }
- template <class V>
- gmp_float& operator=(const V& v)
- {
- *static_cast<detail::gmp_float_imp<digits10>*>(this) = v;
- return *this;
- }
- };
- template <>
- struct gmp_float<0> : public detail::gmp_float_imp<0>
- {
- gmp_float()
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
- }
- gmp_float(const mpf_t val)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
- mpf_set(this->m_data, val);
- }
- gmp_float(const mpz_t val)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
- mpf_set_z(this->m_data, val);
- }
- gmp_float(const mpq_t val)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
- mpf_set_q(this->m_data, val);
- }
- gmp_float(const gmp_float& o) : detail::gmp_float_imp<0>(o) {}
- template <unsigned D>
- gmp_float(const gmp_float<D>& o)
- {
- mpf_init2(this->m_data, mpf_get_prec(o.data()));
- mpf_set(this->m_data, o.data());
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp<0>(static_cast<detail::gmp_float_imp<0>&&>(o)) {}
- #endif
- gmp_float(const gmp_int& o);
- gmp_float(const gmp_rational& o);
- gmp_float(const gmp_float& o, unsigned digits10)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
- mpf_set(this->m_data, o.data());
- }
- gmp_float& operator=(const gmp_float& o)
- {
- *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0> const&>(o);
- return *this;
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT
- {
- *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0> &&>(o);
- return *this;
- }
- #endif
- template <unsigned D>
- gmp_float& operator=(const gmp_float<D>& o)
- {
- if(this->m_data[0]._mp_d == 0)
- {
- mpf_init2(this->m_data, mpf_get_prec(o.data()));
- }
- else
- {
- mpf_set_prec(this->m_data, mpf_get_prec(o.data()));
- }
- mpf_set(this->m_data, o.data());
- return *this;
- }
- gmp_float& operator=(const gmp_int& o);
- gmp_float& operator=(const gmp_rational& o);
- gmp_float& operator=(const mpf_t val)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
- mpf_set(this->m_data, val);
- return *this;
- }
- gmp_float& operator=(const mpz_t val)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
- mpf_set_z(this->m_data, val);
- return *this;
- }
- gmp_float& operator=(const mpq_t val)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
- mpf_set_q(this->m_data, val);
- return *this;
- }
- template <class V>
- gmp_float& operator=(const V& v)
- {
- *static_cast<detail::gmp_float_imp<0>*>(this) = v;
- return *this;
- }
- static unsigned default_precision() BOOST_NOEXCEPT
- {
- return get_default_precision();
- }
- static void default_precision(unsigned v) BOOST_NOEXCEPT
- {
- get_default_precision() = v;
- }
- unsigned precision()const BOOST_NOEXCEPT
- {
- return multiprecision::detail::digits2_2_10(mpf_get_prec(this->m_data));
- }
- void precision(unsigned digits10) BOOST_NOEXCEPT
- {
- mpf_set_prec(this->m_data, multiprecision::detail::digits10_2_2(digits10));
- }
- };
- template <unsigned digits10, class T>
- inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_eq(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
- {
- return a.compare(b) == 0;
- }
- template <unsigned digits10, class T>
- inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_lt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
- {
- return a.compare(b) < 0;
- }
- template <unsigned digits10, class T>
- inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_gt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
- {
- return a.compare(b) > 0;
- }
- template <unsigned D1, unsigned D2>
- inline void eval_add(gmp_float<D1>& result, const gmp_float<D2>& o)
- {
- mpf_add(result.data(), result.data(), o.data());
- }
- template <unsigned D1, unsigned D2>
- inline void eval_subtract(gmp_float<D1>& result, const gmp_float<D2>& o)
- {
- mpf_sub(result.data(), result.data(), o.data());
- }
- template <unsigned D1, unsigned D2>
- inline void eval_multiply(gmp_float<D1>& result, const gmp_float<D2>& o)
- {
- mpf_mul(result.data(), result.data(), o.data());
- }
- template <unsigned digits10>
- inline bool eval_is_zero(const gmp_float<digits10>& val) BOOST_NOEXCEPT
- {
- return mpf_sgn(val.data()) == 0;
- }
- template <unsigned D1, unsigned D2>
- inline void eval_divide(gmp_float<D1>& result, const gmp_float<D2>& o)
- {
- if(eval_is_zero(o))
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpf_div(result.data(), result.data(), o.data());
- }
- template <unsigned digits10>
- inline void eval_add(gmp_float<digits10>& result, unsigned long i)
- {
- mpf_add_ui(result.data(), result.data(), i);
- }
- template <unsigned digits10>
- inline void eval_subtract(gmp_float<digits10>& result, unsigned long i)
- {
- mpf_sub_ui(result.data(), result.data(), i);
- }
- template <unsigned digits10>
- inline void eval_multiply(gmp_float<digits10>& result, unsigned long i)
- {
- mpf_mul_ui(result.data(), result.data(), i);
- }
- template <unsigned digits10>
- inline void eval_divide(gmp_float<digits10>& result, unsigned long i)
- {
- if(i == 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpf_div_ui(result.data(), result.data(), i);
- }
- template <unsigned digits10>
- inline void eval_add(gmp_float<digits10>& result, long i)
- {
- if(i > 0)
- mpf_add_ui(result.data(), result.data(), i);
- else
- mpf_sub_ui(result.data(), result.data(), std::abs(i));
- }
- template <unsigned digits10>
- inline void eval_subtract(gmp_float<digits10>& result, long i)
- {
- if(i > 0)
- mpf_sub_ui(result.data(), result.data(), i);
- else
- mpf_add_ui(result.data(), result.data(), std::abs(i));
- }
- template <unsigned digits10>
- inline void eval_multiply(gmp_float<digits10>& result, long i)
- {
- mpf_mul_ui(result.data(), result.data(), std::abs(i));
- if(i < 0)
- mpf_neg(result.data(), result.data());
- }
- template <unsigned digits10>
- inline void eval_divide(gmp_float<digits10>& result, long i)
- {
- if(i == 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpf_div_ui(result.data(), result.data(), std::abs(i));
- if(i < 0)
- mpf_neg(result.data(), result.data());
- }
- //
- // Specialised 3 arg versions of the basic operators:
- //
- template <unsigned D1, unsigned D2, unsigned D3>
- inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
- {
- mpf_add(a.data(), x.data(), y.data());
- }
- template <unsigned D1, unsigned D2>
- inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
- {
- mpf_add_ui(a.data(), x.data(), y);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
- {
- if(y < 0)
- mpf_sub_ui(a.data(), x.data(), -y);
- else
- mpf_add_ui(a.data(), x.data(), y);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_add(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
- {
- mpf_add_ui(a.data(), y.data(), x);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_add(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
- {
- if(x < 0)
- {
- mpf_ui_sub(a.data(), -x, y.data());
- mpf_neg(a.data(), a.data());
- }
- else
- mpf_add_ui(a.data(), y.data(), x);
- }
- template <unsigned D1, unsigned D2, unsigned D3>
- inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
- {
- mpf_sub(a.data(), x.data(), y.data());
- }
- template <unsigned D1, unsigned D2>
- inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
- {
- mpf_sub_ui(a.data(), x.data(), y);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
- {
- if(y < 0)
- mpf_add_ui(a.data(), x.data(), -y);
- else
- mpf_sub_ui(a.data(), x.data(), y);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_subtract(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
- {
- mpf_ui_sub(a.data(), x, y.data());
- }
- template <unsigned D1, unsigned D2>
- inline void eval_subtract(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
- {
- if(x < 0)
- {
- mpf_add_ui(a.data(), y.data(), -x);
- mpf_neg(a.data(), a.data());
- }
- else
- mpf_ui_sub(a.data(), x, y.data());
- }
- template <unsigned D1, unsigned D2, unsigned D3>
- inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
- {
- mpf_mul(a.data(), x.data(), y.data());
- }
- template <unsigned D1, unsigned D2>
- inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
- {
- mpf_mul_ui(a.data(), x.data(), y);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
- {
- if(y < 0)
- {
- mpf_mul_ui(a.data(), x.data(), -y);
- a.negate();
- }
- else
- mpf_mul_ui(a.data(), x.data(), y);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_multiply(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
- {
- mpf_mul_ui(a.data(), y.data(), x);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_multiply(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
- {
- if(x < 0)
- {
- mpf_mul_ui(a.data(), y.data(), -x);
- mpf_neg(a.data(), a.data());
- }
- else
- mpf_mul_ui(a.data(), y.data(), x);
- }
- template <unsigned D1, unsigned D2, unsigned D3>
- inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
- {
- if(eval_is_zero(y))
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpf_div(a.data(), x.data(), y.data());
- }
- template <unsigned D1, unsigned D2>
- inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
- {
- if(y == 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpf_div_ui(a.data(), x.data(), y);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
- {
- if(y == 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- if(y < 0)
- {
- mpf_div_ui(a.data(), x.data(), -y);
- a.negate();
- }
- else
- mpf_div_ui(a.data(), x.data(), y);
- }
- template <unsigned D1, unsigned D2>
- inline void eval_divide(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
- {
- if(eval_is_zero(y))
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpf_ui_div(a.data(), x, y.data());
- }
- template <unsigned D1, unsigned D2>
- inline void eval_divide(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
- {
- if(eval_is_zero(y))
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- if(x < 0)
- {
- mpf_ui_div(a.data(), -x, y.data());
- mpf_neg(a.data(), a.data());
- }
- else
- mpf_ui_div(a.data(), x, y.data());
- }
- template <unsigned digits10>
- inline int eval_get_sign(const gmp_float<digits10>& val) BOOST_NOEXCEPT
- {
- return mpf_sgn(val.data());
- }
- template <unsigned digits10>
- inline void eval_convert_to(unsigned long* result, const gmp_float<digits10>& val) BOOST_NOEXCEPT
- {
- if(0 == mpf_fits_ulong_p(val.data()))
- *result = (std::numeric_limits<unsigned long>::max)();
- else
- *result = mpf_get_ui(val.data());
- }
- template <unsigned digits10>
- inline void eval_convert_to(long* result, const gmp_float<digits10>& val) BOOST_NOEXCEPT
- {
- if(0 == mpf_fits_slong_p(val.data()))
- {
- *result = (std::numeric_limits<unsigned long>::max)();
- *result *= mpf_sgn(val.data());
- }
- else
- *result = mpf_get_si(val.data());
- }
- template <unsigned digits10>
- inline void eval_convert_to(double* result, const gmp_float<digits10>& val) BOOST_NOEXCEPT
- {
- *result = mpf_get_d(val.data());
- }
- #ifdef BOOST_HAS_LONG_LONG
- template <unsigned digits10>
- inline void eval_convert_to(long long* result, const gmp_float<digits10>& val)
- {
- gmp_float<digits10> t(val);
- if(eval_get_sign(t) < 0)
- t.negate();
- long digits = std::numeric_limits<long long>::digits - std::numeric_limits<long>::digits;
- if(digits > 0)
- mpf_div_2exp(t.data(), t.data(), digits);
- if(!mpf_fits_slong_p(t.data()))
- {
- if(eval_get_sign(val) < 0)
- *result = (std::numeric_limits<long long>::min)();
- else
- *result = (std::numeric_limits<long long>::max)();
- return;
- };
- *result = mpf_get_si(t.data());
- while(digits > 0)
- {
- *result <<= digits;
- digits -= std::numeric_limits<unsigned long>::digits;
- mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits);
- unsigned long l = mpf_get_ui(t.data());
- if(digits < 0)
- l >>= -digits;
- *result |= l;
- }
- if(eval_get_sign(val) < 0)
- *result = -*result;
- }
- template <unsigned digits10>
- inline void eval_convert_to(unsigned long long* result, const gmp_float<digits10>& val)
- {
- gmp_float<digits10> t(val);
- long digits = std::numeric_limits<long long>::digits - std::numeric_limits<long>::digits;
- if(digits > 0)
- mpf_div_2exp(t.data(), t.data(), digits);
- if(!mpf_fits_ulong_p(t.data()))
- {
- *result = (std::numeric_limits<long long>::max)();
- return;
- }
- *result = mpf_get_ui(t.data());
- while(digits > 0)
- {
- *result <<= digits;
- digits -= std::numeric_limits<unsigned long>::digits;
- mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits);
- unsigned long l = mpf_get_ui(t.data());
- if(digits < 0)
- l >>= -digits;
- *result |= l;
- }
- }
- #endif
- //
- // Native non-member operations:
- //
- template <unsigned Digits10>
- inline void eval_sqrt(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
- {
- mpf_sqrt(result.data(), val.data());
- }
- template <unsigned Digits10>
- inline void eval_abs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
- {
- mpf_abs(result.data(), val.data());
- }
- template <unsigned Digits10>
- inline void eval_fabs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
- {
- mpf_abs(result.data(), val.data());
- }
- template <unsigned Digits10>
- inline void eval_ceil(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
- {
- mpf_ceil(result.data(), val.data());
- }
- template <unsigned Digits10>
- inline void eval_floor(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
- {
- mpf_floor(result.data(), val.data());
- }
- template <unsigned Digits10>
- inline void eval_trunc(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
- {
- mpf_trunc(result.data(), val.data());
- }
- template <unsigned Digits10>
- inline void eval_ldexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long e)
- {
- if(e > 0)
- mpf_mul_2exp(result.data(), val.data(), e);
- else if(e < 0)
- mpf_div_2exp(result.data(), val.data(), -e);
- else
- result = val;
- }
- template <unsigned Digits10>
- inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, int* e)
- {
- long v;
- mpf_get_d_2exp(&v, val.data());
- *e = v;
- eval_ldexp(result, val, -v);
- }
- template <unsigned Digits10>
- inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long* e)
- {
- mpf_get_d_2exp(e, val.data());
- eval_ldexp(result, val, -*e);
- }
- struct gmp_int
- {
- typedef mpl::list<long, long long> signed_types;
- typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
- typedef mpl::list<double, long double> float_types;
- gmp_int()
- {
- mpz_init(this->m_data);
- }
- gmp_int(const gmp_int& o)
- {
- if(o.m_data[0]._mp_d)
- mpz_init_set(m_data, o.m_data);
- else
- mpz_init(this->m_data);
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_int(gmp_int&& o) BOOST_NOEXCEPT
- {
- m_data[0] = o.m_data[0];
- o.m_data[0]._mp_d = 0;
- }
- #endif
- explicit gmp_int(const mpf_t val)
- {
- mpz_init(this->m_data);
- mpz_set_f(this->m_data, val);
- }
- gmp_int(const mpz_t val)
- {
- mpz_init_set(this->m_data, val);
- }
- explicit gmp_int(const mpq_t val)
- {
- mpz_init(this->m_data);
- mpz_set_q(this->m_data, val);
- }
- template <unsigned Digits10>
- explicit gmp_int(const gmp_float<Digits10>& o)
- {
- mpz_init(this->m_data);
- mpz_set_f(this->m_data, o.data());
- }
- explicit gmp_int(const gmp_rational& o);
- gmp_int& operator = (const gmp_int& o)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- mpz_set(m_data, o.m_data);
- return *this;
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_int& operator = (gmp_int&& o) BOOST_NOEXCEPT
- {
- mpz_swap(m_data, o.m_data);
- return *this;
- }
- #endif
- gmp_int& operator = (unsigned long long i)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
- unsigned shift = 0;
- mpz_t t;
- mpz_set_ui(m_data, 0);
- mpz_init_set_ui(t, 0);
- while(i)
- {
- mpz_set_ui(t, static_cast<unsigned>(i & mask));
- if(shift)
- mpz_mul_2exp(t, t, shift);
- mpz_add(m_data, m_data, t);
- shift += std::numeric_limits<unsigned>::digits;
- i >>= std::numeric_limits<unsigned>::digits;
- }
- mpz_clear(t);
- return *this;
- }
- gmp_int& operator = (long long i)
- {
- BOOST_MP_USING_ABS
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- bool neg = i < 0;
- *this = static_cast<unsigned long long>(abs(i));
- if(neg)
- mpz_neg(m_data, m_data);
- return *this;
- }
- gmp_int& operator = (unsigned long i)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- mpz_set_ui(m_data, i);
- return *this;
- }
- gmp_int& operator = (long i)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- mpz_set_si(m_data, i);
- return *this;
- }
- gmp_int& operator = (double d)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- mpz_set_d(m_data, d);
- return *this;
- }
- gmp_int& operator = (long double a)
- {
- using std::frexp;
- using std::ldexp;
- using std::floor;
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- if (a == 0) {
- mpz_set_si(m_data, 0);
- return *this;
- }
- if (a == 1) {
- mpz_set_si(m_data, 1);
- return *this;
- }
- BOOST_ASSERT(!(boost::math::isinf)(a));
- BOOST_ASSERT(!(boost::math::isnan)(a));
- int e;
- long double f, term;
- mpz_set_ui(m_data, 0u);
- f = frexp(a, &e);
- static const int shift = std::numeric_limits<int>::digits - 1;
- while(f)
- {
- // extract int sized bits from f:
- f = ldexp(f, shift);
- term = floor(f);
- e -= shift;
- mpz_mul_2exp(m_data, m_data, shift);
- if(term > 0)
- mpz_add_ui(m_data, m_data, static_cast<unsigned>(term));
- else
- mpz_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
- f -= term;
- }
- if(e > 0)
- mpz_mul_2exp(m_data, m_data, e);
- else if(e < 0)
- mpz_div_2exp(m_data, m_data, -e);
- return *this;
- }
- gmp_int& operator = (const char* s)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- std::size_t n = s ? std::strlen(s) : 0;
- int radix = 10;
- if(n && (*s == '0'))
- {
- if((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
- {
- radix = 16;
- s +=2;
- n -= 2;
- }
- else
- {
- radix = 8;
- n -= 1;
- }
- }
- if(n)
- {
- if(0 != mpz_set_str(m_data, s, radix))
- BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid integer.")));
- }
- else
- mpz_set_ui(m_data, 0);
- return *this;
- }
- gmp_int& operator=(const mpf_t val)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- mpz_set_f(this->m_data, val);
- return *this;
- }
- gmp_int& operator=(const mpz_t val)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- mpz_set(this->m_data, val);
- return *this;
- }
- gmp_int& operator=(const mpq_t val)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- mpz_set_q(this->m_data, val);
- return *this;
- }
- template <unsigned Digits10>
- gmp_int& operator=(const gmp_float<Digits10>& o)
- {
- if(m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- mpz_set_f(this->m_data, o.data());
- return *this;
- }
- gmp_int& operator=(const gmp_rational& o);
- void swap(gmp_int& o)
- {
- mpz_swap(m_data, o.m_data);
- }
- std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f)const
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- int base = 10;
- if((f & std::ios_base::oct) == std::ios_base::oct)
- base = 8;
- else if((f & std::ios_base::hex) == std::ios_base::hex)
- base = 16;
- //
- // sanity check, bases 8 and 16 are only available for positive numbers:
- //
- if((base != 10) && (mpz_sgn(m_data) < 0))
- BOOST_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers"));
- void *(*alloc_func_ptr) (size_t);
- void *(*realloc_func_ptr) (void *, size_t, size_t);
- void (*free_func_ptr) (void *, size_t);
- const char* ps = mpz_get_str (0, base, m_data);
- std::string s = ps;
- mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
- (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
- if((base != 10) && (f & std::ios_base::showbase))
- {
- int pos = s[0] == '-' ? 1 : 0;
- const char* pp = base == 8 ? "0" : "0x";
- s.insert(pos, pp);
- }
- if((f & std::ios_base::showpos) && (s[0] != '-'))
- s.insert(0, 1, '+');
- return s;
- }
- ~gmp_int() BOOST_NOEXCEPT
- {
- if(m_data[0]._mp_d)
- mpz_clear(m_data);
- }
- void negate() BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- mpz_neg(m_data, m_data);
- }
- int compare(const gmp_int& o)const BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d);
- return mpz_cmp(m_data, o.m_data);
- }
- int compare(long i)const BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- return mpz_cmp_si(m_data, i);
- }
- int compare(unsigned long i)const BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- return mpz_cmp_ui(m_data, i);
- }
- template <class V>
- int compare(V v)const
- {
- gmp_int d;
- d = v;
- return compare(d);
- }
- mpz_t& data() BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- return m_data;
- }
- const mpz_t& data()const BOOST_NOEXCEPT
- {
- BOOST_ASSERT(m_data[0]._mp_d);
- return m_data;
- }
- protected:
- mpz_t m_data;
- };
- template <class T>
- inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const gmp_int& a, const T& b)
- {
- return a.compare(b) == 0;
- }
- template <class T>
- inline typename enable_if<is_arithmetic<T>, bool>::type eval_lt(const gmp_int& a, const T& b)
- {
- return a.compare(b) < 0;
- }
- template <class T>
- inline typename enable_if<is_arithmetic<T>, bool>::type eval_gt(const gmp_int& a, const T& b)
- {
- return a.compare(b) > 0;
- }
- inline bool eval_is_zero(const gmp_int& val)
- {
- return mpz_sgn(val.data()) == 0;
- }
- inline void eval_add(gmp_int& t, const gmp_int& o)
- {
- mpz_add(t.data(), t.data(), o.data());
- }
- inline void eval_multiply_add(gmp_int& t, const gmp_int& a, const gmp_int& b)
- {
- mpz_addmul(t.data(), a.data(), b.data());
- }
- inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, const gmp_int& b)
- {
- mpz_submul(t.data(), a.data(), b.data());
- }
- inline void eval_subtract(gmp_int& t, const gmp_int& o)
- {
- mpz_sub(t.data(), t.data(), o.data());
- }
- inline void eval_multiply(gmp_int& t, const gmp_int& o)
- {
- mpz_mul(t.data(), t.data(), o.data());
- }
- inline void eval_divide(gmp_int& t, const gmp_int& o)
- {
- if(eval_is_zero(o))
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpz_tdiv_q(t.data(), t.data(), o.data());
- }
- inline void eval_modulus(gmp_int& t, const gmp_int& o)
- {
- mpz_tdiv_r(t.data(), t.data(), o.data());
- }
- inline void eval_add(gmp_int& t, unsigned long i)
- {
- mpz_add_ui(t.data(), t.data(), i);
- }
- inline void eval_multiply_add(gmp_int& t, const gmp_int& a, unsigned long i)
- {
- mpz_addmul_ui(t.data(), a.data(), i);
- }
- inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, unsigned long i)
- {
- mpz_submul_ui(t.data(), a.data(), i);
- }
- inline void eval_subtract(gmp_int& t, unsigned long i)
- {
- mpz_sub_ui(t.data(), t.data(), i);
- }
- inline void eval_multiply(gmp_int& t, unsigned long i)
- {
- mpz_mul_ui(t.data(), t.data(), i);
- }
- inline void eval_modulus(gmp_int& t, unsigned long i)
- {
- mpz_tdiv_r_ui(t.data(), t.data(), i);
- }
- inline void eval_divide(gmp_int& t, unsigned long i)
- {
- if(i == 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpz_tdiv_q_ui(t.data(), t.data(), i);
- }
- inline void eval_add(gmp_int& t, long i)
- {
- if(i > 0)
- mpz_add_ui(t.data(), t.data(), i);
- else
- mpz_sub_ui(t.data(), t.data(), -i);
- }
- inline void eval_multiply_add(gmp_int& t, const gmp_int& a, long i)
- {
- if(i > 0)
- mpz_addmul_ui(t.data(), a.data(), i);
- else
- mpz_submul_ui(t.data(), a.data(), -i);
- }
- inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, long i)
- {
- if(i > 0)
- mpz_submul_ui(t.data(), a.data(), i);
- else
- mpz_addmul_ui(t.data(), a.data(), -i);
- }
- inline void eval_subtract(gmp_int& t, long i)
- {
- if(i > 0)
- mpz_sub_ui(t.data(), t.data(), i);
- else
- mpz_add_ui(t.data(), t.data(), -i);
- }
- inline void eval_multiply(gmp_int& t, long i)
- {
- mpz_mul_ui(t.data(), t.data(), std::abs(i));
- if(i < 0)
- mpz_neg(t.data(), t.data());
- }
- inline void eval_modulus(gmp_int& t, long i)
- {
- mpz_tdiv_r_ui(t.data(), t.data(), std::abs(i));
- }
- inline void eval_divide(gmp_int& t, long i)
- {
- if(i == 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpz_tdiv_q_ui(t.data(), t.data(), std::abs(i));
- if(i < 0)
- mpz_neg(t.data(), t.data());
- }
- template <class UI>
- inline void eval_left_shift(gmp_int& t, UI i)
- {
- mpz_mul_2exp(t.data(), t.data(), static_cast<unsigned long>(i));
- }
- template <class UI>
- inline void eval_right_shift(gmp_int& t, UI i)
- {
- mpz_fdiv_q_2exp(t.data(), t.data(), static_cast<unsigned long>(i));
- }
- template <class UI>
- inline void eval_left_shift(gmp_int& t, const gmp_int& v, UI i)
- {
- mpz_mul_2exp(t.data(), v.data(), static_cast<unsigned long>(i));
- }
- template <class UI>
- inline void eval_right_shift(gmp_int& t, const gmp_int& v, UI i)
- {
- mpz_fdiv_q_2exp(t.data(), v.data(), static_cast<unsigned long>(i));
- }
- inline void eval_bitwise_and(gmp_int& result, const gmp_int& v)
- {
- mpz_and(result.data(), result.data(), v.data());
- }
- inline void eval_bitwise_or(gmp_int& result, const gmp_int& v)
- {
- mpz_ior(result.data(), result.data(), v.data());
- }
- inline void eval_bitwise_xor(gmp_int& result, const gmp_int& v)
- {
- mpz_xor(result.data(), result.data(), v.data());
- }
- inline void eval_add(gmp_int& t, const gmp_int& p, const gmp_int& o)
- {
- mpz_add(t.data(), p.data(), o.data());
- }
- inline void eval_subtract(gmp_int& t, const gmp_int& p, const gmp_int& o)
- {
- mpz_sub(t.data(), p.data(), o.data());
- }
- inline void eval_multiply(gmp_int& t, const gmp_int& p, const gmp_int& o)
- {
- mpz_mul(t.data(), p.data(), o.data());
- }
- inline void eval_divide(gmp_int& t, const gmp_int& p, const gmp_int& o)
- {
- if(eval_is_zero(o))
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpz_tdiv_q(t.data(), p.data(), o.data());
- }
- inline void eval_modulus(gmp_int& t, const gmp_int& p, const gmp_int& o)
- {
- mpz_tdiv_r(t.data(), p.data(), o.data());
- }
- inline void eval_add(gmp_int& t, const gmp_int& p, unsigned long i)
- {
- mpz_add_ui(t.data(), p.data(), i);
- }
- inline void eval_subtract(gmp_int& t, const gmp_int& p, unsigned long i)
- {
- mpz_sub_ui(t.data(), p.data(), i);
- }
- inline void eval_multiply(gmp_int& t, const gmp_int& p, unsigned long i)
- {
- mpz_mul_ui(t.data(), p.data(), i);
- }
- inline void eval_modulus(gmp_int& t, const gmp_int& p, unsigned long i)
- {
- mpz_tdiv_r_ui(t.data(), p.data(), i);
- }
- inline void eval_divide(gmp_int& t, const gmp_int& p, unsigned long i)
- {
- if(i == 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpz_tdiv_q_ui(t.data(), p.data(), i);
- }
- inline void eval_add(gmp_int& t, const gmp_int& p, long i)
- {
- if(i > 0)
- mpz_add_ui(t.data(), p.data(), i);
- else
- mpz_sub_ui(t.data(), p.data(), -i);
- }
- inline void eval_subtract(gmp_int& t, const gmp_int& p, long i)
- {
- if(i > 0)
- mpz_sub_ui(t.data(), p.data(), i);
- else
- mpz_add_ui(t.data(), p.data(), -i);
- }
- inline void eval_multiply(gmp_int& t, const gmp_int& p, long i)
- {
- mpz_mul_ui(t.data(), p.data(), std::abs(i));
- if(i < 0)
- mpz_neg(t.data(), t.data());
- }
- inline void eval_modulus(gmp_int& t, const gmp_int& p, long i)
- {
- mpz_tdiv_r_ui(t.data(), p.data(), std::abs(i));
- }
- inline void eval_divide(gmp_int& t, const gmp_int& p, long i)
- {
- if(i == 0)
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpz_tdiv_q_ui(t.data(), p.data(), std::abs(i));
- if(i < 0)
- mpz_neg(t.data(), t.data());
- }
- inline void eval_bitwise_and(gmp_int& result, const gmp_int& u, const gmp_int& v)
- {
- mpz_and(result.data(), u.data(), v.data());
- }
- inline void eval_bitwise_or(gmp_int& result, const gmp_int& u, const gmp_int& v)
- {
- mpz_ior(result.data(), u.data(), v.data());
- }
- inline void eval_bitwise_xor(gmp_int& result, const gmp_int& u, const gmp_int& v)
- {
- mpz_xor(result.data(), u.data(), v.data());
- }
- inline void eval_complement(gmp_int& result, const gmp_int& u)
- {
- mpz_com(result.data(), u.data());
- }
- inline int eval_get_sign(const gmp_int& val)
- {
- return mpz_sgn(val.data());
- }
- inline void eval_convert_to(unsigned long* result, const gmp_int& val)
- {
- if(0 == mpz_fits_ulong_p(val.data()))
- {
- *result = (std::numeric_limits<unsigned long>::max)();
- }
- else
- *result = mpz_get_ui(val.data());
- }
- inline void eval_convert_to(long* result, const gmp_int& val)
- {
- if(0 == mpz_fits_slong_p(val.data()))
- {
- *result = (std::numeric_limits<unsigned long>::max)();
- *result *= mpz_sgn(val.data());
- }
- else
- *result = mpz_get_si(val.data());
- }
- inline void eval_convert_to(double* result, const gmp_int& val)
- {
- *result = mpz_get_d(val.data());
- }
- inline void eval_abs(gmp_int& result, const gmp_int& val)
- {
- mpz_abs(result.data(), val.data());
- }
- inline void eval_gcd(gmp_int& result, const gmp_int& a, const gmp_int& b)
- {
- mpz_gcd(result.data(), a.data(), b.data());
- }
- inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b)
- {
- mpz_lcm(result.data(), a.data(), b.data());
- }
- template <class I>
- inline typename enable_if_c<(is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b)
- {
- mpz_gcd_ui(result.data(), a.data(), b);
- }
- template <class I>
- inline typename enable_if_c<(is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b)
- {
- mpz_lcm_ui(result.data(), a.data(), b);
- }
- template <class I>
- inline typename enable_if_c<(is_signed<I>::value && (sizeof(I) <= sizeof(long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b)
- {
- mpz_gcd_ui(result.data(), a.data(), std::abs(b));
- }
- template <class I>
- inline typename enable_if_c<is_signed<I>::value && ((sizeof(I) <= sizeof(long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b)
- {
- mpz_lcm_ui(result.data(), a.data(), std::abs(b));
- }
- inline void eval_integer_sqrt(gmp_int& s, gmp_int& r, const gmp_int& x)
- {
- mpz_sqrtrem(s.data(), r.data(), x.data());
- }
- inline unsigned eval_lsb(const gmp_int& val)
- {
- int c = eval_get_sign(val);
- if(c == 0)
- {
- BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
- }
- if(c < 0)
- {
- BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
- }
- return mpz_scan1(val.data(), 0);
- }
- inline unsigned eval_msb(const gmp_int& val)
- {
- int c = eval_get_sign(val);
- if(c == 0)
- {
- BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
- }
- if(c < 0)
- {
- BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
- }
- return mpz_sizeinbase(val.data(), 2) - 1;
- }
- inline bool eval_bit_test(const gmp_int& val, unsigned index)
- {
- return mpz_tstbit(val.data(), index) ? true : false;
- }
- inline void eval_bit_set(gmp_int& val, unsigned index)
- {
- mpz_setbit(val.data(), index);
- }
- inline void eval_bit_unset(gmp_int& val, unsigned index)
- {
- mpz_clrbit(val.data(), index);
- }
- inline void eval_bit_flip(gmp_int& val, unsigned index)
- {
- mpz_combit(val.data(), index);
- }
- inline void eval_qr(const gmp_int& x, const gmp_int& y,
- gmp_int& q, gmp_int& r)
- {
- mpz_tdiv_qr(q.data(), r.data(), x.data(), y.data());
- }
- template <class Integer>
- inline typename enable_if<is_unsigned<Integer>, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val)
- {
- if((sizeof(Integer) <= sizeof(long)) || (val <= (std::numeric_limits<unsigned long>::max)()))
- {
- return mpz_tdiv_ui(x.data(), val);
- }
- else
- {
- return default_ops::eval_integer_modulus(x, val);
- }
- }
- template <class Integer>
- inline typename enable_if<is_signed<Integer>, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val)
- {
- typedef typename make_unsigned<Integer>::type unsigned_type;
- return eval_integer_modulus(x, static_cast<unsigned_type>(std::abs(val)));
- }
- inline void eval_powm(gmp_int& result, const gmp_int& base, const gmp_int& p, const gmp_int& m)
- {
- if(eval_get_sign(p) < 0)
- {
- BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
- }
- mpz_powm(result.data(), base.data(), p.data(), m.data());
- }
- template <class Integer>
- inline typename enable_if<
- mpl::and_<
- is_unsigned<Integer>,
- mpl::bool_<sizeof(Integer) <= sizeof(unsigned long)>
- >
- >::type eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m)
- {
- mpz_powm_ui(result.data(), base.data(), p, m.data());
- }
- template <class Integer>
- inline typename enable_if<
- mpl::and_<
- is_signed<Integer>,
- mpl::bool_<sizeof(Integer) <= sizeof(unsigned long)>
- >
- >::type eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m)
- {
- if(p < 0)
- {
- BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
- }
- mpz_powm_ui(result.data(), base.data(), p, m.data());
- }
- struct gmp_rational;
- void eval_add(gmp_rational& t, const gmp_rational& o);
- struct gmp_rational
- {
- typedef mpl::list<long, long long> signed_types;
- typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
- typedef mpl::list<double, long double> float_types;
- gmp_rational()
- {
- mpq_init(this->m_data);
- }
- gmp_rational(const gmp_rational& o)
- {
- mpq_init(m_data);
- if(o.m_data[0]._mp_num._mp_d)
- mpq_set(m_data, o.m_data);
- }
- gmp_rational(const gmp_int& o)
- {
- mpq_init(m_data);
- mpq_set_z(m_data, o.data());
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_rational(gmp_rational&& o) BOOST_NOEXCEPT
- {
- m_data[0]._mp_num = o.data()[0]._mp_num;
- m_data[0]._mp_den = o.data()[0]._mp_den;
- o.m_data[0]._mp_num._mp_d = 0;
- o.m_data[0]._mp_den._mp_d = 0;
- }
- #endif
- gmp_rational(const mpq_t o)
- {
- mpq_init(m_data);
- mpq_set(m_data, o);
- }
- gmp_rational(const mpz_t o)
- {
- mpq_init(m_data);
- mpq_set_z(m_data, o);
- }
- gmp_rational& operator = (const gmp_rational& o)
- {
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- mpq_set(m_data, o.m_data);
- return *this;
- }
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- gmp_rational& operator = (gmp_rational&& o) BOOST_NOEXCEPT
- {
- mpq_swap(m_data, o.m_data);
- return *this;
- }
- #endif
- gmp_rational& operator = (unsigned long long i)
- {
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
- unsigned shift = 0;
- mpq_t t;
- mpq_set_ui(m_data, 0, 1);
- mpq_init(t);
- while(i)
- {
- mpq_set_ui(t, static_cast<unsigned>(i & mask), 1);
- if(shift)
- mpq_mul_2exp(t, t, shift);
- mpq_add(m_data, m_data, t);
- shift += std::numeric_limits<unsigned>::digits;
- i >>= std::numeric_limits<unsigned>::digits;
- }
- mpq_clear(t);
- return *this;
- }
- gmp_rational& operator = (long long i)
- {
- BOOST_MP_USING_ABS
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- bool neg = i < 0;
- *this = static_cast<unsigned long long>(abs(i));
- if(neg)
- mpq_neg(m_data, m_data);
- return *this;
- }
- gmp_rational& operator = (unsigned long i)
- {
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- mpq_set_ui(m_data, i, 1);
- return *this;
- }
- gmp_rational& operator = (long i)
- {
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- mpq_set_si(m_data, i, 1);
- return *this;
- }
- gmp_rational& operator = (double d)
- {
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- mpq_set_d(m_data, d);
- return *this;
- }
- gmp_rational& operator = (long double a)
- {
- using std::frexp;
- using std::ldexp;
- using std::floor;
- using default_ops::eval_add;
- using default_ops::eval_subtract;
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- if (a == 0) {
- mpq_set_si(m_data, 0, 1);
- return *this;
- }
- if (a == 1) {
- mpq_set_si(m_data, 1, 1);
- return *this;
- }
- BOOST_ASSERT(!(boost::math::isinf)(a));
- BOOST_ASSERT(!(boost::math::isnan)(a));
- int e;
- long double f, term;
- mpq_set_ui(m_data, 0, 1);
- mpq_set_ui(m_data, 0u, 1);
- gmp_rational t;
- f = frexp(a, &e);
- static const int shift = std::numeric_limits<int>::digits - 1;
- while(f)
- {
- // extract int sized bits from f:
- f = ldexp(f, shift);
- term = floor(f);
- e -= shift;
- mpq_mul_2exp(m_data, m_data, shift);
- t = static_cast<long>(term);
- eval_add(*this, t);
- f -= term;
- }
- if(e > 0)
- mpq_mul_2exp(m_data, m_data, e);
- else if(e < 0)
- mpq_div_2exp(m_data, m_data, -e);
- return *this;
- }
- gmp_rational& operator = (const char* s)
- {
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- if(0 != mpq_set_str(m_data, s, 10))
- BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid rational number.")));
- return *this;
- }
- gmp_rational& operator=(const gmp_int& o)
- {
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- mpq_set_z(m_data, o.data());
- return *this;
- }
- gmp_rational& operator=(const mpq_t o)
- {
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- mpq_set(m_data, o);
- return *this;
- }
- gmp_rational& operator=(const mpz_t o)
- {
- if(m_data[0]._mp_den._mp_d == 0)
- mpq_init(m_data);
- mpq_set_z(m_data, o);
- return *this;
- }
- void swap(gmp_rational& o)
- {
- mpq_swap(m_data, o.m_data);
- }
- std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags /*f*/)const
- {
- BOOST_ASSERT(m_data[0]._mp_num._mp_d);
- // TODO make a better job of this including handling of f!!
- void *(*alloc_func_ptr) (size_t);
- void *(*realloc_func_ptr) (void *, size_t, size_t);
- void (*free_func_ptr) (void *, size_t);
- const char* ps = mpq_get_str (0, 10, m_data);
- std::string s = ps;
- mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
- (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
- return s;
- }
- ~gmp_rational()
- {
- if(m_data[0]._mp_num._mp_d || m_data[0]._mp_den._mp_d)
- mpq_clear(m_data);
- }
- void negate()
- {
- BOOST_ASSERT(m_data[0]._mp_num._mp_d);
- mpq_neg(m_data, m_data);
- }
- int compare(const gmp_rational& o)const
- {
- BOOST_ASSERT(m_data[0]._mp_num._mp_d && o.m_data[0]._mp_num._mp_d);
- return mpq_cmp(m_data, o.m_data);
- }
- template <class V>
- int compare(V v)const
- {
- gmp_rational d;
- d = v;
- return compare(d);
- }
- int compare(unsigned long v)const
- {
- BOOST_ASSERT(m_data[0]._mp_num._mp_d);
- return mpq_cmp_ui(m_data, v, 1);
- }
- int compare(long v)const
- {
- BOOST_ASSERT(m_data[0]._mp_num._mp_d);
- return mpq_cmp_si(m_data, v, 1);
- }
- mpq_t& data()
- {
- BOOST_ASSERT(m_data[0]._mp_num._mp_d);
- return m_data;
- }
- const mpq_t& data()const
- {
- BOOST_ASSERT(m_data[0]._mp_num._mp_d);
- return m_data;
- }
- protected:
- mpq_t m_data;
- };
- inline bool eval_is_zero(const gmp_rational& val)
- {
- return mpq_sgn(val.data()) == 0;
- }
- template <class T>
- inline bool eval_eq(gmp_rational& a, const T& b)
- {
- return a.compare(b) == 0;
- }
- template <class T>
- inline bool eval_lt(gmp_rational& a, const T& b)
- {
- return a.compare(b) < 0;
- }
- template <class T>
- inline bool eval_gt(gmp_rational& a, const T& b)
- {
- return a.compare(b) > 0;
- }
- inline void eval_add(gmp_rational& t, const gmp_rational& o)
- {
- mpq_add(t.data(), t.data(), o.data());
- }
- inline void eval_subtract(gmp_rational& t, const gmp_rational& o)
- {
- mpq_sub(t.data(), t.data(), o.data());
- }
- inline void eval_multiply(gmp_rational& t, const gmp_rational& o)
- {
- mpq_mul(t.data(), t.data(), o.data());
- }
- inline void eval_divide(gmp_rational& t, const gmp_rational& o)
- {
- if(eval_is_zero(o))
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpq_div(t.data(), t.data(), o.data());
- }
- inline void eval_add(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
- {
- mpq_add(t.data(), p.data(), o.data());
- }
- inline void eval_subtract(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
- {
- mpq_sub(t.data(), p.data(), o.data());
- }
- inline void eval_multiply(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
- {
- mpq_mul(t.data(), p.data(), o.data());
- }
- inline void eval_divide(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
- {
- if(eval_is_zero(o))
- BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- mpq_div(t.data(), p.data(), o.data());
- }
- inline int eval_get_sign(const gmp_rational& val)
- {
- return mpq_sgn(val.data());
- }
- inline void eval_convert_to(double* result, const gmp_rational& val)
- {
- *result = mpq_get_d(val.data());
- }
- inline void eval_convert_to(long* result, const gmp_rational& val)
- {
- double r;
- eval_convert_to(&r, val);
- *result = static_cast<long>(r);
- }
- inline void eval_convert_to(unsigned long* result, const gmp_rational& val)
- {
- double r;
- eval_convert_to(&r, val);
- *result = static_cast<long>(r);
- }
- inline void eval_abs(gmp_rational& result, const gmp_rational& val)
- {
- mpq_abs(result.data(), val.data());
- }
- inline void assign_components(gmp_rational& result, unsigned long v1, unsigned long v2)
- {
- mpq_set_ui(result.data(), v1, v2);
- mpq_canonicalize(result.data());
- }
- inline void assign_components(gmp_rational& result, long v1, long v2)
- {
- mpq_set_si(result.data(), v1, v2);
- mpq_canonicalize(result.data());
- }
- inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int const& v2)
- {
- mpz_set(mpq_numref(result.data()), v1.data());
- mpz_set(mpq_denref(result.data()), v2.data());
- mpq_canonicalize(result.data());
- }
- //
- // Some member functions that are dependent upon previous code go here:
- //
- template <unsigned Digits10>
- template <unsigned D>
- inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename enable_if_c<D <= Digits10>::type*)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision()));
- mpf_set(this->m_data, o.data());
- }
- template <unsigned Digits10>
- template <unsigned D>
- inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename disable_if_c<D <= Digits10>::type*)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision()));
- mpf_set(this->m_data, o.data());
- }
- template <unsigned Digits10>
- inline gmp_float<Digits10>::gmp_float(const gmp_int& o)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision()));
- mpf_set_z(this->data(), o.data());
- }
- template <unsigned Digits10>
- inline gmp_float<Digits10>::gmp_float(const gmp_rational& o)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision()));
- mpf_set_q(this->data(), o.data());
- }
- template <unsigned Digits10>
- template <unsigned D>
- inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_float<D>& o)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision()));
- mpf_set(this->m_data, o.data());
- return *this;
- }
- template <unsigned Digits10>
- inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_int& o)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision()));
- mpf_set_z(this->data(), o.data());
- return *this;
- }
- template <unsigned Digits10>
- inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_rational& o)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision()));
- mpf_set_q(this->data(), o.data());
- return *this;
- }
- inline gmp_float<0>::gmp_float(const gmp_int& o)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
- mpf_set_z(this->data(), o.data());
- }
- inline gmp_float<0>::gmp_float(const gmp_rational& o)
- {
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
- mpf_set_q(this->data(), o.data());
- }
- inline gmp_float<0>& gmp_float<0>::operator=(const gmp_int& o)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(this->get_default_precision()));
- mpf_set_z(this->data(), o.data());
- return *this;
- }
- inline gmp_float<0>& gmp_float<0>::operator=(const gmp_rational& o)
- {
- if(this->m_data[0]._mp_d == 0)
- mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(this->get_default_precision()));
- mpf_set_q(this->data(), o.data());
- return *this;
- }
- inline gmp_int::gmp_int(const gmp_rational& o)
- {
- mpz_init(this->m_data);
- mpz_set_q(this->m_data, o.data());
- }
- inline gmp_int& gmp_int::operator=(const gmp_rational& o)
- {
- if(this->m_data[0]._mp_d == 0)
- mpz_init(this->m_data);
- mpz_set_q(this->m_data, o.data());
- return *this;
- }
- } //namespace backends
- using boost::multiprecision::backends::gmp_int;
- using boost::multiprecision::backends::gmp_rational;
- using boost::multiprecision::backends::gmp_float;
- template <>
- struct component_type<number<gmp_rational> >
- {
- typedef number<gmp_int> type;
- };
- template <expression_template_option ET>
- inline number<gmp_int, ET> numerator(const number<gmp_rational, ET>& val)
- {
- number<gmp_int, ET> result;
- mpz_set(result.backend().data(), (mpq_numref(val.backend().data())));
- return result;
- }
- template <expression_template_option ET>
- inline number<gmp_int, ET> denominator(const number<gmp_rational, ET>& val)
- {
- number<gmp_int, ET> result;
- mpz_set(result.backend().data(), (mpq_denref(val.backend().data())));
- return result;
- }
- #ifdef BOOST_NO_SFINAE_EXPR
- namespace detail{
- template<>
- struct is_explicitly_convertible<canonical<mpf_t, gmp_int>::type, gmp_int> : public mpl::true_ {};
- template<>
- struct is_explicitly_convertible<canonical<mpq_t, gmp_int>::type, gmp_int> : public mpl::true_ {};
- template<unsigned Digits10>
- struct is_explicitly_convertible<gmp_float<Digits10>, gmp_int> : public mpl::true_ {};
- template<>
- struct is_explicitly_convertible<gmp_rational, gmp_int> : public mpl::true_ {};
- template<unsigned D1, unsigned D2>
- struct is_explicitly_convertible<gmp_float<D1>, gmp_float<D2> > : public mpl::true_ {};
- }
- #endif
- template<>
- struct number_category<detail::canonical<mpz_t, gmp_int>::type> : public mpl::int_<number_kind_integer>{};
- template<>
- struct number_category<detail::canonical<mpq_t, gmp_rational>::type> : public mpl::int_<number_kind_rational>{};
- template<>
- struct number_category<detail::canonical<mpf_t, gmp_float<0> >::type> : public mpl::int_<number_kind_floating_point>{};
- typedef number<gmp_float<50> > mpf_float_50;
- typedef number<gmp_float<100> > mpf_float_100;
- typedef number<gmp_float<500> > mpf_float_500;
- typedef number<gmp_float<1000> > mpf_float_1000;
- typedef number<gmp_float<0> > mpf_float;
- typedef number<gmp_int > mpz_int;
- typedef number<gmp_rational > mpq_rational;
- }} // namespaces
- namespace std{
- //
- // numeric_limits [partial] specializations for the types declared in this header:
- //
- template<unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
- class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >
- {
- typedef boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> number_type;
- public:
- BOOST_STATIC_CONSTEXPR bool is_specialized = true;
- //
- // min and max values chosen so as to not cause segfaults when calling
- // mpf_get_str on 64-bit Linux builds. Possibly we could use larger
- // exponent values elsewhere.
- //
- static number_type (min)()
- {
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- value.first = true;
- value.second = 1;
- mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
- }
- return value.second;
- }
- static number_type (max)()
- {
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- value.first = true;
- value.second = 1;
- mpf_mul_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
- }
- return value.second;
- }
- BOOST_STATIC_CONSTEXPR number_type lowest()
- {
- return -(max)();
- }
- BOOST_STATIC_CONSTEXPR int digits = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301L ? 2 : 1));
- BOOST_STATIC_CONSTEXPR int digits10 = Digits10;
- // Have to allow for a possible extra limb inside the gmp data structure:
- BOOST_STATIC_CONSTEXPR int max_digits10 = Digits10 + 2 + ((GMP_LIMB_BITS * 301L) / 1000L);
- BOOST_STATIC_CONSTEXPR bool is_signed = true;
- BOOST_STATIC_CONSTEXPR bool is_integer = false;
- BOOST_STATIC_CONSTEXPR bool is_exact = false;
- BOOST_STATIC_CONSTEXPR int radix = 2;
- static number_type epsilon()
- {
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- value.first = true;
- value.second = 1;
- mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits<number_type>::digits - 1);
- }
- return value.second;
- }
- // What value should this be????
- static number_type round_error()
- {
- // returns epsilon/2
- initializer.do_nothing();
- static std::pair<bool, number_type> value;
- if(!value.first)
- {
- value.first = true;
- value.second = 1;
- }
- return value.second;
- }
- BOOST_STATIC_CONSTEXPR long min_exponent = LONG_MIN;
- BOOST_STATIC_CONSTEXPR long min_exponent10 = (LONG_MIN / 1000) * 301L;
- BOOST_STATIC_CONSTEXPR long max_exponent = LONG_MAX;
- BOOST_STATIC_CONSTEXPR long max_exponent10 = (LONG_MAX / 1000) * 301L;
- BOOST_STATIC_CONSTEXPR bool has_infinity = false;
- BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false;
- BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
- BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
- BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
- BOOST_STATIC_CONSTEXPR number_type infinity() { return number_type(); }
- BOOST_STATIC_CONSTEXPR number_type quiet_NaN() { return number_type(); }
- BOOST_STATIC_CONSTEXPR number_type signaling_NaN() { return number_type(); }
- BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(); }
- BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
- BOOST_STATIC_CONSTEXPR bool is_bounded = true;
- BOOST_STATIC_CONSTEXPR bool is_modulo = false;
- BOOST_STATIC_CONSTEXPR bool traps = true;
- BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
- BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate;
- private:
- struct data_initializer
- {
- data_initializer()
- {
- std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::epsilon();
- std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::round_error();
- (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::min)();
- (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::max)();
- }
- void do_nothing()const{}
- };
- static const data_initializer initializer;
- };
- template<unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
- const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::initializer;
- template<boost::multiprecision::expression_template_option ExpressionTemplates>
- class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >
- {
- typedef boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> number_type;
- public:
- BOOST_STATIC_CONSTEXPR bool is_specialized = false;
- static number_type (min)() { return number_type(); }
- static number_type (max)() { return number_type(); }
- static number_type lowest() { return number_type(); }
- BOOST_STATIC_CONSTEXPR int digits = 0;
- BOOST_STATIC_CONSTEXPR int digits10 = 0;
- BOOST_STATIC_CONSTEXPR int max_digits10 = 0;
- BOOST_STATIC_CONSTEXPR bool is_signed = false;
- BOOST_STATIC_CONSTEXPR bool is_integer = false;
- BOOST_STATIC_CONSTEXPR bool is_exact = false;
- BOOST_STATIC_CONSTEXPR int radix = 0;
- static number_type epsilon() { return number_type(); }
- static number_type round_error() { return number_type(); }
- BOOST_STATIC_CONSTEXPR int min_exponent = 0;
- BOOST_STATIC_CONSTEXPR int min_exponent10 = 0;
- BOOST_STATIC_CONSTEXPR int max_exponent = 0;
- BOOST_STATIC_CONSTEXPR int max_exponent10 = 0;
- BOOST_STATIC_CONSTEXPR bool has_infinity = false;
- BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false;
- BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
- BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
- BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
- static number_type infinity() { return number_type(); }
- static number_type quiet_NaN() { return number_type(); }
- static number_type signaling_NaN() { return number_type(); }
- static number_type denorm_min() { return number_type(); }
- BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
- BOOST_STATIC_CONSTEXPR bool is_bounded = false;
- BOOST_STATIC_CONSTEXPR bool is_modulo = false;
- BOOST_STATIC_CONSTEXPR bool traps = false;
- BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
- BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate;
- };
- #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_digits10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_signed;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_integer;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_exact;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::radix;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_infinity;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_quiet_NaN;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_signaling_NaN;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm_loss;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_iec559;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_bounded;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_modulo;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::traps;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::tinyness_before;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::round_style;
- #endif
- template<boost::multiprecision::expression_template_option ExpressionTemplates>
- class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >
- {
- typedef boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> number_type;
- public:
- BOOST_STATIC_CONSTEXPR bool is_specialized = true;
- //
- // Largest and smallest numbers are bounded only by available memory, set
- // to zero:
- //
- static number_type (min)()
- {
- return number_type();
- }
- static number_type (max)()
- {
- return number_type();
- }
- static number_type lowest() { return (min)(); }
- BOOST_STATIC_CONSTEXPR int digits = INT_MAX;
- BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L;
- BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2;
- BOOST_STATIC_CONSTEXPR bool is_signed = true;
- BOOST_STATIC_CONSTEXPR bool is_integer = true;
- BOOST_STATIC_CONSTEXPR bool is_exact = true;
- BOOST_STATIC_CONSTEXPR int radix = 2;
- static number_type epsilon() { return number_type(); }
- static number_type round_error() { return number_type(); }
- BOOST_STATIC_CONSTEXPR int min_exponent = 0;
- BOOST_STATIC_CONSTEXPR int min_exponent10 = 0;
- BOOST_STATIC_CONSTEXPR int max_exponent = 0;
- BOOST_STATIC_CONSTEXPR int max_exponent10 = 0;
- BOOST_STATIC_CONSTEXPR bool has_infinity = false;
- BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false;
- BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
- BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
- BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
- static number_type infinity() { return number_type(); }
- static number_type quiet_NaN() { return number_type(); }
- static number_type signaling_NaN() { return number_type(); }
- static number_type denorm_min() { return number_type(); }
- BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
- BOOST_STATIC_CONSTEXPR bool is_bounded = false;
- BOOST_STATIC_CONSTEXPR bool is_modulo = false;
- BOOST_STATIC_CONSTEXPR bool traps = false;
- BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
- BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
- };
- #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_digits10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_signed;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_integer;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_exact;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::radix;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_infinity;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_quiet_NaN;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_signaling_NaN;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm_loss;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_iec559;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_bounded;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_modulo;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::traps;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::tinyness_before;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::round_style;
- #endif
- template<boost::multiprecision::expression_template_option ExpressionTemplates>
- class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >
- {
- typedef boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> number_type;
- public:
- BOOST_STATIC_CONSTEXPR bool is_specialized = true;
- //
- // Largest and smallest numbers are bounded only by available memory, set
- // to zero:
- //
- static number_type (min)()
- {
- return number_type();
- }
- static number_type (max)()
- {
- return number_type();
- }
- static number_type lowest() { return (min)(); }
- // Digits are unbounded, use zero for now:
- BOOST_STATIC_CONSTEXPR int digits = INT_MAX;
- BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L;
- BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2;
- BOOST_STATIC_CONSTEXPR bool is_signed = true;
- BOOST_STATIC_CONSTEXPR bool is_integer = false;
- BOOST_STATIC_CONSTEXPR bool is_exact = true;
- BOOST_STATIC_CONSTEXPR int radix = 2;
- static number_type epsilon() { return number_type(); }
- static number_type round_error() { return number_type(); }
- BOOST_STATIC_CONSTEXPR int min_exponent = 0;
- BOOST_STATIC_CONSTEXPR int min_exponent10 = 0;
- BOOST_STATIC_CONSTEXPR int max_exponent = 0;
- BOOST_STATIC_CONSTEXPR int max_exponent10 = 0;
- BOOST_STATIC_CONSTEXPR bool has_infinity = false;
- BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false;
- BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
- BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
- BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
- static number_type infinity() { return number_type(); }
- static number_type quiet_NaN() { return number_type(); }
- static number_type signaling_NaN() { return number_type(); }
- static number_type denorm_min() { return number_type(); }
- BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
- BOOST_STATIC_CONSTEXPR bool is_bounded = false;
- BOOST_STATIC_CONSTEXPR bool is_modulo = false;
- BOOST_STATIC_CONSTEXPR bool traps = false;
- BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
- BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
- };
- #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_digits10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_signed;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_integer;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_exact;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::radix;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent10;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_infinity;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_quiet_NaN;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_signaling_NaN;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm_loss;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_iec559;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_bounded;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_modulo;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::traps;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::tinyness_before;
- template <boost::multiprecision::expression_template_option ExpressionTemplates>
- BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::round_style;
- #endif
- #ifdef BOOST_MSVC
- #pragma warning(pop)
- #endif
- } // namespace std
- #endif
|