Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:35

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