Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r75637 - in sandbox/big_number/boost/multiprecision: . detail
From: john_at_[hidden]
Date: 2011-11-23 05:14:45


Author: johnmaddock
Date: 2011-11-23 05:14:41 EST (Wed, 23 Nov 2011)
New Revision: 75637
URL: http://svn.boost.org/trac/boost/changeset/75637

Log:
Re-factor and fix (again) floating point formatting.
Text files modified:
   sandbox/big_number/boost/multiprecision/cpp_float.hpp | 66 ++-----------------------------
   sandbox/big_number/boost/multiprecision/detail/mp_number_base.hpp | 81 ++++++++++++++++++++++++++++++++++++++++
   sandbox/big_number/boost/multiprecision/gmp.hpp | 68 ++++++---------------------------
   sandbox/big_number/boost/multiprecision/mpfr.hpp | 73 ++++++++---------------------------
   4 files changed, 118 insertions(+), 170 deletions(-)

Modified: sandbox/big_number/boost/multiprecision/cpp_float.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/cpp_float.hpp (original)
+++ sandbox/big_number/boost/multiprecision/cpp_float.hpp 2011-11-23 05:14:41 EST (Wed, 23 Nov 2011)
@@ -1641,15 +1641,14 @@
 template <unsigned Digits10>
 std::string cpp_float<Digits10>::str(std::streamsize number_of_digits, std::ios_base::fmtflags f) const
 {
- bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
- bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
- bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
- bool shopos = (f & std::ios_base::showpos) == std::ios_base::showpos;
-
    std::string str;
    boost::int64_t my_exp = order();
    if(number_of_digits == 0)
- number_of_digits = (std::numeric_limits<std::size_t>::max)();
+ number_of_digits = cpp_float_max_digits10;
+ if(f & std::ios_base::fixed)
+ number_of_digits += my_exp + 1;
+ else if(f & std::ios_base::scientific)
+ ++number_of_digits;
    // Determine the number of elements needed to provide the requested digits from cpp_float<Digits10>.
    const std::size_t number_of_elements = (std::min)(static_cast<std::size_t>((number_of_digits / static_cast<std::size_t>(mp_elem_digits10)) + 2u),
       static_cast<std::size_t>(mp_elem_number));
@@ -1711,62 +1710,9 @@
          }
       }
    }
- //
- // Suppress trailing zeros:
- //
- std::string::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';
- if(fixed || (!scientific && (str.size() < 20) && (my_exp >= -3) && (my_exp < 20)))
- {
- if(1 + my_exp > str.size())
- {
- // Just pad out the end with zeros:
- str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
- if(showpoint)
- str.append(".0");
- }
- else if(my_exp + 1 != str.size())
- {
- if(my_exp < 0)
- {
- str.insert(0, static_cast<std::string::size_type>(-1-my_exp), '0');
- str.insert(0, "0.");
- }
- else
- {
- // Insert the decimal point:
- str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
- }
- }
- else if(showpoint)
- str += ".0";
- }
- else
- {
- // Scientific format:
- str.insert(1, 1, '.');
- if(str.size() == 2)
- str.append(1, '0');
- str.append(1, 'e');
- str.append(boost::lexical_cast<std::string>(my_exp));
- }
- if((showpoint || scientific) && (number_of_digits != (std::numeric_limits<std::size_t>::max)()))
- {
- std::streamsize chars = str.size() - 1;
- BOOST_ASSERT(str.find('.') != std::string::npos); // there must be a decimal point!!
- chars = number_of_digits - chars;
- if(chars > 0)
- str.append(static_cast<std::string::size_type>(chars), '0');
- }
    if(isneg())
       str.insert(0, 1, '-');
- else if(shopos)
- str.insert(0, 1, '+');
+ boost::multiprecision::detail::format_float_string(str, my_exp, number_of_digits, f);
    return str;
 }
 

Modified: sandbox/big_number/boost/multiprecision/detail/mp_number_base.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/mp_number_base.hpp (original)
+++ sandbox/big_number/boost/multiprecision/detail/mp_number_base.hpp 2011-11-23 05:14:41 EST (Wed, 23 Nov 2011)
@@ -345,6 +345,87 @@
    static const long value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
 };
 
+template <class S>
+void format_float_string(S& str, long long my_exp, std::streamsize digits, std::ios_base::fmtflags f)
+{
+ bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
+ bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
+ bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
+ bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
+
+ if(!fixed && !scientific)
+ {
+ //
+ // Suppress trailing zeros:
+ //
+ std::string::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
+ {
+ //
+ // Pad out the end with zero's if we need to:
+ //
+ std::streamsize chars = str.size();
+ if(chars && str[0] == '-')
+ --chars;
+ chars = digits - chars;
+ if(chars > 0)
+ {
+ str.append(static_cast<std::string::size_type>(chars), '0');
+ }
+ }
+
+ if(fixed || (!scientific && (str.size() < 20) && (my_exp >= -3) && (my_exp < 20)))
+ {
+ if(1 + my_exp > str.size())
+ {
+ // Just pad out the end with zeros:
+ str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
+ if(showpoint)
+ str.append(".0");
+ }
+ else if(my_exp + 1 != str.size())
+ {
+ if(my_exp < 0)
+ {
+ str.insert(0, static_cast<std::string::size_type>(-1-my_exp), '0');
+ str.insert(0, "0.");
+ }
+ else
+ {
+ // Insert the decimal point:
+ str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
+ }
+ }
+ else if(showpoint)
+ str += ".0";
+ }
+ else
+ {
+ // Scientific format:
+ str.insert(1, 1, '.');
+ if(str.size() == 2)
+ str.append(1, '0');
+ str.append(1, 'e');
+ S e = boost::lexical_cast<S>(std::abs(my_exp));
+ if(e.size() < 3)
+ e.insert(0, 3-e.size(), '0');
+ if(my_exp < 0)
+ e.insert(0, 1, '-');
+ else
+ e.insert(0, 1, '+');
+ str.append(e);
+ }
+ if(showpos && (str[0] != '-'))
+ str.insert(0, 1, '+');
+}
+
 } // namespace detail
 
 //

Modified: sandbox/big_number/boost/multiprecision/gmp.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/gmp.hpp (original)
+++ sandbox/big_number/boost/multiprecision/gmp.hpp 2011-11-23 05:14:41 EST (Wed, 23 Nov 2011)
@@ -163,71 +163,29 @@
    {
       bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
       bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
- bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
- bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
+
+ if(scientific)
+ ++digits;
 
       std::string result;
       mp_exp_t e;
       void *(*alloc_func_ptr) (size_t);
       void *(*realloc_func_ptr) (void *, size_t, size_t);
       void (*free_func_ptr) (void *, size_t);
+ mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
       const char* ps = mpf_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data);
- std::ptrdiff_t sl = std::strlen(ps);
- if(ps && *ps == '-')
- --sl; // number of digits excluding sign.
- result = ps;
- if(sl == 0)
- {
- result = scientific ? "0.0e0" : showpoint ? "0.0" : "0";
- }
- else if(fixed || (!scientific && (e > -4) && (e <= std::numeric_limits<boost::uintmax_t>::digits10 + 2)))
- {
- if(1 + e >= sl)
- {
- result.append(e - sl, '0');
- if(showpoint)
- result.append(".0");
- }
- else
- {
- if(e <= 0)
- {
- result.insert(0, -e, '0');
- result.insert(0, "0.");
- }
- else
- {
- // Insert the decimal point:
- result.insert(e, 1, '.');
- }
- }
- }
- else
+ --e; // To match with what our formatter expects.
+ if(fixed && e != -1)
       {
- if(ps[0] == '-')
- result.insert(2, 1, '.');
- else
- result.insert(1, 1, '.');
- --e;
- if(e)
- result += "e" + lexical_cast<std::string>(e);
+ // Oops we actually need a different number of digits to what we asked for:
+ (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
+ digits += e + 1;
+ ps = mpf_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data);
+ --e; // To match with what our formatter expects.
       }
- if(showpoint || scientific)
- {
- // Pad out end with zeros as required to give required precision.
- std::streamsize chars = result.size() - 1;
- BOOST_ASSERT(result.find('.') != std::string::npos); // there must be a decimal point!!
- BOOST_ASSERT(result.size()); // Better not be a null string by this point!!
- if(result[0] == '-')
- --chars;
- chars = digits - chars;
- if(chars > 0)
- result.append(static_cast<std::string::size_type>(chars), '0');
- }
- if(showpos && (result[0] != '-'))
- result.insert(0, 1, '+');
- mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
+ result = ps;
       (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
+ boost::multiprecision::detail::format_float_string(result, e, digits, f);
       return result;
    }
    ~gmp_float_imp()

Modified: sandbox/big_number/boost/multiprecision/mpfr.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/mpfr.hpp (original)
+++ sandbox/big_number/boost/multiprecision/mpfr.hpp 2011-11-23 05:14:41 EST (Wed, 23 Nov 2011)
@@ -160,70 +160,33 @@
    {
       bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
       bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
- bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
- bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
+
+ if(scientific)
+ ++digits;
 
       std::string result;
       mp_exp_t e;
- char* ps = mpfr_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
- std::ptrdiff_t sl = std::strlen(ps);
- int chars = sl;
- while(chars && (ps[chars-1] == '0'))
- --chars;
- ps[chars] = 0;
- if(chars && (*ps == '-'))
- --chars; // number of digits excluding sign.
- if(chars == 0)
+ if(mpfr_zero_p(m_data))
+ {
+ e = 0;
          result = "0";
+ }
       else
- result = ps;
- if(fixed || (!scientific && (e > -4) && (e <= std::numeric_limits<boost::uintmax_t>::digits10 + 2)))
       {
- if(e >= chars)
- {
- result.append(e - chars, '0');
- if(showpoint)
- result.append(".0");
- }
- else
+ char* ps = mpfr_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
+ --e; // To match with what our formatter expects.
+ if(fixed && e != -1)
          {
- if(e <= 0)
- {
- result.insert(0, -e, '0');
- result.insert(0, "0.");
- }
- else
- {
- // Insert the decimal point:
- result.insert(e, 1, '.');
- }
+ // Oops we actually need a different number of digits to what we asked for:
+ mpfr_free_str(ps);
+ digits += e + 1;
+ ps = ps = mpfr_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
+ --e; // To match with what our formatter expects.
          }
+ result = ps;
+ mpfr_free_str(ps);
       }
- else
- {
- if(ps[0] == '-')
- result.insert(2, 1, '.');
- else
- result.insert(1, 1, '.');
- --e;
- if(e)
- result += "e" + lexical_cast<std::string>(e);
- }
- if(showpoint || scientific)
- {
- // Pad out end with zeros as required to give required precision.
- std::streamsize chars = result.size() - 1;
- BOOST_ASSERT(result.find('.') != std::string::npos); // there must be a decimal point!!
- BOOST_ASSERT(result.size()); // Better not be a null string by this point!!
- if(result[0] == '-')
- --chars;
- chars = digits - chars;
- if(chars > 0)
- result.append(static_cast<std::string::size_type>(chars), '0');
- }
- if(showpos && (result[0] != '-'))
- result.insert(0, 1, '+');
- mpfr_free_str(ps);
+ boost::multiprecision::detail::format_float_string(result, e, digits, f);
       return result;
    }
    ~mpfr_float_imp()


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk