Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-01 08:19:08

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // Copyright Christopher Kormanyos 2014.
0003 // Copyright John Maddock 2014.
0004 // Copyright Paul Bristow 2014.
0005 // Distributed under the Boost Software License,
0006 // Version 1.0. (See accompanying file LICENSE_1_0.txt
0007 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 
0010 // Implement quadruple-precision I/O stream operations.
0011 
0012 #ifndef BOOST_MATH_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
0013   #define BOOST_MATH_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
0014 
0015   #include <boost/math/cstdfloat/cstdfloat_types.hpp>
0016   #include <boost/math/cstdfloat/cstdfloat_limits.hpp>
0017   #include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
0018 
0019   #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
0020   #error You can not use <boost/math/cstdfloat/cstdfloat_iostream.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
0021   #endif
0022 
0023   #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
0024 
0025   #include <cstddef>
0026   #include <istream>
0027   #include <ostream>
0028   #include <sstream>
0029   #include <stdexcept>
0030   #include <string>
0031   #include <boost/math/tools/assert.hpp>
0032   #include <boost/math/tools/nothrow.hpp>
0033   #include <boost/math/tools/throw_exception.hpp>
0034 
0035 namespace boost {
0036    namespace math {
0037       namespace detail {
0038          //
0039          // What follows is the input streaming code: this is not "proper" iostream code at all
0040          // but that's hard to write.
0041          // For now just pull in all the characters that could possibly form the number
0042          // and let libquadmath's string parser make use of it.  This fixes most use cases
0043          // including CSV type formats such as those used by the Random lib.
0044          //
0045          inline std::string read_string_while(std::istream& is, std::string const& permitted_chars)
0046          {
0047             std::ios_base::iostate     state = std::ios_base::goodbit;
0048             const std::istream::sentry sentry_check(is);
0049             std::string                result;
0050 
0051             if (sentry_check)
0052             {
0053                int c = is.rdbuf()->sgetc();
0054 
0055                for (;; c = is.rdbuf()->snextc())
0056                   if (std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))
0057                   { // end of file:
0058                      state |= std::ios_base::eofbit;
0059                      break;
0060                   }
0061                   else if (permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)
0062                   {
0063                      // Invalid numeric character, stop reading:
0064                      //is.rdbuf()->sputbackc(static_cast<char>(c));
0065                      break;
0066                   }
0067                   else
0068                   {
0069                      result.append(1, std::istream::traits_type::to_char_type(c));
0070                   }
0071             }
0072 
0073             if (!result.size())
0074                state |= std::ios_base::failbit;
0075             is.setstate(state);
0076             return result;
0077          }
0078 
0079       }
0080    }
0081 }
0082 
0083 #if defined(__GNUC__) && !defined(BOOST_MATH_TEST_IO_AS_INTEL_QUAD)
0084 
0085   // Forward declarations of quadruple-precision string functions.
0086   extern "C" int quadmath_snprintf(char *str, size_t size, const char *format, ...) BOOST_MATH_NOTHROW;
0087   extern "C" boost::math::cstdfloat::detail::float_internal128_t strtoflt128(const char*, char **) BOOST_MATH_NOTHROW;
0088 
0089   namespace std
0090   {
0091     template<typename char_type, class traits_type>
0092     inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const boost::math::cstdfloat::detail::float_internal128_t& x)
0093     {
0094       std::basic_ostringstream<char_type, traits_type> ostr;
0095       ostr.flags(os.flags());
0096       ostr.imbue(os.getloc());
0097       ostr.precision(os.precision());
0098 
0099       char my_buffer[64U];
0100 
0101       const int my_prec   = static_cast<int>(os.precision());
0102       const int my_digits = ((my_prec == 0) ? 36 : my_prec);
0103 
0104       const std::ios_base::fmtflags my_flags  = os.flags();
0105 
0106       char my_format_string[8U];
0107 
0108       std::size_t my_format_string_index = 0U;
0109 
0110       my_format_string[my_format_string_index] = '%';
0111       ++my_format_string_index;
0112 
0113       if(my_flags & std::ios_base::showpos)   { my_format_string[my_format_string_index] = '+'; ++my_format_string_index; }
0114       if(my_flags & std::ios_base::showpoint) { my_format_string[my_format_string_index] = '#'; ++my_format_string_index; }
0115 
0116       my_format_string[my_format_string_index + 0U] = '.';
0117       my_format_string[my_format_string_index + 1U] = '*';
0118       my_format_string[my_format_string_index + 2U] = 'Q';
0119 
0120       my_format_string_index += 3U;
0121 
0122       char the_notation_char;
0123 
0124       if     (my_flags & std::ios_base::scientific) { the_notation_char = 'e'; }
0125       else if(my_flags & std::ios_base::fixed)      { the_notation_char = 'f'; }
0126       else                                          { the_notation_char = 'g'; }
0127 
0128       my_format_string[my_format_string_index + 0U] = the_notation_char;
0129       my_format_string[my_format_string_index + 1U] = 0;
0130 
0131       const int v = ::quadmath_snprintf(my_buffer,
0132                                         static_cast<int>(sizeof(my_buffer)),
0133                                         my_format_string,
0134                                         my_digits,
0135                                         x);
0136 
0137       if(v < 0) { BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed internally in quadmath_snprintf().")); }
0138 
0139       if(v >= static_cast<int>(sizeof(my_buffer) - 1U))
0140       {
0141         // Evidently there is a really long floating-point string here,
0142         // such as a small decimal representation in non-scientific notation.
0143         // So we have to use dynamic memory allocation for the output
0144         // string buffer.
0145 
0146         char* my_buffer2 = nullptr;
0147 
0148 #ifndef BOOST_MATH_NO_EXCEPTIONS
0149         try
0150         {
0151 #endif
0152           my_buffer2 = new char[v + 3];
0153 #ifndef BOOST_MATH_NO_EXCEPTIONS
0154         }
0155         catch(const std::bad_alloc&)
0156         {
0157           BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed while allocating memory."));
0158         }
0159 #endif
0160         const int v2 = ::quadmath_snprintf(my_buffer2,
0161                                             v + 3,
0162                                             my_format_string,
0163                                             my_digits,
0164                                             x);
0165 
0166         if(v2 >= v + 3)
0167         {
0168           BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed."));
0169         }
0170 
0171         static_cast<void>(ostr << my_buffer2);
0172 
0173         delete [] my_buffer2;
0174       }
0175       else
0176       {
0177         static_cast<void>(ostr << my_buffer);
0178       }
0179 
0180       return (os << ostr.str());
0181     }
0182 
0183     template<typename char_type, class traits_type>
0184     inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, boost::math::cstdfloat::detail::float_internal128_t& x)
0185     {
0186       std::string str = boost::math::detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
0187 
0188       char* p_end;
0189 
0190       x = strtoflt128(str.c_str(), &p_end);
0191 
0192       if(static_cast<std::ptrdiff_t>(p_end - str.c_str()) != static_cast<std::ptrdiff_t>(str.length()))
0193       {
0194         for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it)
0195         {
0196           static_cast<void>(is.putback(*it));
0197         }
0198 
0199         is.setstate(ios_base::failbit);
0200 
0201         BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
0202       }
0203 
0204       return is;
0205     }
0206   }
0207 
0208 #elif defined(__INTEL_COMPILER) || defined(BOOST_MATH_TEST_IO_AS_INTEL_QUAD)
0209 
0210   // The section for I/O stream support for the ICC compiler is particularly
0211   // long, because these functions must be painstakingly synthesized from
0212   // manually-written routines (ICC does not support I/O stream operations
0213   // for its _Quad type).
0214 
0215   // The following string-extraction routines are based on the methodology
0216   // used in Boost.Multiprecision by John Maddock and Christopher Kormanyos.
0217   // This methodology has been slightly modified here for boost::float128_t.
0218 
0219 
0220   #include <cstring>
0221   #include <cctype>
0222   
0223   namespace boost { namespace math { namespace cstdfloat { namespace detail {
0224 
0225   template<class string_type>
0226   void format_float_string(string_type& str,
0227                             int my_exp,
0228                             int digits,
0229                             const std::ios_base::fmtflags f,
0230                             const bool iszero)
0231   {
0232     typedef typename string_type::size_type size_type;
0233 
0234     const bool scientific = ((f & std::ios_base::scientific) == std::ios_base::scientific);
0235     const bool fixed      = ((f & std::ios_base::fixed)      == std::ios_base::fixed);
0236     const bool showpoint  = ((f & std::ios_base::showpoint)  == std::ios_base::showpoint);
0237     const bool showpos    = ((f & std::ios_base::showpos)    == std::ios_base::showpos);
0238 
0239     const bool b_neg = ((str.size() != 0U) && (str[0] == '-'));
0240 
0241     if(b_neg)
0242     {
0243       str.erase(0, 1);
0244     }
0245 
0246     if(digits == 0)
0247     {
0248       digits = static_cast<int>((std::max)(str.size(), size_type(16)));
0249     }
0250 
0251     if(iszero || str.empty() || (str.find_first_not_of('0') == string_type::npos))
0252     {
0253       // We will be printing zero, even though the value might not
0254       // actually be zero (it just may have been rounded to zero).
0255       str = "0";
0256 
0257       if(scientific || fixed)
0258       {
0259         str.append(1, '.');
0260         str.append(size_type(digits), '0');
0261 
0262         if(scientific)
0263         {
0264           str.append("e+00");
0265         }
0266       }
0267       else
0268       {
0269         if(showpoint)
0270         {
0271           str.append(1, '.');
0272           if(digits > 1)
0273           {
0274             str.append(size_type(digits - 1), '0');
0275           }
0276         }
0277       }
0278 
0279       if(b_neg)
0280       {
0281         str.insert(0U, 1U, '-');
0282       }
0283       else if(showpos)
0284       {
0285         str.insert(0U, 1U, '+');
0286       }
0287 
0288       return;
0289     }
0290 
0291     if(!fixed && !scientific && !showpoint)
0292     {
0293       // Suppress trailing zeros.
0294       typename string_type::iterator pos = str.end();
0295 
0296       while(pos != str.begin() && *--pos == '0') { ; }
0297 
0298       if(pos != str.end())
0299       {
0300         ++pos;
0301       }
0302 
0303       str.erase(pos, str.end());
0304 
0305       if(str.empty())
0306       {
0307         str = '0';
0308       }
0309     }
0310     else if(!fixed || (my_exp >= 0))
0311     {
0312       // Pad out the end with zero's if we need to.
0313 
0314       std::ptrdiff_t chars = static_cast<std::ptrdiff_t>(str.size());
0315       chars = digits - chars;
0316 
0317       if(scientific)
0318       {
0319         ++chars;
0320       }
0321 
0322       if(chars > 0)
0323       {
0324         str.append(static_cast<size_type>(chars), '0');
0325       }
0326     }
0327 
0328     if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
0329     {
0330       if((1 + my_exp) > static_cast<int>(str.size()))
0331       {
0332         // Just pad out the end with zeros.
0333         str.append(static_cast<size_type>((1 + my_exp) - static_cast<int>(str.size())), '0');
0334 
0335         if(showpoint || fixed)
0336         {
0337           str.append(".");
0338         }
0339       }
0340       else if(my_exp + 1 < static_cast<int>(str.size()))
0341       {
0342         if(my_exp < 0)
0343         {
0344           str.insert(0U, static_cast<size_type>(-1 - my_exp), '0');
0345           str.insert(0U, "0.");
0346         }
0347         else
0348         {
0349           // Insert the decimal point:
0350           str.insert(static_cast<size_type>(my_exp + 1), 1, '.');
0351         }
0352       }
0353       else if(showpoint || fixed) // we have exactly the digits we require to left of the point
0354       {
0355         str += ".";
0356       }
0357 
0358       if(fixed)
0359       {
0360         // We may need to add trailing zeros.
0361         int l = static_cast<int>(str.find('.') + 1U);
0362         l = digits - (static_cast<int>(str.size()) - l);
0363 
0364         if(l > 0)
0365         {
0366           str.append(size_type(l), '0');
0367         }
0368       }
0369     }
0370     else
0371     {
0372       // Scientific format:
0373       if(showpoint || (str.size() > 1))
0374       {
0375         str.insert(1U, 1U, '.');
0376       }
0377 
0378       str.append(1U, 'e');
0379 
0380       string_type e = std::to_string(std::abs(my_exp));
0381 
0382       if(e.size() < 2U)
0383       {
0384         e.insert(0U, 2U - e.size(), '0');
0385       }
0386 
0387       if(my_exp < 0)
0388       {
0389         e.insert(0U, 1U, '-');
0390       }
0391       else
0392       {
0393         e.insert(0U, 1U, '+');
0394       }
0395 
0396       str.append(e);
0397     }
0398 
0399     if(b_neg)
0400     {
0401       str.insert(0U, 1U, '-');
0402     }
0403     else if(showpos)
0404     {
0405       str.insert(0U, 1U, '+');
0406     }
0407   }
0408 
0409   template<class float_type, class type_a> inline void eval_convert_to(type_a* pa,    const float_type& cb)                        { *pa  = static_cast<type_a>(cb); }
0410   template<class float_type, class type_a> inline void eval_add       (float_type& b, const type_a& a)                             { b   += a; }
0411   template<class float_type, class type_a> inline void eval_subtract  (float_type& b, const type_a& a)                             { b   -= a; }
0412   template<class float_type, class type_a> inline void eval_multiply  (float_type& b, const type_a& a)                             { b   *= a; }
0413   template<class float_type>               inline void eval_multiply  (float_type& b, const float_type& cb, const float_type& cb2) { b    = (cb * cb2); }
0414   template<class float_type, class type_a> inline void eval_divide    (float_type& b, const type_a& a)                             { b   /= a; }
0415   template<class float_type>               inline void eval_log10     (float_type& b, const float_type& cb)                        { b    = std::log10(cb); }
0416   template<class float_type>               inline void eval_floor     (float_type& b, const float_type& cb)                        { b    = std::floor(cb); }
0417 
0418   inline void round_string_up_at(std::string& s, int pos, int& expon)
0419   {
0420     // This subroutine rounds up a string representation of a
0421     // number at the given position pos.
0422 
0423     if(pos < 0)
0424     {
0425       s.insert(0U, 1U, '1');
0426       s.erase(s.size() - 1U);
0427       ++expon;
0428     }
0429     else if(s[pos] == '9')
0430     {
0431       s[pos] = '0';
0432       round_string_up_at(s, pos - 1, expon);
0433     }
0434     else
0435     {
0436       if((pos == 0) && (s[pos] == '0') && (s.size() == 1))
0437       {
0438         ++expon;
0439       }
0440 
0441       ++s[pos];
0442     }
0443   }
0444 
0445   template<class float_type>
0446   std::string convert_to_string(float_type& x,
0447                                 std::streamsize digits,
0448                                 const std::ios_base::fmtflags f)
0449   {
0450     const bool isneg  = (x < 0);
0451     const bool iszero = ((!isneg) ? bool(+x < (std::numeric_limits<float_type>::min)())
0452                                   : bool(-x < (std::numeric_limits<float_type>::min)()));
0453     const bool isnan  = (x != x);
0454     const bool isinf  = ((!isneg) ? bool(+x > (std::numeric_limits<float_type>::max)())
0455                                   : bool(-x > (std::numeric_limits<float_type>::max)()));
0456 
0457     int expon = 0;
0458 
0459     if(digits <= 0) { digits = std::numeric_limits<float_type>::max_digits10; }
0460 
0461     const int org_digits = static_cast<int>(digits);
0462 
0463     std::string result;
0464 
0465     if(iszero)
0466     {
0467       result = "0";
0468     }
0469     else if(isinf)
0470     {
0471       if(x < 0)
0472       {
0473         return "-inf";
0474       }
0475       else
0476       {
0477         return ((f & std::ios_base::showpos) == std::ios_base::showpos) ? "+inf" : "inf";
0478       }
0479     }
0480     else if(isnan)
0481     {
0482       return "nan";
0483     }
0484     else
0485     {
0486       // Start by figuring out the base-10 exponent.
0487       if(isneg) { x = -x; }
0488 
0489       float_type t;
0490       constexpr float_type ten = 10;
0491 
0492       eval_log10(t, x);
0493       eval_floor(t, t);
0494       eval_convert_to(&expon, t);
0495 
0496       if(-expon > std::numeric_limits<float_type>::max_exponent10 - 3)
0497       {
0498         int e = -expon / 2;
0499 
0500         const float_type t2 = boost::math::cstdfloat::detail::pown(ten, e);
0501 
0502         eval_multiply(t, t2, x);
0503         eval_multiply(t, t2);
0504 
0505         if((expon & 1) != 0)
0506         {
0507           eval_multiply(t, ten);
0508         }
0509       }
0510       else
0511       {
0512         t = boost::math::cstdfloat::detail::pown(ten, -expon);
0513         eval_multiply(t, x);
0514       }
0515 
0516       // Make sure that the value lies between [1, 10), and adjust if not.
0517       if(t < 1)
0518       {
0519         eval_multiply(t, 10);
0520 
0521         --expon;
0522       }
0523       else if(t >= 10)
0524       {
0525         eval_divide(t, 10);
0526 
0527         ++expon;
0528       }
0529 
0530       float_type digit;
0531       int        cdigit;
0532 
0533       // Adjust the number of digits required based on formatting options.
0534       if(((f & std::ios_base::fixed) == std::ios_base::fixed) && (expon != -1))
0535       {
0536         digits += (expon + 1);
0537       }
0538 
0539       if((f & std::ios_base::scientific) == std::ios_base::scientific)
0540       {
0541         ++digits;
0542       }
0543 
0544       // Extract the base-10 digits one at a time.
0545       for(int i = 0; i < digits; ++i)
0546       {
0547         eval_floor(digit, t);
0548         eval_convert_to(&cdigit, digit);
0549 
0550         result += static_cast<char>('0' + cdigit);
0551 
0552         eval_subtract(t, digit);
0553         eval_multiply(t, ten);
0554       }
0555       if (result.size() == 0)
0556          result = "0";
0557 
0558       // Possibly round the result.
0559       if(digits >= 0)
0560       {
0561         eval_floor(digit, t);
0562         eval_convert_to(&cdigit, digit);
0563         eval_subtract(t, digit);
0564 
0565         if((cdigit == 5) && (t == 0))
0566         {
0567           // Use simple bankers rounding.
0568 
0569           if((static_cast<int>(*result.rbegin() - '0') & 1) != 0)
0570           {
0571             round_string_up_at(result, static_cast<int>(result.size() - 1U), expon);
0572             if (digits == 0) digits = 1;
0573           }
0574         }
0575         else if(cdigit >= 5)
0576         {
0577           round_string_up_at(result, static_cast<int>(result.size() - 1u), expon);
0578           if (digits == 0) digits = 1;
0579         }
0580       }
0581     }
0582 
0583     while((result.size() > static_cast<std::string::size_type>(digits)) && result.size())
0584     {
0585       // We may get here as a result of rounding.
0586 
0587       if(result.size() > 1U)
0588       {
0589         result.erase(result.size() - 1U);
0590       }
0591       else
0592       {
0593         if(expon > 0)
0594         {
0595           --expon; // so we put less padding in the result.
0596         }
0597         else
0598         {
0599           ++expon;
0600         }
0601 
0602         ++digits;
0603       }
0604     }
0605 
0606     if(isneg)
0607     {
0608       result.insert(0U, 1U, '-');
0609     }
0610 
0611     format_float_string(result, expon, org_digits, f, iszero);
0612 
0613     return result;
0614   }
0615 
0616   template <class float_type>
0617   bool convert_from_string(float_type& value, const char* p)
0618   {
0619     value = 0;
0620 
0621     if((p == nullptr) || (*p == '\0'))
0622     {
0623       return false;
0624     }
0625 
0626     bool is_neg       = false;
0627     bool is_neg_expon = false;
0628 
0629     constexpr int ten = 10;
0630 
0631     int expon       = 0;
0632     int digits_seen = 0;
0633 
0634     constexpr int max_digits = std::numeric_limits<float_type>::max_digits10 + 1;
0635 
0636     if(*p == '+')
0637     {
0638       ++p;
0639     }
0640     else if(*p == '-')
0641     {
0642       is_neg = true;
0643       ++p;
0644     }
0645 
0646     const bool isnan = ((std::strcmp(p, "nan") == 0) || (std::strcmp(p, "NaN") == 0) || (std::strcmp(p, "NAN") == 0));
0647 
0648     if(isnan)
0649     {
0650       eval_divide(value, 0);
0651 
0652       if(is_neg)
0653       {
0654         value = -value;
0655       }
0656 
0657       return true;
0658     }
0659 
0660     const bool isinf = ((std::strcmp(p, "inf") == 0) || (std::strcmp(p, "Inf") == 0) || (std::strcmp(p, "INF") == 0));
0661 
0662     if(isinf)
0663     {
0664       value = 1;
0665       eval_divide(value, 0);
0666 
0667       if(is_neg)
0668       {
0669         value = -value;
0670       }
0671 
0672       return true;
0673     }
0674 
0675     // Grab all the leading digits before the decimal point.
0676     while(std::isdigit(*p))
0677     {
0678       eval_multiply(value, ten);
0679       eval_add(value, static_cast<int>(*p - '0'));
0680       ++p;
0681       ++digits_seen;
0682     }
0683 
0684     if(*p == '.')
0685     {
0686       // Grab everything after the point, stop when we've seen
0687       // enough digits, even if there are actually more available.
0688 
0689       ++p;
0690 
0691       while(std::isdigit(*p))
0692       {
0693         eval_multiply(value, ten);
0694         eval_add(value, static_cast<int>(*p - '0'));
0695         ++p;
0696         --expon;
0697 
0698         if(++digits_seen > max_digits)
0699         {
0700           break;
0701         }
0702       }
0703 
0704       while(std::isdigit(*p))
0705       {
0706         ++p;
0707       }
0708     }
0709 
0710     // Parse the exponent.
0711     if((*p == 'e') || (*p == 'E'))
0712     {
0713       ++p;
0714 
0715       if(*p == '+')
0716       {
0717         ++p;
0718       }
0719       else if(*p == '-')
0720       {
0721         is_neg_expon = true;
0722         ++p;
0723       }
0724 
0725       int e2 = 0;
0726 
0727       while(std::isdigit(*p))
0728       {
0729         e2 *= 10;
0730         e2 += (*p - '0');
0731         ++p;
0732       }
0733 
0734       if(is_neg_expon)
0735       {
0736         e2 = -e2;
0737       }
0738 
0739       expon += e2;
0740     }
0741 
0742     if(expon)
0743     {
0744       // Scale by 10^expon. Note that 10^expon can be outside the range
0745       // of our number type, even though the result is within range.
0746       // If that looks likely, then split the calculation in two parts.
0747       float_type t;
0748       t = ten;
0749 
0750       if(expon > (std::numeric_limits<float_type>::min_exponent10 + 2))
0751       {
0752         t = boost::math::cstdfloat::detail::pown(t, expon);
0753         eval_multiply(value, t);
0754       }
0755       else
0756       {
0757         t = boost::math::cstdfloat::detail::pown(t, (expon + digits_seen + 1));
0758         eval_multiply(value, t);
0759         t = ten;
0760         t = boost::math::cstdfloat::detail::pown(t, (-digits_seen - 1));
0761         eval_multiply(value, t);
0762       }
0763     }
0764 
0765     if(is_neg)
0766     {
0767       value = -value;
0768     }
0769 
0770     return (*p == '\0');
0771   }
0772   } } } } // boost::math::cstdfloat::detail
0773 
0774   namespace std
0775   {
0776     template<typename char_type, class traits_type>
0777     inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const boost::math::cstdfloat::detail::float_internal128_t& x)
0778     {
0779       boost::math::cstdfloat::detail::float_internal128_t non_const_x = x;
0780 
0781       const std::string str = boost::math::cstdfloat::detail::convert_to_string(non_const_x,
0782                                                                                 os.precision(),
0783                                                                                 os.flags());
0784 
0785       std::basic_ostringstream<char_type, traits_type> ostr;
0786       ostr.flags(os.flags());
0787       ostr.imbue(os.getloc());
0788       ostr.precision(os.precision());
0789 
0790       static_cast<void>(ostr << str);
0791 
0792       return (os << ostr.str());
0793     }
0794 
0795     template<typename char_type, class traits_type>
0796     inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, boost::math::cstdfloat::detail::float_internal128_t& x)
0797     {
0798       std::string str = boost::math::detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
0799 
0800       const bool conversion_is_ok = boost::math::cstdfloat::detail::convert_from_string(x, str.c_str());
0801 
0802       if(false == conversion_is_ok)
0803       {
0804         for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it)
0805         {
0806           static_cast<void>(is.putback(*it));
0807         }
0808 
0809         is.setstate(ios_base::failbit);
0810 
0811         BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
0812       }
0813 
0814       return is;
0815     }
0816   }
0817 
0818   #endif // Use __GNUC__ or __INTEL_COMPILER libquadmath
0819 
0820   #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
0821 
0822 #endif // BOOST_MATH_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_