| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236 | /////////////////////////////////////////////////////////////////////////////////  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_EXTENDED_REAL_HPP#define BOOST_MATH_EXTENDED_REAL_HPP#include <boost/config.hpp>#include <boost/cstdint.hpp>#include <boost/mpl/max.hpp>#include <boost/mpl/plus.hpp>#include <boost/mpl/or.hpp>#include <boost/mpl/find_if.hpp>#include <boost/assert.hpp>#include <boost/type_traits/remove_pointer.hpp>#include <boost/type_traits/is_signed.hpp>#include <boost/type_traits/is_unsigned.hpp>#include <boost/type_traits/is_floating_point.hpp>#include <boost/type_traits/is_integral.hpp>#include <boost/type_traits/is_complex.hpp>#include <boost/type_traits/make_unsigned.hpp>#include <boost/type_traits/is_convertible.hpp>#include <boost/throw_exception.hpp>#include <boost/multiprecision/detail/precision.hpp>#include <boost/multiprecision/detail/generic_interconvert.hpp>#include <boost/multiprecision/detail/number_compare.hpp>#include <boost/multiprecision/traits/is_restricted_conversion.hpp>#include <boost/container_hash/hash.hpp>#include <istream> // stream operators#include <cstdio>  // EOF#include <cctype>  // isspace#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW#include <string_view>#endifnamespace boost {namespace multiprecision {#ifdef BOOST_MSVC// warning C4127: conditional expression is constant// warning C4714: function marked as __forceinline not inlined#pragma warning(push)#pragma warning(disable : 4127 4714 6326)#endiftemplate <class Backend, expression_template_option ExpressionTemplates>class number{   typedef number<Backend, ExpressionTemplates> self_type; public:   typedef Backend                                  backend_type;   typedef typename component_type<self_type>::type value_type;   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number() BOOST_MP_NOEXCEPT_IF(noexcept(Backend())) {}   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(e.m_backend) {}   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename boost::enable_if_c<                                               (boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value) && !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value#ifdef BOOST_HAS_FLOAT128                                               && !boost::is_same<V, __float128>::value#endif                                               >::type* = 0)   {      m_backend = canonical_value(v);   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<                                                               is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = 0)#ifndef BOOST_INTEL       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))#endif       : m_backend(canonical_value(v))   {}   template <class V>   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, unsigned digits10, typename boost::enable_if_c<(boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value) && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)#ifdef BOOST_HAS_FLOAT128                                                                                                          && !boost::is_same<V, __float128>::value#endif                                                                                                          >::type* = 0)       : m_backend(canonical_value(v), digits10)   {}   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e, unsigned digits10)       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend const&>(), std::declval<unsigned>())))       : m_backend(e.m_backend, digits10) {}   template <class V>   explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename boost::enable_if_c<                                                        (boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value) && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = 0)       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<typename detail::canonical<V, Backend>::type const&>()))   {      m_backend = canonical_value(v);   }   template <class V>   explicit BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<                                                                        detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value || !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)>::type* = 0)       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))       : m_backend(canonical_value(v)) {}   template <class V>   explicit BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, unsigned digits10, typename boost::enable_if_c<(boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value) && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)>::type* = 0)       : m_backend(canonical_value(v), digits10) {}   template <expression_template_option ET>   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number<Backend, ET>& val)       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(val.backend()) {}   template <class Other, expression_template_option ET>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val,                               typename boost::enable_if_c<(boost::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = 0)       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Other const&>())))       : m_backend(val.backend()) {}   template <class Other, expression_template_option ET>   explicit BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename boost::enable_if_c<                                                     (!detail::is_explicitly_convertible<Other, Backend>::value)>::type* = 0)   {      //      // Attempt a generic interconvertion:      //      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard_1(val);      detail::scoped_default_precision<number<Other, ET> >                    precision_guard_2(val);      using detail::generic_interconvert;      generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());   }   template <class Other, expression_template_option ET>   explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename boost::enable_if_c<                                                                          (detail::is_explicitly_convertible<Other, Backend>::value && (detail::is_restricted_conversion<Other, Backend>::value || !boost::is_convertible<Other, Backend>::value))>::type* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Other const&>())))       : m_backend(val.backend()) {}   template <class V, class U>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,                               typename boost::enable_if_c<(is_convertible<V, value_type>::value && is_convertible<U, value_type>::value && !is_same<typename component_type<self_type>::type, self_type>::value)>::type* = 0)   {      using default_ops::assign_components;      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);      assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));   }   template <class V, class U>   BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,                                        typename boost::enable_if_c<                                            (is_constructible<value_type, V>::value || is_convertible<V, std::string>::value) && (is_constructible<value_type, U>::value || is_convertible<U, std::string>::value) && !is_same<typename component_type<self_type>::type, self_type>::value && !is_same<V, self_type>::value && !(is_convertible<V, value_type>::value && is_convertible<U, value_type>::value)>::type* = 0)   {      using default_ops::assign_components;      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);      assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));   }#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW   //   // Support for new types in C++17   //   template <class Traits>   explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view)   {      using default_ops::assign_from_string_view;      assign_from_string_view(this->backend(), view);   }   template <class Traits>   explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& view_y)   {      using default_ops::assign_from_string_view;      assign_from_string_view(this->backend(), view_x, view_y);   }   template <class Traits>   explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& v, unsigned digits10)       : m_backend(canonical_value(v), digits10) {}   template <class Traits>   BOOST_MP_CXX14_CONSTEXPR number& assign(const std::basic_string_view<char, Traits>& view)   {      using default_ops::assign_from_string_view;      assign_from_string_view(this->backend(), view);      return *this;   }#endif   template <class V, class U>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,                               typename boost::enable_if_c<(is_convertible<V, value_type>::value && is_convertible<U, value_type>::value && !is_same<typename component_type<self_type>::type, self_type>::value)>::type* = 0)       : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10)   {}   template <class V, class U>   BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,                                        typename boost::enable_if_c<((is_constructible<value_type, V>::value || is_convertible<V, std::string>::value) && (is_constructible<value_type, U>::value || is_convertible<U, std::string>::value) && !is_same<typename component_type<self_type>::type, self_type>::value) && !(is_convertible<V, value_type>::value && is_convertible<U, value_type>::value)>::type* = 0)       : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10) {}   template <class Other, expression_template_option ET>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& v1, const number<Other, ET>& v2, typename boost::enable_if_c<boost::is_convertible<Other, Backend>::value>::type* = 0)   {      using default_ops::assign_components;      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);      assign_components(m_backend, v1.backend(), v2.backend());   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      typedef mpl::bool_<is_same<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value> tag_type;      detail::scoped_default_precision<number<Backend, ExpressionTemplates> >                                       precision_guard(e);      //      // If the current precision of *this differs from that of expression e, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t(e);         return *this = BOOST_MP_MOVE(t);      }      do_assign(e, tag_type());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      typedef mpl::bool_<is_same<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value> tag_type;      detail::scoped_default_precision<number<Backend, ExpressionTemplates> >                                       precision_guard(e);      //      // If the current precision of *this differs from that of expression e, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t;         t.assign(e);         return *this = BOOST_MP_MOVE(t);      }      do_assign(e, tag_type());      return *this;   }   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(const number& e)       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<Backend const&>()))   {      m_backend = e.m_backend;      return *this;   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type   operator=(const V& v)       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))   {      m_backend = canonical_value(v);      return *this;   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v)       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))   {      m_backend = canonical_value(v);      return *this;   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v, unsigned digits10)       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))   {      number t(v, digits10);      return *this = t;   }   template <class Other, expression_template_option ET>   BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if<boost::multiprecision::detail::is_explicitly_convertible<Other, Backend>, number<Backend, ExpressionTemplates>&>::type   assign(const number<Other, ET>& v)   {      //      // Attempt a generic interconvertion:      //      using detail::generic_interconvert;      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v);      detail::scoped_default_precision<number<Other, ET> >                    precision_guard2(v);      //      // If the current precision of *this differs from that of value v, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t(v);         return *this = BOOST_MP_MOVE(t);      }      generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)   {      //      // No preicsion guard here, we already have one in operator=      //      *this = e;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   explicit BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e,                   typename boost::enable_if_c<!is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)   {      //      // No precision guard as assign has one already:      //      assign(e);   }#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(number&& r)       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend>())))       : m_backend(static_cast<Backend&&>(r.m_backend))   {}   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(number&& r) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<Backend>()))   {      m_backend = static_cast<Backend&&>(r.m_backend);      return *this;   }#endif   BOOST_MP_CXX14_CONSTEXPR number& operator+=(const self_type& val)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);      //      // If the current precision of *this differs from that of expression e, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t(*this + val);         return *this = BOOST_MP_MOVE(t);      }      do_add(detail::expression<detail::terminal, self_type>(val), detail::terminal());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      // Create a copy if e contains this, but not if we're just doing a      //    x += x      if ((contains_self(e) && !is_self(e)))      {         self_type temp(e);         do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());      }      else      {         do_add(e, tag());      }      return *this;   }   template <class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR number& operator+=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      //      // If the current precision of *this differs from that of expression e, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t(*this + e);         return *this = BOOST_MP_MOVE(t);      }      //      // Fused multiply-add:      //      using default_ops::eval_multiply_add;      eval_multiply_add(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));      return *this;   }   template <class V>   typename boost::enable_if_c<boost::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type      BOOST_MP_CXX14_CONSTEXPR operator+=(const V& v)   {      using default_ops::eval_add;      eval_add(m_backend, canonical_value(v));      return *this;   }   BOOST_MP_CXX14_CONSTEXPR number& operator-=(const self_type& val)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);      //      // If the current precision of *this differs from that of expression e, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t(*this - val);         return *this = BOOST_MP_MOVE(t);      }      do_subtract(detail::expression<detail::terminal, self_type>(val), detail::terminal());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      // Create a copy if e contains this:      if (contains_self(e))      {         self_type temp(e);         do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());      }      else      {         do_subtract(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());      }      return *this;   }   template <class V>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type   operator-=(const V& v)   {      using default_ops::eval_subtract;      eval_subtract(m_backend, canonical_value(v));      return *this;   }   template <class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR number& operator-=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      //      // If the current precision of *this differs from that of expression e, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t(*this - e);         return *this = BOOST_MP_MOVE(t);      }      //      // Fused multiply-subtract:      //      using default_ops::eval_multiply_subtract;      eval_multiply_subtract(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));      return *this;   }   BOOST_MP_CXX14_CONSTEXPR number& operator*=(const self_type& e)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      //      // If the current precision of *this differs from that of expression e, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t(*this * e);         return *this = BOOST_MP_MOVE(t);      }      do_multiplies(detail::expression<detail::terminal, self_type>(e), detail::terminal());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      // Create a temporary if the RHS references *this, but not      // if we're just doing an   x *= x;      if ((contains_self(e) && !is_self(e)))      {         self_type temp(e);         do_multiplies(detail::expression<detail::terminal, self_type>(temp), detail::terminal());      }      else      {         do_multiplies(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());      }      return *this;   }   template <class V>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type   operator*=(const V& v)   {      using default_ops::eval_multiply;      eval_multiply(m_backend, canonical_value(v));      return *this;   }   BOOST_MP_CXX14_CONSTEXPR number& operator%=(const self_type& e)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      //      // If the current precision of *this differs from that of expression e, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t(*this % e);         return *this = BOOST_MP_MOVE(t);      }      do_modulus(detail::expression<detail::terminal, self_type>(e), detail::terminal());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      // Create a temporary if the RHS references *this:      if (contains_self(e))      {         self_type temp(e);         do_modulus(detail::expression<detail::terminal, self_type>(temp), detail::terminal());      }      else      {         do_modulus(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());      }      return *this;   }   template <class V>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type   operator%=(const V& v)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");      using default_ops::eval_modulus;      eval_modulus(m_backend, canonical_value(v));      return *this;   }   //   // These operators are *not* proto-ized.   // The issue is that the increment/decrement must happen   // even if the result of the operator *is never used*.   // Possibly we could modify our expression wrapper to   // execute the increment/decrement on destruction, but   // correct implementation will be tricky, so defered for now...   //   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator++()   {      using default_ops::eval_increment;      eval_increment(m_backend);      return *this;   }   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator--()   {      using default_ops::eval_decrement;      eval_decrement(m_backend);      return *this;   }   inline BOOST_MP_CXX14_CONSTEXPR number operator++(int)   {      using default_ops::eval_increment;      self_type temp(*this);      eval_increment(m_backend);      return temp;   }   inline BOOST_MP_CXX14_CONSTEXPR number operator--(int)   {      using default_ops::eval_decrement;      self_type temp(*this);      eval_decrement(m_backend);      return temp;   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_integral<V>::value, number&>::type operator<<=(V val)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left-shift operation is only valid for integer types");      detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), mpl::bool_<is_signed<V>::value>());      eval_left_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));      return *this;   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_integral<V>::value, number&>::type operator>>=(V val)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right-shift operation is only valid for integer types");      detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), mpl::bool_<is_signed<V>::value>());      eval_right_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));      return *this;   }   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator/=(const self_type& e)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      //      // If the current precision of *this differs from that of expression e, then we      // create a temporary (which will have the correct precision thanks to precision_guard)      // and then move the result into *this.  In C++17 we add a leading "if constexpr"      // which causes this code to be eliminated in the common case that this type is      // not actually variable precision.  Pre C++17 this code should still be mostly      // optimised away, but we can't prevent instantiation of the dead code leading      // to longer build and possibly link times.      //      BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)      if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))      {         number t(*this / e);         return *this = BOOST_MP_MOVE(t);      }      do_divide(detail::expression<detail::terminal, self_type>(e), detail::terminal());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);      // Create a temporary if the RHS references *this:      if (contains_self(e))      {         self_type temp(e);         do_divide(detail::expression<detail::terminal, self_type>(temp), detail::terminal());      }      else      {         do_divide(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());      }      return *this;   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type   operator/=(const V& v)   {      using default_ops::eval_divide;      eval_divide(m_backend, canonical_value(v));      return *this;   }   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator&=(const self_type& e)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");      do_bitwise_and(detail::expression<detail::terminal, self_type>(e), detail::terminal());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");      // Create a temporary if the RHS references *this, but not      // if we're just doing an   x &= x;      if (contains_self(e) && !is_self(e))      {         self_type temp(e);         do_bitwise_and(detail::expression<detail::terminal, self_type>(temp), detail::terminal());      }      else      {         do_bitwise_and(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());      }      return *this;   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type   operator&=(const V& v)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");      using default_ops::eval_bitwise_and;      eval_bitwise_and(m_backend, canonical_value(v));      return *this;   }   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator|=(const self_type& e)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");      do_bitwise_or(detail::expression<detail::terminal, self_type>(e), detail::terminal());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");      // Create a temporary if the RHS references *this, but not      // if we're just doing an   x |= x;      if (contains_self(e) && !is_self(e))      {         self_type temp(e);         do_bitwise_or(detail::expression<detail::terminal, self_type>(temp), detail::terminal());      }      else      {         do_bitwise_or(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());      }      return *this;   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type   operator|=(const V& v)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");      using default_ops::eval_bitwise_or;      eval_bitwise_or(m_backend, canonical_value(v));      return *this;   }   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator^=(const self_type& e)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");      do_bitwise_xor(detail::expression<detail::terminal, self_type>(e), detail::terminal());      return *this;   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");      if (contains_self(e))      {         self_type temp(e);         do_bitwise_xor(detail::expression<detail::terminal, self_type>(temp), detail::terminal());      }      else      {         do_bitwise_xor(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());      }      return *this;   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type   operator^=(const V& v)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");      using default_ops::eval_bitwise_xor;      eval_bitwise_xor(m_backend, canonical_value(v));      return *this;   }   //   // swap:   //   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(self_type& other) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend>().swap(std::declval<Backend&>())))   {      m_backend.swap(other.backend());   }   //   // Zero and sign:   //   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool is_zero() const   {      using default_ops::eval_is_zero;      return eval_is_zero(m_backend);   }   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int sign() const   {      using default_ops::eval_get_sign;      return eval_get_sign(m_backend);   }   //   // String conversion functions:   //   std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0)) const   {      return m_backend.str(digits, f);   }   template <class Archive>   void serialize(Archive& ar, const unsigned int /*version*/)   {      ar& boost::make_nvp("backend", m_backend);   } private:   template <class T>   BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(T* result) const   {      using default_ops::eval_convert_to;      eval_convert_to(result, m_backend);   }   template <class B2, expression_template_option ET>   BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(number<B2, ET>* result) const   {      result->assign(*this);   }   BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(std::string* result) const   {      *result = this->str();   } public:   template <class T>   BOOST_MP_CXX14_CONSTEXPR T convert_to() const   {      T result = T();      convert_to_imp(&result);      return result;   }   //   // Use in boolean context, and explicit conversion operators:   //#ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS#if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))   //   // Horrible workaround for gcc-4.6.x which always prefers the template   // operator bool() rather than the non-template operator when converting to   // an arithmetic type:   //   template <class T, typename boost::enable_if_c<is_same<T, bool>::value, int>::type = 0>   explicit operator T() const   {      using default_ops::eval_is_zero;      return !eval_is_zero(backend());   }   template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value, int>::type = 0>   explicit operator T() const   {      return this->template convert_to<T>();   }#else#if BOOST_WORKAROUND(BOOST_MSVC, < 1900) || (defined(__apple_build_version__) && BOOST_WORKAROUND(__clang_major__, < 9))   template <class T>#else   template <class T, class = typename boost::disable_if_c<boost::is_constructible<T, self_type const&>::value || !boost::is_default_constructible<T>::value || (!boost::is_arithmetic<T>::value && !boost::is_complex<T>::value), T>::type>#endif   explicit BOOST_MP_CXX14_CONSTEXPR operator T() const   {      return this->template convert_to<T>();   }   BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const   {      return !is_zero();   }#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)   BOOST_MP_FORCEINLINE explicit operator void() const   {}#endif#endif#else   typedef bool (self_type::*unmentionable_type)() const;   BOOST_MP_FORCEINLINE operator unmentionable_type() const   {      return is_zero() ? 0 : &self_type::is_zero;   }#endif   //   // Default precision:   //   static BOOST_MP_CXX14_CONSTEXPR unsigned default_precision() BOOST_NOEXCEPT   {      return Backend::default_precision();   }   static BOOST_MP_CXX14_CONSTEXPR void default_precision(unsigned digits10)   {      Backend::default_precision(digits10);   }   BOOST_MP_CXX14_CONSTEXPR unsigned precision() const BOOST_NOEXCEPT   {      return m_backend.precision();   }   BOOST_MP_CXX14_CONSTEXPR void precision(unsigned digits10)   {      m_backend.precision(digits10);   }   //   // Comparison:   //   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int compare(const number<Backend, ExpressionTemplates>& o) const       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend>().compare(std::declval<Backend>())))   {      return m_backend.compare(o.m_backend);   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_arithmetic<V>::value && (number_category<Backend>::value != number_kind_complex), int>::type compare(const V& o) const   {      using default_ops::eval_get_sign;      if (o == 0)         return eval_get_sign(m_backend);      return m_backend.compare(canonical_value(o));   }   template <class V>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<is_arithmetic<V>::value && (number_category<Backend>::value == number_kind_complex), int>::type compare(const V& o) const   {      using default_ops::eval_get_sign;      return m_backend.compare(canonical_value(o));   }   //   // Direct access to the underlying backend:   //#if !(defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_REF_QUALIFIERS) || BOOST_WORKAROUND(BOOST_GCC, < 50000))   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend& backend() & BOOST_NOEXCEPT   {      return m_backend;   }   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& backend() const& BOOST_NOEXCEPT { return m_backend; }   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend&& backend() && BOOST_NOEXCEPT { return static_cast<Backend&&>(m_backend); }   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend const&& backend() const&& BOOST_NOEXCEPT { return static_cast<Backend const&&>(m_backend); }#else   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend& backend() BOOST_NOEXCEPT   {      return m_backend;   }   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& backend() const BOOST_NOEXCEPT { return m_backend; }#endif   //   // Complex number real and imag:   //   BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type   real() const   {      using default_ops::eval_real;      detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);      typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type                                   result;      eval_real(result.backend(), backend());      return result;   }   BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type   imag() const   {      using default_ops::eval_imag;      detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);      typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type                                   result;      eval_imag(result.backend(), backend());      return result;   }   template <class T>   inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_convertible<T, self_type>::value, self_type&>::type real(const T& val)   {      using default_ops::eval_set_real;      eval_set_real(backend(), canonical_value(val));      return *this;   }   template <class T>   inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_convertible<T, self_type>::value && number_category<self_type>::value == number_kind_complex, self_type&>::type imag(const T& val)   {      using default_ops::eval_set_imag;      eval_set_imag(backend(), canonical_value(val));      return *this;   } private:   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const mpl::true_&)   {      do_assign(e, tag());   }   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const mpl::false_&)   {      // The result of the expression isn't the same type as this -      // create a temporary result and assign it to *this:      typedef typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type temp_type;      temp_type                                                                     t(e);      this->assign(t);   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::add_immediates&)   {      using default_ops::eval_add;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_add(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::subtract_immediates&)   {      using default_ops::eval_subtract;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_immediates&)   {      using default_ops::eval_multiply;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_multiply(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_add&)   {      using default_ops::eval_multiply_add;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_multiply_add(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_subtract&)   {      using default_ops::eval_multiply_subtract;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_multiply_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divide_immediates&)   {      using default_ops::eval_divide;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_divide(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::negate&)   {      typedef typename Exp::left_type left_type;      do_assign(e.left(), typename left_type::tag_type());      m_backend.negate();   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::plus&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      BOOST_CONSTEXPR int const left_depth  = left_type::depth;      BOOST_CONSTEXPR int const right_depth = right_type::depth;      bool bl = contains_self(e.left());      bool br = contains_self(e.right());      if (bl && br)      {         self_type temp(e);         temp.m_backend.swap(this->m_backend);      }      else if (bl && is_self(e.left()))      {         // Ignore the left node, it's *this, just add the right:         do_add(e.right(), typename right_type::tag_type());      }      else if (br && is_self(e.right()))      {         // Ignore the right node, it's *this, just add the left:         do_add(e.left(), typename left_type::tag_type());      }      else if (!br && (bl || (left_depth >= right_depth)))      { // br is always false, but if bl is true we must take the this branch:         do_assign(e.left(), typename left_type::tag_type());         do_add(e.right(), typename right_type::tag_type());      }      else      {         do_assign(e.right(), typename right_type::tag_type());         do_add(e.left(), typename left_type::tag_type());      }   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::minus&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      BOOST_CONSTEXPR int const left_depth  = left_type::depth;      BOOST_CONSTEXPR int const right_depth = right_type::depth;      bool bl = contains_self(e.left());      bool br = contains_self(e.right());      if (bl && br)      {         self_type temp(e);         temp.m_backend.swap(this->m_backend);      }      else if (bl && is_self(e.left()))      {         // Ignore the left node, it's *this, just subtract the right:         do_subtract(e.right(), typename right_type::tag_type());      }      else if (br && is_self(e.right()))      {         // Ignore the right node, it's *this, just subtract the left and negate the result:         do_subtract(e.left(), typename left_type::tag_type());         m_backend.negate();      }      else if (!br && (bl || (left_depth >= right_depth)))      { // br is always false, but if bl is true we must take the this branch:         do_assign(e.left(), typename left_type::tag_type());         do_subtract(e.right(), typename right_type::tag_type());      }      else      {         do_assign(e.right(), typename right_type::tag_type());         do_subtract(e.left(), typename left_type::tag_type());         m_backend.negate();      }   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiplies&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      BOOST_CONSTEXPR int const left_depth  = left_type::depth;      BOOST_CONSTEXPR int const right_depth = right_type::depth;      bool bl = contains_self(e.left());      bool br = contains_self(e.right());      if (bl && br)      {         self_type temp(e);         temp.m_backend.swap(this->m_backend);      }      else if (bl && is_self(e.left()))      {         // Ignore the left node, it's *this, just add the right:         do_multiplies(e.right(), typename right_type::tag_type());      }      else if (br && is_self(e.right()))      {         // Ignore the right node, it's *this, just add the left:         do_multiplies(e.left(), typename left_type::tag_type());      }      else if (!br && (bl || (left_depth >= right_depth)))      { // br is always false, but if bl is true we must take the this branch:         do_assign(e.left(), typename left_type::tag_type());         do_multiplies(e.right(), typename right_type::tag_type());      }      else      {         do_assign(e.right(), typename right_type::tag_type());         do_multiplies(e.left(), typename left_type::tag_type());      }   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divides&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      bool bl = contains_self(e.left());      bool br = contains_self(e.right());      if (bl && is_self(e.left()))      {         // Ignore the left node, it's *this, just add the right:         do_divide(e.right(), typename right_type::tag_type());      }      else if (br)      {         self_type temp(e);         temp.m_backend.swap(this->m_backend);      }      else      {         do_assign(e.left(), typename left_type::tag_type());         do_divide(e.right(), typename right_type::tag_type());      }   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus&)   {      //      // This operation is only valid for integer backends:      //      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      bool bl = contains_self(e.left());      bool br = contains_self(e.right());      if (bl && is_self(e.left()))      {         // Ignore the left node, it's *this, just add the right:         do_modulus(e.right(), typename right_type::tag_type());      }      else if (br)      {         self_type temp(e);         temp.m_backend.swap(this->m_backend);      }      else      {         do_assign(e.left(), typename left_type::tag_type());         do_modulus(e.right(), typename right_type::tag_type());      }   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus_immediates&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");      using default_ops::eval_modulus;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_modulus(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and&)   {      //      // This operation is only valid for integer backends:      //      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      BOOST_CONSTEXPR int const left_depth  = left_type::depth;      BOOST_CONSTEXPR int const right_depth = right_type::depth;      bool bl = contains_self(e.left());      bool br = contains_self(e.right());      if (bl && is_self(e.left()))      {         // Ignore the left node, it's *this, just add the right:         do_bitwise_and(e.right(), typename right_type::tag_type());      }      else if (br && is_self(e.right()))      {         do_bitwise_and(e.left(), typename left_type::tag_type());      }      else if (!br && (bl || (left_depth >= right_depth)))      {         do_assign(e.left(), typename left_type::tag_type());         do_bitwise_and(e.right(), typename right_type::tag_type());      }      else      {         do_assign(e.right(), typename right_type::tag_type());         do_bitwise_and(e.left(), typename left_type::tag_type());      }   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and_immediates&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");      using default_ops::eval_bitwise_and;      eval_bitwise_and(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or&)   {      //      // This operation is only valid for integer backends:      //      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      BOOST_CONSTEXPR int const left_depth  = left_type::depth;      BOOST_CONSTEXPR int const right_depth = right_type::depth;      bool bl = contains_self(e.left());      bool br = contains_self(e.right());      if (bl && is_self(e.left()))      {         // Ignore the left node, it's *this, just add the right:         do_bitwise_or(e.right(), typename right_type::tag_type());      }      else if (br && is_self(e.right()))      {         do_bitwise_or(e.left(), typename left_type::tag_type());      }      else if (!br && (bl || (left_depth >= right_depth)))      {         do_assign(e.left(), typename left_type::tag_type());         do_bitwise_or(e.right(), typename right_type::tag_type());      }      else      {         do_assign(e.right(), typename right_type::tag_type());         do_bitwise_or(e.left(), typename left_type::tag_type());      }   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or_immediates&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");      using default_ops::eval_bitwise_or;      eval_bitwise_or(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor&)   {      //      // This operation is only valid for integer backends:      //      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      BOOST_CONSTEXPR int const left_depth  = left_type::depth;      BOOST_CONSTEXPR int const right_depth = right_type::depth;      bool bl = contains_self(e.left());      bool br = contains_self(e.right());      if (bl && is_self(e.left()))      {         // Ignore the left node, it's *this, just add the right:         do_bitwise_xor(e.right(), typename right_type::tag_type());      }      else if (br && is_self(e.right()))      {         do_bitwise_xor(e.left(), typename left_type::tag_type());      }      else if (!br && (bl || (left_depth >= right_depth)))      {         do_assign(e.left(), typename left_type::tag_type());         do_bitwise_xor(e.right(), typename right_type::tag_type());      }      else      {         do_assign(e.right(), typename right_type::tag_type());         do_bitwise_xor(e.left(), typename left_type::tag_type());      }   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");      using default_ops::eval_bitwise_xor;      eval_bitwise_xor(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::terminal&)   {      if (!is_self(e))      {         m_backend = canonical_value(e.value());      }   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::function&)   {      typedef typename Exp::arity tag_type;      boost::multiprecision::detail::maybe_promote_precision(this);      do_assign_function(e, tag_type());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_left&)   {      // We can only shift by an integer value, not an arbitrary expression:      typedef typename Exp::left_type    left_type;      typedef typename Exp::right_type   right_type;      typedef typename right_type::arity right_arity;      BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");      typedef typename right_type::result_type right_value_type;      BOOST_STATIC_ASSERT_MSG(is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");      typedef typename left_type::tag_type tag_type;      do_assign_left_shift(e.left(), canonical_value(e.right().value()), tag_type());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_right&)   {      // We can only shift by an integer value, not an arbitrary expression:      typedef typename Exp::left_type    left_type;      typedef typename Exp::right_type   right_type;      typedef typename right_type::arity right_arity;      BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");      typedef typename right_type::result_type right_value_type;      BOOST_STATIC_ASSERT_MSG(is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");      typedef typename left_type::tag_type tag_type;      do_assign_right_shift(e.left(), canonical_value(e.right().value()), tag_type());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_complement&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");      using default_ops::eval_complement;      self_type temp(e.left());      eval_complement(m_backend, temp.backend());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::complement_immediates&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");      using default_ops::eval_complement;      eval_complement(m_backend, canonical_value(e.left().value()));   }   template <class Exp, class Val>   BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");      using default_ops::eval_right_shift;      detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), mpl::bool_<is_signed<Val>::value>());      eval_right_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));   }   template <class Exp, class Val>   BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");      using default_ops::eval_left_shift;      detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), mpl::bool_<is_signed<Val>::value>());      eval_left_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));   }   template <class Exp, class Val, class Tag>   BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const Tag&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");      using default_ops::eval_right_shift;      self_type temp(e);      detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), mpl::bool_<is_signed<Val>::value>());      eval_right_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));   }   template <class Exp, class Val, class Tag>   BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const Tag&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");      using default_ops::eval_left_shift;      self_type temp(e);      detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), mpl::bool_<is_signed<Val>::value>());      eval_left_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const mpl::int_<1>&)   {      e.left().value()(&m_backend);   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const mpl::int_<2>&)   {      typedef typename Exp::right_type      right_type;      typedef typename right_type::tag_type tag_type;      do_assign_function_1(e.left().value(), e.right_ref(), tag_type());   }   template <class F, class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&)   {      f(m_backend, function_arg_value(val));   }   template <class F, class Exp, class Tag>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const Tag&)   {      typename Exp::result_type t(val);      f(m_backend, t.backend());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const mpl::int_<3>&)   {      typedef typename Exp::middle_type      middle_type;      typedef typename middle_type::tag_type tag_type;      typedef typename Exp::right_type       end_type;      typedef typename end_type::tag_type    end_tag;      do_assign_function_2(e.left().value(), e.middle_ref(), e.right_ref(), tag_type(), end_tag());   }   template <class F, class Exp1, class Exp2>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const detail::terminal&)   {      f(m_backend, function_arg_value(val1), function_arg_value(val2));   }   template <class F, class Exp1, class Exp2, class Tag1>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const detail::terminal&)   {      typename Exp1::result_type temp1(val1);      f(m_backend, BOOST_MP_MOVE(temp1.backend()), function_arg_value(val2));   }   template <class F, class Exp1, class Exp2, class Tag2>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const Tag2&)   {      typename Exp2::result_type temp2(val2);      f(m_backend, function_arg_value(val1), BOOST_MP_MOVE(temp2.backend()));   }   template <class F, class Exp1, class Exp2, class Tag1, class Tag2>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const Tag2&)   {      typename Exp1::result_type temp1(val1);      typename Exp2::result_type temp2(val2);      f(m_backend, BOOST_MP_MOVE(temp1.backend()), BOOST_MP_MOVE(temp2.backend()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const mpl::int_<4>&)   {      typedef typename Exp::left_middle_type  left_type;      typedef typename left_type::tag_type    left_tag_type;      typedef typename Exp::right_middle_type middle_type;      typedef typename middle_type::tag_type  middle_tag_type;      typedef typename Exp::right_type        right_type;      typedef typename right_type::tag_type   right_tag_type;      do_assign_function_3a(e.left().value(), e.left_middle_ref(), e.right_middle_ref(), e.right_ref(), left_tag_type(), middle_tag_type(), right_tag_type());   }   template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag2& t2, const Tag3& t3)   {      do_assign_function_3b(f, val1, val2, val3, t2, t3);   }   template <class F, class Exp1, class Exp2, class Exp3, class Tag1, class Tag2, class Tag3>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag1&, const Tag2& t2, const Tag3& t3)   {      typename Exp1::result_type t(val1);      do_assign_function_3b(f, BOOST_MP_MOVE(t), val2, val3, t2, t3);   }   template <class F, class Exp1, class Exp2, class Exp3, class Tag3>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag3& t3)   {      do_assign_function_3c(f, val1, val2, val3, t3);   }   template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& /*t2*/, const Tag3& t3)   {      typename Exp2::result_type t(val2);      do_assign_function_3c(f, val1, BOOST_MP_MOVE(t), val3, t3);   }   template <class F, class Exp1, class Exp2, class Exp3>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&)   {      f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3));   }   template <class F, class Exp1, class Exp2, class Exp3, class Tag3>   BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& /*t3*/)   {      typename Exp3::result_type t(val3);      do_assign_function_3c(f, val1, val2, BOOST_MP_MOVE(t), detail::terminal());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::terminal&)   {      using default_ops::eval_add;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_add(m_backend, canonical_value(e.value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::negate&)   {      typedef typename Exp::left_type left_type;      boost::multiprecision::detail::maybe_promote_precision(this);      do_subtract(e.left(), typename left_type::tag_type());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::plus&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_add(e.left(), typename left_type::tag_type());      do_add(e.right(), typename right_type::tag_type());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::minus&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_add(e.left(), typename left_type::tag_type());      do_subtract(e.right(), typename right_type::tag_type());   }   template <class Exp, class unknown>   BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const unknown&)   {      self_type temp(e);      do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::add_immediates&)   {      using default_ops::eval_add;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_add(m_backend, canonical_value(e.left().value()));      eval_add(m_backend, canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::subtract_immediates&)   {      using default_ops::eval_add;      using default_ops::eval_subtract;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_add(m_backend, canonical_value(e.left().value()));      eval_subtract(m_backend, canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::terminal&)   {      using default_ops::eval_subtract;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_subtract(m_backend, canonical_value(e.value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::negate&)   {      typedef typename Exp::left_type left_type;      do_add(e.left(), typename left_type::tag_type());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::plus&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_subtract(e.left(), typename left_type::tag_type());      do_subtract(e.right(), typename right_type::tag_type());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::minus&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_subtract(e.left(), typename left_type::tag_type());      do_add(e.right(), typename right_type::tag_type());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::add_immediates&)   {      using default_ops::eval_subtract;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_subtract(m_backend, canonical_value(e.left().value()));      eval_subtract(m_backend, canonical_value(e.right().value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::subtract_immediates&)   {      using default_ops::eval_add;      using default_ops::eval_subtract;      eval_subtract(m_backend, canonical_value(e.left().value()));      eval_add(m_backend, canonical_value(e.right().value()));   }   template <class Exp, class unknown>   BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const unknown&)   {      self_type temp(e);      do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::terminal&)   {      using default_ops::eval_multiply;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_multiply(m_backend, canonical_value(e.value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::negate&)   {      typedef typename Exp::left_type left_type;      do_multiplies(e.left(), typename left_type::tag_type());      m_backend.negate();   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiplies&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_multiplies(e.left(), typename left_type::tag_type());      do_multiplies(e.right(), typename right_type::tag_type());   }   //   // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make   // the disable_if dependent on the template argument (the size of 1 can never occur in practice).   //   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type   do_multiplies(const Exp& e, const detail::divides&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_multiplies(e.left(), typename left_type::tag_type());      do_divide(e.right(), typename right_type::tag_type());   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiply_immediates&)   {      using default_ops::eval_multiply;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_multiply(m_backend, canonical_value(e.left().value()));      eval_multiply(m_backend, canonical_value(e.right().value()));   }   //   // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make   // the disable_if dependent on the template argument (the size of 1 can never occur in practice).   //   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type   do_multiplies(const Exp& e, const detail::divide_immediates&)   {      using default_ops::eval_divide;      using default_ops::eval_multiply;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_multiply(m_backend, canonical_value(e.left().value()));      eval_divide(m_backend, canonical_value(e.right().value()));   }   template <class Exp, class unknown>   BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const unknown&)   {      using default_ops::eval_multiply;      boost::multiprecision::detail::maybe_promote_precision(this);      self_type temp(e);      eval_multiply(m_backend, temp.m_backend);   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::terminal&)   {      using default_ops::eval_divide;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_divide(m_backend, canonical_value(e.value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::negate&)   {      typedef typename Exp::left_type left_type;      do_divide(e.left(), typename left_type::tag_type());      m_backend.negate();   }   //   // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make   // the disable_if dependent on the template argument (the size of 1 can never occur in practice).   //   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type   do_divide(const Exp& e, const detail::multiplies&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_divide(e.left(), typename left_type::tag_type());      do_divide(e.right(), typename right_type::tag_type());   }   //   // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make   // the disable_if dependent on the template argument (the size of 1 can never occur in practice).   //   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type   do_divide(const Exp& e, const detail::divides&)   {      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_divide(e.left(), typename left_type::tag_type());      do_multiplies(e.right(), typename right_type::tag_type());   }   //   // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make   // the disable_if dependent on the template argument (the size of 1 can never occur in practice).   //   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type   do_divides(const Exp& e, const detail::multiply_immediates&)   {      using default_ops::eval_divide;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_divide(m_backend, canonical_value(e.left().value()));      eval_divide(m_backend, canonical_value(e.right().value()));   }   //   // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make   // the disable_if dependent on the template argument (the size of 1 can never occur in practice).   //   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type   do_divides(const Exp& e, const detail::divide_immediates&)   {      using default_ops::eval_divide;      using default_ops::eval_multiply;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_divide(m_backend, canonical_value(e.left().value()));      mutiply(m_backend, canonical_value(e.right().value()));   }   template <class Exp, class unknown>   BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const unknown&)   {      using default_ops::eval_multiply;      boost::multiprecision::detail::maybe_promote_precision(this);      self_type temp(e);      eval_divide(m_backend, temp.m_backend);   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const detail::terminal&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");      using default_ops::eval_modulus;      boost::multiprecision::detail::maybe_promote_precision(this);      eval_modulus(m_backend, canonical_value(e.value()));   }   template <class Exp, class Unknown>   BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const Unknown&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");      using default_ops::eval_modulus;      boost::multiprecision::detail::maybe_promote_precision(this);      self_type temp(e);      eval_modulus(m_backend, canonical_value(temp));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::terminal&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");      using default_ops::eval_bitwise_and;      eval_bitwise_and(m_backend, canonical_value(e.value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::bitwise_and&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_bitwise_and(e.left(), typename left_type::tag_type());      do_bitwise_and(e.right(), typename right_type::tag_type());   }   template <class Exp, class unknown>   BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const unknown&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");      using default_ops::eval_bitwise_and;      self_type temp(e);      eval_bitwise_and(m_backend, temp.m_backend);   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::terminal&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");      using default_ops::eval_bitwise_or;      eval_bitwise_or(m_backend, canonical_value(e.value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::bitwise_or&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_bitwise_or(e.left(), typename left_type::tag_type());      do_bitwise_or(e.right(), typename right_type::tag_type());   }   template <class Exp, class unknown>   BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const unknown&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");      using default_ops::eval_bitwise_or;      self_type temp(e);      eval_bitwise_or(m_backend, temp.m_backend);   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::terminal&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");      using default_ops::eval_bitwise_xor;      eval_bitwise_xor(m_backend, canonical_value(e.value()));   }   template <class Exp>   BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");      typedef typename Exp::left_type  left_type;      typedef typename Exp::right_type right_type;      do_bitwise_xor(e.left(), typename left_type::tag_type());      do_bitwise_xor(e.right(), typename right_type::tag_type());   }   template <class Exp, class unknown>   BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const unknown&)   {      BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");      using default_ops::eval_bitwise_xor;      self_type temp(e);      eval_bitwise_xor(m_backend, temp.m_backend);   }   // Tests if the expression contains a reference to *this:   template <class Exp>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e) const BOOST_NOEXCEPT   {      return contains_self(e, typename Exp::arity());   }   template <class Exp>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, mpl::int_<0> const&) const BOOST_NOEXCEPT   {      return is_realy_self(e.value());   }   template <class Exp>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, mpl::int_<1> const&) const BOOST_NOEXCEPT   {      typedef typename Exp::left_type child_type;      return contains_self(e.left(), typename child_type::arity());   }   template <class Exp>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, mpl::int_<2> const&) const BOOST_NOEXCEPT   {      typedef typename Exp::left_type  child0_type;      typedef typename Exp::right_type child1_type;      return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.right(), typename child1_type::arity());   }   template <class Exp>   BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, mpl::int_<3> const&) const BOOST_NOEXCEPT   {      typedef typename Exp::left_type   child0_type;      typedef typename Exp::middle_type child1_type;      typedef typename Exp::right_type  child2_type;      return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.middle(), typename child1_type::arity()) || contains_self(e.right(), typename child2_type::arity());   }   // Test if the expression is a reference to *this:   template <class Exp>   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e) const BOOST_NOEXCEPT   {      return is_self(e, typename Exp::arity());   }   template <class Exp>   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e, mpl::int_<0> const&) const BOOST_NOEXCEPT   {      return is_realy_self(e.value());   }   template <class Exp, int v>   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp&, mpl::int_<v> const&) const BOOST_NOEXCEPT   {      return false;   }   template <class Val>   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const Val&) const BOOST_NOEXCEPT { return false; }   BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const self_type& v) const BOOST_NOEXCEPT { return &v == this; }   static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT { return v.backend(); }   template <class Other, expression_template_option ET2>   static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Other& function_arg_value(const number<Other, ET2>& v) BOOST_NOEXCEPT { return v.backend(); }   template <class V>   static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const V& function_arg_value(const V& v) BOOST_NOEXCEPT { return v; }   template <class A1, class A2, class A3, class A4>   static BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value(); }   template <class A2, class A3, class A4>   static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value().backend(); }   Backend                                                    m_backend; public:   //   // These shouldn't really need to be public, or even member functions, but it makes implementing   // the non-member operators way easier if they are:   //   static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& canonical_value(const self_type& v) BOOST_NOEXCEPT { return v.m_backend; }   template <class B2, expression_template_option ET>   static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const B2& canonical_value(const number<B2, ET>& v) BOOST_NOEXCEPT { return v.backend(); }   template <class V>   static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR typename boost::disable_if<is_same<typename detail::canonical<V, Backend>::type, V>, typename detail::canonical<V, Backend>::type>::type   canonical_value(const V& v) BOOST_NOEXCEPT { return static_cast<typename detail::canonical<V, Backend>::type>(v); }   template <class V>   static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR typename boost::enable_if_c<is_same<typename detail::canonical<V, Backend>::type, V>::value, const V&>::type   canonical_value(const V& v) BOOST_NOEXCEPT { return v; }   static BOOST_MP_FORCEINLINE typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v) BOOST_NOEXCEPT { return v.c_str(); }};template <class Backend, expression_template_option ExpressionTemplates>inline std::ostream& operator<<(std::ostream& os, const number<Backend, ExpressionTemplates>& r){   std::streamsize d  = os.precision();   std::string     s  = r.str(d, os.flags());   std::streamsize ss = os.width();   if (ss > static_cast<std::streamsize>(s.size()))   {      char fill = os.fill();      if ((os.flags() & std::ios_base::left) == std::ios_base::left)         s.append(static_cast<std::string::size_type>(ss - s.size()), fill);      else         s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - s.size()), fill);   }   return os << s;}namespace detail {template <class tag, class A1, class A2, class A3, class A4>inline std::ostream& operator<<(std::ostream& os, const expression<tag, A1, A2, A3, A4>& r){   typedef typename expression<tag, A1, A2, A3, A4>::result_type value_type;   value_type                                                    temp(r);   return os << temp;}//// What follows is the input streaming code: this is not "proper" iostream code at all// but that's fiendishly hard to write when dealing with multiple backends all// with different requirements... yes we could deligate this to the backend author...// but we really want backends to be EASY to write!// For now just pull in all the characters that could possibly form the number// and let the backend's string parser make use of it.  This fixes most use cases// including CSV type formats such as those used by the Random lib.//inline std::string read_string_while(std::istream& is, std::string const& permitted_chars){   std::ios_base::iostate     state = std::ios_base::goodbit;   const std::istream::sentry sentry_check(is);   std::string                result;   if (sentry_check)   {      int c = is.rdbuf()->sgetc();      for (;; c = is.rdbuf()->snextc())         if (std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))         { // end of file:            state |= std::ios_base::eofbit;            break;         }         else if (permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)         {            // Invalid numeric character, stop reading:            //is.rdbuf()->sputbackc(static_cast<char>(c));            break;         }         else         {            result.append(1, std::istream::traits_type::to_char_type(c));         }   }   if (!result.size())      state |= std::ios_base::failbit;   is.setstate(state);   return result;}} // namespace detailtemplate <class Backend, expression_template_option ExpressionTemplates>inline std::istream& operator>>(std::istream& is, number<Backend, ExpressionTemplates>& r){   bool        hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;   bool        oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;   std::string s;   switch (boost::multiprecision::number_category<number<Backend, ExpressionTemplates> >::value)   {   case boost::multiprecision::number_kind_integer:      if (oct_format)         s = detail::read_string_while(is, "+-01234567");      else if (hex_format)         s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789");      else         s = detail::read_string_while(is, "+-0123456789");      break;   case boost::multiprecision::number_kind_floating_point:      s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");      break;   default:      is >> s;   }   if (s.size())   {      if (hex_format && (number_category<Backend>::value == number_kind_integer) && ((s[0] != '0') || (s[1] != 'x')))         s.insert(s.find_first_not_of("+-"), "0x");      if (oct_format && (number_category<Backend>::value == number_kind_integer) && (s[0] != '0'))         s.insert(s.find_first_not_of("+-"), "0");      r.assign(s);   }   else if (!is.fail())      is.setstate(std::istream::failbit);   return is;}template <class Backend, expression_template_option ExpressionTemplates>BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b)    BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<number<Backend, ExpressionTemplates>&>() = std::declval<number<Backend, ExpressionTemplates>&>())){   a.swap(b);}//// Boost.Hash support, just call hash_value for the backend, which may or may not be supported://template <class Backend, expression_template_option ExpressionTemplates>inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const number<Backend, ExpressionTemplates>& val){   return hash_value(val.backend());}} // namespace multiprecisiontemplate <class T>class rational;template <class Backend, multiprecision::expression_template_option ExpressionTemplates>inline std::istream& operator>>(std::istream& is, rational<multiprecision::number<Backend, ExpressionTemplates> >& r){   std::string                                          s1;   multiprecision::number<Backend, ExpressionTemplates> v1, v2;   char                                                 c;   bool                                                 have_hex   = false;   bool                                                 hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;   bool                                                 oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;   while ((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))   {      if (c == 'x' || c == 'X')         have_hex = true;      s1.append(1, c);      is.get();   }   if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))      s1.insert(static_cast<std::string::size_type>(0), "0x");   if (oct_format && (s1[0] != '0'))      s1.insert(static_cast<std::string::size_type>(0), "0");   v1.assign(s1);   s1.erase();   if (c == '/')   {      is.get();      while ((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))      {         if (c == 'x' || c == 'X')            have_hex = true;         s1.append(1, c);         is.get();      }      if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))         s1.insert(static_cast<std::string::size_type>(0), "0x");      if (oct_format && (s1[0] != '0'))         s1.insert(static_cast<std::string::size_type>(0), "0");      v2.assign(s1);   }   else      v2 = 1;   r.assign(v1, v2);   return is;}template <class T, multiprecision::expression_template_option ExpressionTemplates>inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a){   return a.numerator();}template <class T, multiprecision::expression_template_option ExpressionTemplates>inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> denominator(const rational<multiprecision::number<T, ExpressionTemplates> >& a){   return a.denominator();}template <class T, multiprecision::expression_template_option ExpressionTemplates>inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const rational<multiprecision::number<T, ExpressionTemplates> >& val){   std::size_t result = hash_value(val.numerator());   boost::hash_combine(result, hash_value(val.denominator()));   return result;}namespace multiprecision {template <class I>struct component_type<boost::rational<I> >{   typedef I type;};} // namespace multiprecision#ifdef BOOST_MSVC#pragma warning(pop)#endif} // namespace boost#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL#include <functional>namespace std {template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>struct hash<boost::multiprecision::number<Backend, ExpressionTemplates> >{   BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::multiprecision::number<Backend, ExpressionTemplates>& val) const { return hash_value(val); }};template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>struct hash<boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> > >{   BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> >& val) const   {      std::size_t result = hash_value(val.numerator());      boost::hash_combine(result, hash_value(val.denominator()));      return result;   }};} // namespace std#endif#include <boost/multiprecision/detail/ublas_interop.hpp>#endif
 |