775 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			775 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
///////////////////////////////////////////////////////////////////////////////
 | 
						|
// Copyright Christopher Kormanyos 2014.
 | 
						|
// Copyright John Maddock 2014.
 | 
						|
// Copyright Paul Bristow 2014.
 | 
						|
// 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)
 | 
						|
//
 | 
						|
 | 
						|
// Implement quadruple-precision I/O stream operations.
 | 
						|
 | 
						|
#ifndef _BOOST_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
 | 
						|
  #define _BOOST_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
 | 
						|
 | 
						|
  #include <boost/math/cstdfloat/cstdfloat_types.hpp>
 | 
						|
  #include <boost/math/cstdfloat/cstdfloat_limits.hpp>
 | 
						|
  #include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
 | 
						|
 | 
						|
  #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
 | 
						|
  #error You can not use <boost/math/cstdfloat/cstdfloat_iostream.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
 | 
						|
  #endif
 | 
						|
 | 
						|
  #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
 | 
						|
 | 
						|
  #include <cstddef>
 | 
						|
  #include <istream>
 | 
						|
  #include <ostream>
 | 
						|
  #include <sstream>
 | 
						|
  #include <stdexcept>
 | 
						|
  #include <string>
 | 
						|
  #include <boost/static_assert.hpp>
 | 
						|
  #include <boost/throw_exception.hpp>
 | 
						|
 | 
						|
//  #if (0)
 | 
						|
  #if defined(__GNUC__)
 | 
						|
 | 
						|
  // Forward declarations of quadruple-precision string functions.
 | 
						|
  extern "C" int quadmath_snprintf(char *str, size_t size, const char *format, ...) throw();
 | 
						|
  extern "C" boost::math::cstdfloat::detail::float_internal128_t strtoflt128(const char*, char **) throw();
 | 
						|
 | 
						|
  namespace std
 | 
						|
  {
 | 
						|
    template<typename char_type, class traits_type>
 | 
						|
    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)
 | 
						|
    {
 | 
						|
      std::basic_ostringstream<char_type, traits_type> ostr;
 | 
						|
      ostr.flags(os.flags());
 | 
						|
      ostr.imbue(os.getloc());
 | 
						|
      ostr.precision(os.precision());
 | 
						|
 | 
						|
      char my_buffer[64U];
 | 
						|
 | 
						|
      const int my_prec   = static_cast<int>(os.precision());
 | 
						|
      const int my_digits = ((my_prec == 0) ? 36 : my_prec);
 | 
						|
 | 
						|
      const std::ios_base::fmtflags my_flags  = os.flags();
 | 
						|
 | 
						|
      char my_format_string[8U];
 | 
						|
 | 
						|
      std::size_t my_format_string_index = 0U;
 | 
						|
 | 
						|
      my_format_string[my_format_string_index] = '%';
 | 
						|
      ++my_format_string_index;
 | 
						|
 | 
						|
      if(my_flags & std::ios_base::showpos)   { my_format_string[my_format_string_index] = '+'; ++my_format_string_index; }
 | 
						|
      if(my_flags & std::ios_base::showpoint) { my_format_string[my_format_string_index] = '#'; ++my_format_string_index; }
 | 
						|
 | 
						|
      my_format_string[my_format_string_index + 0U] = '.';
 | 
						|
      my_format_string[my_format_string_index + 1U] = '*';
 | 
						|
      my_format_string[my_format_string_index + 2U] = 'Q';
 | 
						|
 | 
						|
      my_format_string_index += 3U;
 | 
						|
 | 
						|
      char the_notation_char;
 | 
						|
 | 
						|
      if     (my_flags & std::ios_base::scientific) { the_notation_char = 'e'; }
 | 
						|
      else if(my_flags & std::ios_base::fixed)      { the_notation_char = 'f'; }
 | 
						|
      else                                          { the_notation_char = 'g'; }
 | 
						|
 | 
						|
      my_format_string[my_format_string_index + 0U] = the_notation_char;
 | 
						|
      my_format_string[my_format_string_index + 1U] = 0;
 | 
						|
 | 
						|
      const int v = ::quadmath_snprintf(my_buffer,
 | 
						|
                                        static_cast<int>(sizeof(my_buffer)),
 | 
						|
                                        my_format_string,
 | 
						|
                                        my_digits,
 | 
						|
                                        x);
 | 
						|
 | 
						|
      if(v < 0) { BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed internally in quadmath_snprintf().")); }
 | 
						|
 | 
						|
      if(v >= static_cast<int>(sizeof(my_buffer) - 1U))
 | 
						|
      {
 | 
						|
        // Evidently there is a really long floating-point string here,
 | 
						|
        // such as a small decimal representation in non-scientific notation.
 | 
						|
        // So we have to use dynamic memory allocation for the output
 | 
						|
        // string buffer.
 | 
						|
 | 
						|
        char* my_buffer2 = static_cast<char*>(0U);
 | 
						|
 | 
						|
#ifndef BOOST_NO_EXCEPTIONS
 | 
						|
        try
 | 
						|
        {
 | 
						|
#endif
 | 
						|
          my_buffer2 = new char[v + 3];
 | 
						|
#ifndef BOOST_NO_EXCEPTIONS
 | 
						|
        }
 | 
						|
        catch(const std::bad_alloc&)
 | 
						|
        {
 | 
						|
          BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed while allocating memory."));
 | 
						|
        }
 | 
						|
#endif
 | 
						|
        const int v2 = ::quadmath_snprintf(my_buffer2,
 | 
						|
                                            v + 3,
 | 
						|
                                            my_format_string,
 | 
						|
                                            my_digits,
 | 
						|
                                            x);
 | 
						|
 | 
						|
        if(v2 >= v + 3)
 | 
						|
        {
 | 
						|
          BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed."));
 | 
						|
        }
 | 
						|
 | 
						|
        static_cast<void>(ostr << my_buffer2);
 | 
						|
 | 
						|
        delete [] my_buffer2;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        static_cast<void>(ostr << my_buffer);
 | 
						|
      }
 | 
						|
 | 
						|
      return (os << ostr.str());
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename char_type, class traits_type>
 | 
						|
    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)
 | 
						|
    {
 | 
						|
      std::string str;
 | 
						|
 | 
						|
      static_cast<void>(is >> str);
 | 
						|
 | 
						|
      char* p_end;
 | 
						|
 | 
						|
      x = strtoflt128(str.c_str(), &p_end);
 | 
						|
 | 
						|
      if(static_cast<std::ptrdiff_t>(p_end - str.c_str()) != static_cast<std::ptrdiff_t>(str.length()))
 | 
						|
      {
 | 
						|
        for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it)
 | 
						|
        {
 | 
						|
          static_cast<void>(is.putback(*it));
 | 
						|
        }
 | 
						|
 | 
						|
        is.setstate(ios_base::failbit);
 | 
						|
 | 
						|
        BOOST_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
 | 
						|
      }
 | 
						|
 | 
						|
      return is;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
//  #elif defined(__GNUC__)
 | 
						|
  #elif defined(BOOST_INTEL)
 | 
						|
 | 
						|
  // The section for I/O stream support for the ICC compiler is particularly
 | 
						|
  // long, because these functions must be painstakingly synthesized from
 | 
						|
  // manually-written routines (ICC does not support I/O stream operations
 | 
						|
  // for its _Quad type).
 | 
						|
 | 
						|
  // The following string-extraction routines are based on the methodology
 | 
						|
  // used in Boost.Multiprecision by John Maddock and Christopher Kormanyos.
 | 
						|
  // This methodology has been slightly modified here for boost::float128_t.
 | 
						|
 | 
						|
  #include <cstring>
 | 
						|
  #include <cctype>
 | 
						|
  #include <boost/lexical_cast.hpp>
 | 
						|
 | 
						|
  namespace boost { namespace math { namespace cstdfloat { namespace detail {
 | 
						|
 | 
						|
  template<class string_type>
 | 
						|
  void format_float_string(string_type& str,
 | 
						|
                            int my_exp,
 | 
						|
                            int digits,
 | 
						|
                            const std::ios_base::fmtflags f,
 | 
						|
                            const bool iszero)
 | 
						|
  {
 | 
						|
    typedef typename string_type::size_type size_type;
 | 
						|
 | 
						|
    const bool scientific = ((f & std::ios_base::scientific) == std::ios_base::scientific);
 | 
						|
    const bool fixed      = ((f & std::ios_base::fixed)      == std::ios_base::fixed);
 | 
						|
    const bool showpoint  = ((f & std::ios_base::showpoint)  == std::ios_base::showpoint);
 | 
						|
    const bool showpos    = ((f & std::ios_base::showpos)    == std::ios_base::showpos);
 | 
						|
 | 
						|
    const bool b_neg = ((str.size() != 0U) && (str[0] == '-'));
 | 
						|
 | 
						|
    if(b_neg)
 | 
						|
    {
 | 
						|
      str.erase(0, 1);
 | 
						|
    }
 | 
						|
 | 
						|
    if(digits == 0)
 | 
						|
    {
 | 
						|
      digits = static_cast<int>((std::max)(str.size(), size_type(16)));
 | 
						|
    }
 | 
						|
 | 
						|
    if(iszero || str.empty() || (str.find_first_not_of('0') == string_type::npos))
 | 
						|
    {
 | 
						|
      // We will be printing zero, even though the value might not
 | 
						|
      // actually be zero (it just may have been rounded to zero).
 | 
						|
      str = "0";
 | 
						|
 | 
						|
      if(scientific || fixed)
 | 
						|
      {
 | 
						|
        str.append(1, '.');
 | 
						|
        str.append(size_type(digits), '0');
 | 
						|
 | 
						|
        if(scientific)
 | 
						|
        {
 | 
						|
          str.append("e+00");
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if(showpoint)
 | 
						|
        {
 | 
						|
          str.append(1, '.');
 | 
						|
          if(digits > 1)
 | 
						|
          {
 | 
						|
            str.append(size_type(digits - 1), '0');
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if(b_neg)
 | 
						|
      {
 | 
						|
        str.insert(0U, 1U, '-');
 | 
						|
      }
 | 
						|
      else if(showpos)
 | 
						|
      {
 | 
						|
        str.insert(0U, 1U, '+');
 | 
						|
      }
 | 
						|
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    if(!fixed && !scientific && !showpoint)
 | 
						|
    {
 | 
						|
      // Suppress trailing zeros.
 | 
						|
      typename string_type::iterator pos = str.end();
 | 
						|
 | 
						|
      while(pos != str.begin() && *--pos == '0') { ; }
 | 
						|
 | 
						|
      if(pos != str.end())
 | 
						|
      {
 | 
						|
        ++pos;
 | 
						|
      }
 | 
						|
 | 
						|
      str.erase(pos, str.end());
 | 
						|
 | 
						|
      if(str.empty())
 | 
						|
      {
 | 
						|
        str = '0';
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else if(!fixed || (my_exp >= 0))
 | 
						|
    {
 | 
						|
      // Pad out the end with zero's if we need to.
 | 
						|
 | 
						|
      int chars = static_cast<int>(str.size());
 | 
						|
      chars = digits - chars;
 | 
						|
 | 
						|
      if(scientific)
 | 
						|
      {
 | 
						|
        ++chars;
 | 
						|
      }
 | 
						|
 | 
						|
      if(chars > 0)
 | 
						|
      {
 | 
						|
        str.append(static_cast<size_type>(chars), '0');
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
 | 
						|
    {
 | 
						|
      if((1 + my_exp) > static_cast<int>(str.size()))
 | 
						|
      {
 | 
						|
        // Just pad out the end with zeros.
 | 
						|
        str.append(static_cast<size_type>((1 + my_exp) - static_cast<int>(str.size())), '0');
 | 
						|
 | 
						|
        if(showpoint || fixed)
 | 
						|
        {
 | 
						|
          str.append(".");
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else if(my_exp + 1 < static_cast<int>(str.size()))
 | 
						|
      {
 | 
						|
        if(my_exp < 0)
 | 
						|
        {
 | 
						|
          str.insert(0U, static_cast<size_type>(-1 - my_exp), '0');
 | 
						|
          str.insert(0U, "0.");
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          // Insert the decimal point:
 | 
						|
          str.insert(static_cast<size_type>(my_exp + 1), 1, '.');
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else if(showpoint || fixed) // we have exactly the digits we require to left of the point
 | 
						|
      {
 | 
						|
        str += ".";
 | 
						|
      }
 | 
						|
 | 
						|
      if(fixed)
 | 
						|
      {
 | 
						|
        // We may need to add trailing zeros.
 | 
						|
        int l = static_cast<int>(str.find('.') + 1U);
 | 
						|
        l = digits - (static_cast<int>(str.size()) - l);
 | 
						|
 | 
						|
        if(l > 0)
 | 
						|
        {
 | 
						|
          str.append(size_type(l), '0');
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      // Scientific format:
 | 
						|
      if(showpoint || (str.size() > 1))
 | 
						|
      {
 | 
						|
        str.insert(1U, 1U, '.');
 | 
						|
      }
 | 
						|
 | 
						|
      str.append(1U, 'e');
 | 
						|
      string_type e = boost::lexical_cast<string_type>(std::abs(my_exp));
 | 
						|
 | 
						|
      if(e.size() < 2U)
 | 
						|
      {
 | 
						|
        e.insert(0U, 2U - e.size(), '0');
 | 
						|
      }
 | 
						|
 | 
						|
      if(my_exp < 0)
 | 
						|
      {
 | 
						|
        e.insert(0U, 1U, '-');
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        e.insert(0U, 1U, '+');
 | 
						|
      }
 | 
						|
 | 
						|
      str.append(e);
 | 
						|
    }
 | 
						|
 | 
						|
    if(b_neg)
 | 
						|
    {
 | 
						|
      str.insert(0U, 1U, '-');
 | 
						|
    }
 | 
						|
    else if(showpos)
 | 
						|
    {
 | 
						|
      str.insert(0U, 1U, '+');
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  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); }
 | 
						|
  template<class float_type, class type_a> inline void eval_add       (float_type& b, const type_a& a)                             { b   += a; }
 | 
						|
  template<class float_type, class type_a> inline void eval_subtract  (float_type& b, const type_a& a)                             { b   -= a; }
 | 
						|
  template<class float_type, class type_a> inline void eval_multiply  (float_type& b, const type_a& a)                             { b   *= a; }
 | 
						|
  template<class float_type>               inline void eval_multiply  (float_type& b, const float_type& cb, const float_type& cb2) { b    = (cb * cb2); }
 | 
						|
  template<class float_type, class type_a> inline void eval_divide    (float_type& b, const type_a& a)                             { b   /= a; }
 | 
						|
  template<class float_type>               inline void eval_log10     (float_type& b, const float_type& cb)                        { b    = std::log10(cb); }
 | 
						|
  template<class float_type>               inline void eval_floor     (float_type& b, const float_type& cb)                        { b    = std::floor(cb); }
 | 
						|
 | 
						|
  inline void round_string_up_at(std::string& s, int pos, int& expon)
 | 
						|
  {
 | 
						|
    // This subroutine rounds up a string representation of a
 | 
						|
    // number at the given position pos.
 | 
						|
 | 
						|
    if(pos < 0)
 | 
						|
    {
 | 
						|
      s.insert(0U, 1U, '1');
 | 
						|
      s.erase(s.size() - 1U);
 | 
						|
      ++expon;
 | 
						|
    }
 | 
						|
    else if(s[pos] == '9')
 | 
						|
    {
 | 
						|
      s[pos] = '0';
 | 
						|
      round_string_up_at(s, pos - 1, expon);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if((pos == 0) && (s[pos] == '0') && (s.size() == 1))
 | 
						|
      {
 | 
						|
        ++expon;
 | 
						|
      }
 | 
						|
 | 
						|
      ++s[pos];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  template<class float_type>
 | 
						|
  std::string convert_to_string(float_type& x,
 | 
						|
                                std::streamsize digits,
 | 
						|
                                const std::ios_base::fmtflags f)
 | 
						|
  {
 | 
						|
    const bool isneg  = (x < 0);
 | 
						|
    const bool iszero = ((!isneg) ? bool(+x < (std::numeric_limits<float_type>::min)())
 | 
						|
                                  : bool(-x < (std::numeric_limits<float_type>::min)()));
 | 
						|
    const bool isnan  = (x != x);
 | 
						|
    const bool isinf  = ((!isneg) ? bool(+x > (std::numeric_limits<float_type>::max)())
 | 
						|
                                  : bool(-x > (std::numeric_limits<float_type>::max)()));
 | 
						|
 | 
						|
    int expon = 0;
 | 
						|
 | 
						|
    if(digits <= 0) { digits = std::numeric_limits<float_type>::max_digits10; }
 | 
						|
 | 
						|
    const int org_digits = static_cast<int>(digits);
 | 
						|
 | 
						|
    std::string result;
 | 
						|
 | 
						|
    if(iszero)
 | 
						|
    {
 | 
						|
      result = "0";
 | 
						|
    }
 | 
						|
    else if(isinf)
 | 
						|
    {
 | 
						|
      if(x < 0)
 | 
						|
      {
 | 
						|
        return "-inf";
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        return ((f & std::ios_base::showpos) == std::ios_base::showpos) ? "+inf" : "inf";
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else if(isnan)
 | 
						|
    {
 | 
						|
      return "nan";
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      // Start by figuring out the base-10 exponent.
 | 
						|
      if(isneg) { x = -x; }
 | 
						|
 | 
						|
      float_type t;
 | 
						|
      float_type ten = 10;
 | 
						|
 | 
						|
      eval_log10(t, x);
 | 
						|
      eval_floor(t, t);
 | 
						|
      eval_convert_to(&expon, t);
 | 
						|
 | 
						|
      if(-expon > std::numeric_limits<float_type>::max_exponent10 - 3)
 | 
						|
      {
 | 
						|
        int e = -expon / 2;
 | 
						|
 | 
						|
        const float_type t2 = boost::math::cstdfloat::detail::pown(ten, e);
 | 
						|
 | 
						|
        eval_multiply(t, t2, x);
 | 
						|
        eval_multiply(t, t2);
 | 
						|
 | 
						|
        if((expon & 1) != 0)
 | 
						|
        {
 | 
						|
          eval_multiply(t, ten);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        t = boost::math::cstdfloat::detail::pown(ten, -expon);
 | 
						|
        eval_multiply(t, x);
 | 
						|
      }
 | 
						|
 | 
						|
      // Make sure that the value lies between [1, 10), and adjust if not.
 | 
						|
      if(t < 1)
 | 
						|
      {
 | 
						|
        eval_multiply(t, 10);
 | 
						|
 | 
						|
        --expon;
 | 
						|
      }
 | 
						|
      else if(t >= 10)
 | 
						|
      {
 | 
						|
        eval_divide(t, 10);
 | 
						|
 | 
						|
        ++expon;
 | 
						|
      }
 | 
						|
 | 
						|
      float_type digit;
 | 
						|
      int        cdigit;
 | 
						|
 | 
						|
      // Adjust the number of digits required based on formatting options.
 | 
						|
      if(((f & std::ios_base::fixed) == std::ios_base::fixed) && (expon != -1))
 | 
						|
      {
 | 
						|
        digits += (expon + 1);
 | 
						|
      }
 | 
						|
 | 
						|
      if((f & std::ios_base::scientific) == std::ios_base::scientific)
 | 
						|
      {
 | 
						|
        ++digits;
 | 
						|
      }
 | 
						|
 | 
						|
      // Extract the base-10 digits one at a time.
 | 
						|
      for(int i = 0; i < digits; ++i)
 | 
						|
      {
 | 
						|
        eval_floor(digit, t);
 | 
						|
        eval_convert_to(&cdigit, digit);
 | 
						|
 | 
						|
        result += static_cast<char>('0' + cdigit);
 | 
						|
 | 
						|
        eval_subtract(t, digit);
 | 
						|
        eval_multiply(t, ten);
 | 
						|
      }
 | 
						|
 | 
						|
      // Possibly round the result.
 | 
						|
      if(digits >= 0)
 | 
						|
      {
 | 
						|
        eval_floor(digit, t);
 | 
						|
        eval_convert_to(&cdigit, digit);
 | 
						|
        eval_subtract(t, digit);
 | 
						|
 | 
						|
        if((cdigit == 5) && (t == 0))
 | 
						|
        {
 | 
						|
          // Use simple bankers rounding.
 | 
						|
 | 
						|
          if((static_cast<int>(*result.rbegin() - '0') & 1) != 0)
 | 
						|
          {
 | 
						|
            round_string_up_at(result, static_cast<int>(result.size() - 1U), expon);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        else if(cdigit >= 5)
 | 
						|
        {
 | 
						|
          round_string_up_at(result, static_cast<int>(result.size() - 1), expon);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    while((result.size() > static_cast<std::string::size_type>(digits)) && result.size())
 | 
						|
    {
 | 
						|
      // We may get here as a result of rounding.
 | 
						|
 | 
						|
      if(result.size() > 1U)
 | 
						|
      {
 | 
						|
        result.erase(result.size() - 1U);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if(expon > 0)
 | 
						|
        {
 | 
						|
          --expon; // so we put less padding in the result.
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          ++expon;
 | 
						|
        }
 | 
						|
 | 
						|
        ++digits;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if(isneg)
 | 
						|
    {
 | 
						|
      result.insert(0U, 1U, '-');
 | 
						|
    }
 | 
						|
 | 
						|
    format_float_string(result, expon, org_digits, f, iszero);
 | 
						|
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class float_type>
 | 
						|
  bool convert_from_string(float_type& value, const char* p)
 | 
						|
  {
 | 
						|
    value = 0;
 | 
						|
 | 
						|
    if((p == static_cast<const char*>(0U)) || (*p == static_cast<char>(0)))
 | 
						|
    {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    bool is_neg       = false;
 | 
						|
    bool is_neg_expon = false;
 | 
						|
 | 
						|
    BOOST_CONSTEXPR_OR_CONST int ten = 10;
 | 
						|
 | 
						|
    int expon       = 0;
 | 
						|
    int digits_seen = 0;
 | 
						|
 | 
						|
    BOOST_CONSTEXPR_OR_CONST int max_digits = std::numeric_limits<float_type>::max_digits10 + 1;
 | 
						|
 | 
						|
    if(*p == static_cast<char>('+'))
 | 
						|
    {
 | 
						|
      ++p;
 | 
						|
    }
 | 
						|
    else if(*p == static_cast<char>('-'))
 | 
						|
    {
 | 
						|
      is_neg = true;
 | 
						|
      ++p;
 | 
						|
    }
 | 
						|
 | 
						|
    const bool isnan = ((std::strcmp(p, "nan") == 0) || (std::strcmp(p, "NaN") == 0) || (std::strcmp(p, "NAN") == 0));
 | 
						|
 | 
						|
    if(isnan)
 | 
						|
    {
 | 
						|
      eval_divide(value, 0);
 | 
						|
 | 
						|
      if(is_neg)
 | 
						|
      {
 | 
						|
        value = -value;
 | 
						|
      }
 | 
						|
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
 | 
						|
    const bool isinf = ((std::strcmp(p, "inf") == 0) || (std::strcmp(p, "Inf") == 0) || (std::strcmp(p, "INF") == 0));
 | 
						|
 | 
						|
    if(isinf)
 | 
						|
    {
 | 
						|
      value = 1;
 | 
						|
      eval_divide(value, 0);
 | 
						|
 | 
						|
      if(is_neg)
 | 
						|
      {
 | 
						|
        value = -value;
 | 
						|
      }
 | 
						|
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
 | 
						|
    // Grab all the leading digits before the decimal point.
 | 
						|
    while(std::isdigit(*p))
 | 
						|
    {
 | 
						|
      eval_multiply(value, ten);
 | 
						|
      eval_add(value, static_cast<int>(*p - '0'));
 | 
						|
      ++p;
 | 
						|
      ++digits_seen;
 | 
						|
    }
 | 
						|
 | 
						|
    if(*p == static_cast<char>('.'))
 | 
						|
    {
 | 
						|
      // Grab everything after the point, stop when we've seen
 | 
						|
      // enough digits, even if there are actually more available.
 | 
						|
 | 
						|
      ++p;
 | 
						|
 | 
						|
      while(std::isdigit(*p))
 | 
						|
      {
 | 
						|
        eval_multiply(value, ten);
 | 
						|
        eval_add(value, static_cast<int>(*p - '0'));
 | 
						|
        ++p;
 | 
						|
        --expon;
 | 
						|
 | 
						|
        if(++digits_seen > max_digits)
 | 
						|
        {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      while(std::isdigit(*p))
 | 
						|
      {
 | 
						|
        ++p;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    // Parse the exponent.
 | 
						|
    if((*p == static_cast<char>('e')) || (*p == static_cast<char>('E')))
 | 
						|
    {
 | 
						|
      ++p;
 | 
						|
 | 
						|
      if(*p == static_cast<char>('+'))
 | 
						|
      {
 | 
						|
        ++p;
 | 
						|
      }
 | 
						|
      else if(*p == static_cast<char>('-'))
 | 
						|
      {
 | 
						|
        is_neg_expon = true;
 | 
						|
        ++p;
 | 
						|
      }
 | 
						|
 | 
						|
      int e2 = 0;
 | 
						|
 | 
						|
      while(std::isdigit(*p))
 | 
						|
      {
 | 
						|
        e2 *= 10;
 | 
						|
        e2 += (*p - '0');
 | 
						|
        ++p;
 | 
						|
      }
 | 
						|
 | 
						|
      if(is_neg_expon)
 | 
						|
      {
 | 
						|
        e2 = -e2;
 | 
						|
      }
 | 
						|
 | 
						|
      expon += e2;
 | 
						|
    }
 | 
						|
 | 
						|
    if(expon)
 | 
						|
    {
 | 
						|
      // Scale by 10^expon. Note that 10^expon can be outside the range
 | 
						|
      // of our number type, even though the result is within range.
 | 
						|
      // If that looks likely, then split the calculation in two parts.
 | 
						|
      float_type t;
 | 
						|
      t = ten;
 | 
						|
 | 
						|
      if(expon > (std::numeric_limits<float_type>::min_exponent10 + 2))
 | 
						|
      {
 | 
						|
        t = boost::math::cstdfloat::detail::pown(t, expon);
 | 
						|
        eval_multiply(value, t);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        t = boost::math::cstdfloat::detail::pown(t, (expon + digits_seen + 1));
 | 
						|
        eval_multiply(value, t);
 | 
						|
        t = ten;
 | 
						|
        t = boost::math::cstdfloat::detail::pown(t, (-digits_seen - 1));
 | 
						|
        eval_multiply(value, t);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if(is_neg)
 | 
						|
    {
 | 
						|
      value = -value;
 | 
						|
    }
 | 
						|
 | 
						|
    return (*p == static_cast<char>(0));
 | 
						|
  }
 | 
						|
  } } } } // boost::math::cstdfloat::detail
 | 
						|
 | 
						|
  namespace std
 | 
						|
  {
 | 
						|
    template<typename char_type, class traits_type>
 | 
						|
    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)
 | 
						|
    {
 | 
						|
      boost::math::cstdfloat::detail::float_internal128_t non_const_x = x;
 | 
						|
 | 
						|
      const std::string str = boost::math::cstdfloat::detail::convert_to_string(non_const_x,
 | 
						|
                                                                                os.precision(),
 | 
						|
                                                                                os.flags());
 | 
						|
 | 
						|
      std::basic_ostringstream<char_type, traits_type> ostr;
 | 
						|
      ostr.flags(os.flags());
 | 
						|
      ostr.imbue(os.getloc());
 | 
						|
      ostr.precision(os.precision());
 | 
						|
 | 
						|
      static_cast<void>(ostr << str);
 | 
						|
 | 
						|
      return (os << ostr.str());
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename char_type, class traits_type>
 | 
						|
    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)
 | 
						|
    {
 | 
						|
      std::string str;
 | 
						|
 | 
						|
      static_cast<void>(is >> str);
 | 
						|
 | 
						|
      const bool conversion_is_ok = boost::math::cstdfloat::detail::convert_from_string(x, str.c_str());
 | 
						|
 | 
						|
      if(false == conversion_is_ok)
 | 
						|
      {
 | 
						|
        for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it)
 | 
						|
        {
 | 
						|
          static_cast<void>(is.putback(*it));
 | 
						|
        }
 | 
						|
 | 
						|
        is.setstate(ios_base::failbit);
 | 
						|
 | 
						|
        BOOST_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
 | 
						|
      }
 | 
						|
 | 
						|
      return is;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  #endif // Use __GNUC__ or BOOST_INTEL libquadmath
 | 
						|
 | 
						|
  #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
 | 
						|
 | 
						|
#endif // _BOOST_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
 |