Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r73569 - in sandbox/e_float: boost/e_float libs/e_float/src/e_float libs/e_float/src/e_float/efx libs/e_float/src/e_float/mpfr
From: e_float_at_[hidden]
Date: 2011-08-06 05:44:38


Author: christopher_kormanyos
Date: 2011-08-06 05:44:37 EDT (Sat, 06 Aug 2011)
New Revision: 73569
URL: http://svn.boost.org/trac/boost/changeset/73569

Log:
- Removed the write-string code from multiple places in the big-number back-ends to a single place in the base class.
- This reduces code complexity and sources of possible error.
Text files modified:
   sandbox/e_float/boost/e_float/e_float_base.hpp | 14 +
   sandbox/e_float/boost/e_float/e_float_efx.hpp | 33 ++---
   sandbox/e_float/boost/e_float/e_float_mpfr.hpp | 36 ++----
   sandbox/e_float/libs/e_float/src/e_float/e_float_base.cpp | 135 +++++++++++++++++++++++++
   sandbox/e_float/libs/e_float/src/e_float/efx/e_float_efx.cpp | 154 ++++------------------------
   sandbox/e_float/libs/e_float/src/e_float/mpfr/e_float_mpfr.cpp | 213 +++++++++------------------------------
   6 files changed, 248 insertions(+), 337 deletions(-)

Modified: sandbox/e_float/boost/e_float/e_float_base.hpp
==============================================================================
--- sandbox/e_float/boost/e_float/e_float_base.hpp (original)
+++ sandbox/e_float/boost/e_float/e_float_base.hpp 2011-08-06 05:44:37 EDT (Sat, 06 Aug 2011)
@@ -107,7 +107,7 @@
     virtual e_float_base& operator--(void) = 0;
 
     // Argument range and check functions
- virtual INT64 order(void) const = 0;
+ INT64 order(void) const { return get_order_approximate(); }
 
     // Conversion routines
     virtual void extract_parts (double&, INT64&) const = 0;
@@ -117,7 +117,7 @@
     virtual e_float extract_decimal_part(void) const = 0;
 
     // Formated Output routine.
- virtual void wr_string(std::string&, std::ostream&) const = 0;
+ void wr_string(std::string& str, std::ostream& os) const;
     virtual bool rd_string(const char* const) = 0;
 
     // Specific higher functions which might be present in the MP implementation.
@@ -174,6 +174,13 @@
 
     static bool char_is_nonzero_predicate(const char& c) { return (c != static_cast<char>('0')); }
 
+ private:
+ static bool digits_match_lib_dll_is_ok;
+
+ virtual INT64 get_order_exact(void) const = 0;
+ virtual INT64 get_order_approximate(void) const = 0;
+ virtual void get_output_string(std::string& str, INT64& my_exp, const std::size_t number_of_digits) const = 0;
+
     static void wr_string_scientific(std::string& str,
                                       const INT64 my_exp,
                                       const std::size_t os_precision,
@@ -186,9 +193,6 @@
                                 const std::size_t os_precision,
                                 const bool my_showpoint,
                                 const bool trim_trailing_zeros = false);
-
- private:
- static bool digits_match_lib_dll_is_ok;
   };
 
   // Create a loud link error if the digits in the

Modified: sandbox/e_float/boost/e_float/e_float_efx.hpp
==============================================================================
--- sandbox/e_float/boost/e_float/e_float_efx.hpp (original)
+++ sandbox/e_float/boost/e_float/e_float_efx.hpp 2011-08-06 05:44:37 EDT (Sat, 06 Aug 2011)
@@ -94,18 +94,6 @@
 
       virtual ~e_float() { }
 
- private:
- static bool data_elem_is_nonzero_predicate(const UINT32& d) { return (d != static_cast<UINT32>(0u)); }
-
- void from_unsigned_long_long(const unsigned long long u);
- void from_unsigned_long(const unsigned long u);
-
- INT32 cmp_data(const array_type& vd) const;
-
- static void mul_loop_uv(const UINT32* const u, const UINT32* const v, UINT32* const w, const INT32 p);
- static UINT32 mul_loop_n (UINT32* const u, UINT32 n, const INT32 p);
- static UINT32 div_loop_n (UINT32* const u, UINT32 n, const INT32 p);
-
     public:
       virtual INT32 cmp(const e_float& v) const;
 
@@ -153,15 +141,24 @@
       virtual e_float extract_integer_part(void) const;
       virtual e_float extract_decimal_part(void) const;
 
- // Argument range and check functions
- virtual INT64 order(void) const { return (iszero() ? static_cast<INT64>(0)
- : static_cast<INT64>(exp + static_cast<INT64>(::log10(static_cast<double>(data[0])) + 0.5))); }
-
     private:
- virtual void wr_string(std::string& str, std::ostream& os) const;
+ static bool data_elem_is_nonzero_predicate(const UINT32& d) { return (d != static_cast<UINT32>(0u)); }
+
+ void from_unsigned_long_long(const unsigned long long u);
+ void from_unsigned_long(const unsigned long u);
+
+ INT32 cmp_data(const array_type& vd) const;
+
+ static void mul_loop_uv(const UINT32* const u, const UINT32* const v, UINT32* const w, const INT32 p);
+ static UINT32 mul_loop_n (UINT32* const u, UINT32 n, const INT32 p);
+ static UINT32 div_loop_n (UINT32* const u, UINT32 n, const INT32 p);
+
+ virtual INT64 get_order_exact(void) const;
+ virtual INT64 get_order_approximate(void) const;
+ virtual void get_output_string(std::string& str, INT64& my_exp, const std::size_t number_of_digits) const;
+
       virtual bool rd_string(const char* const s);
 
- static void round_output_string(std::string& str, INT64& my_exp, const std::size_t number_of_digits);
     };
   }
 

Modified: sandbox/e_float/boost/e_float/e_float_mpfr.hpp
==============================================================================
--- sandbox/e_float/boost/e_float/e_float_mpfr.hpp (original)
+++ sandbox/e_float/boost/e_float/e_float_mpfr.hpp 2011-08-06 05:44:37 EDT (Sat, 06 Aug 2011)
@@ -65,7 +65,6 @@
     class e_float : public ::e_float_base
     {
     public:
-
       static const INT32 ef_digits = static_cast<INT32>(((static_cast<INT64>(ef_digits10) * 3322LL) + 500LL) / 1000LL);
       static const INT32 ef_radix = 2;
 
@@ -75,13 +74,10 @@
       static const INT64 ef_min_exp10 = static_cast<INT64>(-323228496LL);
 
     private:
-
       static const INT32 ef_digits2 = static_cast<INT32>(((static_cast<INT64>(ef_digits10_tol) * 3322LL) + 500LL) / 1000LL);
-
       ::mpfr_t rop;
 
     public:
-
       e_float();
       e_float(const char n);
       e_float(const signed char n);
@@ -106,16 +102,6 @@
 
       virtual ~e_float();
 
-
- private:
-
- static void init(void);
-
- void from_unsigned_long_long(const unsigned long long u);
- void from_unsigned_long(const unsigned long u);
-
- public:
-
       virtual INT32 cmp(const e_float& v) const;
 
       virtual const e_float& my_value_nan(void) const;
@@ -158,8 +144,6 @@
       virtual e_float extract_integer_part(void) const;
       virtual e_float extract_decimal_part(void) const;
 
- virtual INT64 order(void) const;
-
       static e_float my_cbrt (const e_float& x);
       static e_float my_rootn (const e_float& x, const UINT32 p);
       static e_float my_exp (const e_float& x);
@@ -181,14 +165,6 @@
       static e_float my_cyl_bessel_jn(const INT32 n, const e_float& x);
       static e_float my_cyl_bessel_yn(const INT32 n, const e_float& x);
 
- private:
-
- static void get_raw_digits_from_scientific_string(std::string& str);
- virtual void wr_string(std::string& str, std::ostream& os) const;
- virtual bool rd_string(const char* const s);
-
- public:
-
       virtual bool has_its_own_cbrt (void) const { return true; }
       virtual bool has_its_own_rootn (void) const { return true; }
       virtual bool has_its_own_exp (void) const { return true; }
@@ -209,6 +185,18 @@
       virtual bool has_its_own_riemann_zeta (void) const { return false; }
       virtual bool has_its_own_cyl_bessel_jn(void) const { return false; }
       virtual bool has_its_own_cyl_bessel_yn(void) const { return false; }
+
+ private:
+ static void init(void);
+
+ void from_unsigned_long_long(const unsigned long long u);
+ void from_unsigned_long(const unsigned long u);
+
+ virtual bool rd_string(const char* const s);
+
+ virtual INT64 get_order_exact(void) const;
+ virtual INT64 get_order_approximate(void) const;
+ virtual void get_output_string(std::string& str, INT64& my_exp, const std::size_t number_of_digits) const;
     };
   }
 

Modified: sandbox/e_float/libs/e_float/src/e_float/e_float_base.cpp
==============================================================================
--- sandbox/e_float/libs/e_float/src/e_float/e_float_base.cpp (original)
+++ sandbox/e_float/libs/e_float/src/e_float/e_float_base.cpp 2011-08-06 05:44:37 EDT (Sat, 06 Aug 2011)
@@ -11,6 +11,17 @@
 #include <e_float/e_float.hpp>
 #include "../utility/util_lexical_cast.h"
 
+namespace
+{
+ typedef enum enum_os_float_field_type
+ {
+ os_float_field_scientific,
+ os_float_field_fixed,
+ os_float_field_none
+ }
+ os_float_filed_type;
+}
+
 bool e_float_base::digits_match_lib_dll_is_ok;
 
 // Create a loud link error if the digits in the
@@ -72,6 +83,130 @@
   if(b_neg) { negate(); } return static_cast<e_float&>(*this);
 }
 
+void e_float_base::wr_string(std::string& str, std::ostream& os) const
+{
+ // Assess the format flags.
+ const std::ios::fmtflags my_flags = os.flags();
+
+ // Obtain the showpos flag.
+ const bool my_showpos = ((my_flags & std::ios::showpos) != static_cast<std::ios::fmtflags>(0u));
+
+ // Handle INF and NaN.
+ if(isnan()) { str = ((!isneg()) ? (my_showpos ? std::string("+INF") : std::string("INF")) : std::string("-INF")); return; }
+ if(isinf()) { str = "INF"; return; }
+
+ // Get the base-10 exponent.
+ INT64 my_exp = get_order_exact();
+
+ // Get the output stream's precision and limit it to max_digits10.
+ // Erroneous negative precision will be set to the zero.
+ const std::size_t os_precision = ((os.precision() > std::streamsize(-1)) ? static_cast<std::size_t>(os.precision())
+ : static_cast<std::size_t>(0u));
+
+ // Determine the kind of output format requested (scientific, fixed, none).
+ os_float_filed_type my_float_field;
+
+ if ((my_flags & std::ios::scientific) != static_cast<std::ios::fmtflags>(0u)) { my_float_field = os_float_field_scientific; }
+ else if((my_flags & std::ios::fixed) != static_cast<std::ios::fmtflags>(0u)) { my_float_field = os_float_field_fixed; }
+ else { my_float_field = os_float_field_none; }
+
+ bool use_scientific = false;
+ bool use_fixed = false;
+
+ if (my_float_field == os_float_field_scientific) { use_scientific = true; }
+ else if(my_float_field == os_float_field_fixed) { use_fixed = true; }
+ else // os_float_field_none
+ {
+ if(my_exp < static_cast<INT64>(-4))
+ {
+ // The number is small in magnitude with a large, negative exponent.
+ // Use exponential notation.
+ use_scientific = true;
+ }
+ else if(my_exp >= (std::min)(static_cast<INT64>(std::numeric_limits<e_float>::digits10), (std::max)(static_cast<INT64>(os_precision), static_cast<INT64>(7))))
+ {
+ // The number is large in magnitude with a large, positive exponent.
+ // Use exponential notation.
+ use_scientific = true;
+ }
+ else
+ {
+ use_fixed = true;
+ }
+ }
+
+ // Ascertain the number of digits requested from e_float.
+ std::size_t the_number_of_digits_i_want_from_e_float = static_cast<std::size_t>(0u);
+ const std::size_t max10_plus_one = static_cast<std::size_t>(std::numeric_limits<e_float>::max_digits10 + 1);
+
+ if(use_scientific)
+ {
+ // The float-field is scientific. The number of digits is given by
+ // (1 + the ostream's precision), not to exceed (max_digits10 + 1).
+ const std::size_t prec_plus_one = static_cast<std::size_t>(1u + os_precision);
+ the_number_of_digits_i_want_from_e_float = (std::min)(max10_plus_one, prec_plus_one);
+ }
+ else if(use_fixed)
+ {
+ // The float-field is scientific. The number of all-digits depends
+ // on the form of the number.
+
+ if(my_exp >= static_cast<INT64>(0))
+ {
+ // If the number is larger than 1 in absolute value, then the number of
+ // digits is given by the width of the integer part plus the ostream's
+ // precision, not to exceed (max_digits10 + 1).
+ const std::size_t exp_plus_one = static_cast<std::size_t>(my_exp + 1);
+ const std::size_t exp_plus_one_plus_my_precision = static_cast<std::size_t>(exp_plus_one + os_precision);
+
+ the_number_of_digits_i_want_from_e_float = (std::min)(exp_plus_one_plus_my_precision, max10_plus_one);
+ }
+ else
+ {
+ const INT64 exp_plus_one = static_cast<INT64>(my_exp + 1);
+ const INT64 exp_plus_one_plus_my_precision = static_cast<INT64>(exp_plus_one + static_cast<INT64>(os_precision));
+
+ the_number_of_digits_i_want_from_e_float = (std::min)(static_cast<std::size_t>((std::max)(exp_plus_one_plus_my_precision, static_cast<INT64>(0))), max10_plus_one);
+ }
+ }
+
+ // Extract the rounded output string with the desired number of digits.
+ get_output_string(str, my_exp, the_number_of_digits_i_want_from_e_float);
+
+ // Obtain additional format information.
+ const bool my_uppercase = ((my_flags & std::ios::uppercase) != static_cast<std::ios::fmtflags>(0u));
+ const bool my_showpoint = ((my_flags & std::ios::showpoint) != static_cast<std::ios::fmtflags>(0u));
+
+ // Write the output string in the desired format.
+ if (my_float_field == os_float_field_scientific) { wr_string_scientific(str, my_exp, os_precision, my_showpoint, my_uppercase); }
+ else if(my_float_field == os_float_field_fixed) { wr_string_fixed(str, my_exp, os_precision, my_showpoint); }
+ else // os_float_field_none
+ {
+ (use_scientific ? wr_string_scientific(str, my_exp, os_precision, my_showpoint, my_uppercase, true)
+ : wr_string_fixed(str, my_exp, os_precision, my_showpoint, true));
+ }
+
+ // Append the sign.
+ if (isneg()) { str.insert(static_cast<std::size_t>(0u), "-"); }
+ else if(my_showpos) { str.insert(static_cast<std::size_t>(0u), "+"); }
+
+ // Handle std::setw(...), std::setfill(...), std::left, std::right, std::internal.
+ const std::size_t my_width = ((os.width() >= static_cast<std::streamsize>(0)) ? static_cast<std::size_t>(os.width())
+ : static_cast<std::size_t>(0u));
+
+ if(my_width > str.length())
+ {
+ // Get the number of fill characters.
+ const std::size_t n_fill = static_cast<std::size_t>(my_width - str.length());
+
+ // Left-justify is the exception, std::right and std::internal justify right.
+ const bool my_left = ((my_flags & std::ios::left) != static_cast<std::ios::fmtflags>(0u));
+
+ // Justify left or right and insert the fill characters.
+ str.insert((my_left ? str.end() : str.begin()), n_fill, os.fill());
+ }
+}
+
 void e_float_base::wr_string_scientific(std::string& str,
                                         const INT64 my_exp,
                                         const std::size_t os_precision,

Modified: sandbox/e_float/libs/e_float/src/e_float/efx/e_float_efx.cpp
==============================================================================
--- sandbox/e_float/libs/e_float/src/e_float/efx/e_float_efx.cpp (original)
+++ sandbox/e_float/libs/e_float/src/e_float/efx/e_float_efx.cpp 2011-08-06 05:44:37 EDT (Sat, 06 Aug 2011)
@@ -34,14 +34,6 @@
 
 namespace
 {
- typedef enum enum_os_float_field_type
- {
- os_float_field_scientific,
- os_float_field_fixed,
- os_float_field_none
- }
- os_float_filed_type;
-
   // Emphasize: This template class can be used with native floating-point
   // types like float, double and 10-byte long double. Note: It would need
   // to be extended for 16-byte long double because the mantissa would
@@ -1630,102 +1622,43 @@
   return val;
 }
 
-void efx::e_float::wr_string(std::string& str, std::ostream& os) const
+INT64 efx::e_float::get_order_exact(void) const
 {
- // Assess the format flags.
- const std::ios::fmtflags my_flags = os.flags();
-
- // Obtain the showpos flag.
- const bool my_showpos = ((my_flags & std::ios::showpos) != static_cast<std::ios::fmtflags>(0u));
-
- // Handle INF and NaN.
- if(isnan()) { str = ((!isneg()) ? (my_showpos ? std::string("+INF") : std::string("INF")) : std::string("-INF")); return; }
- if(isinf()) { str = "INF"; return; }
-
- // Extract all of the digits from e_float, beginning with the first data element.
- str = Util::lexical_cast(data[0]);
-
- // Readjust the exponent based on the width of the first data element.
- INT64 my_exp = ((!iszero()) ? static_cast<INT64>((exp + static_cast<INT64>(str.length())) - static_cast<INT64>(1))
- : static_cast<INT64>(0));
-
- // Get the output stream's precision and limit it to max_digits10.
- // Erroneous negative precision will be set to the zero.
- const std::size_t os_precision = ((os.precision() > std::streamsize(-1)) ? static_cast<std::size_t>(os.precision())
- : static_cast<std::size_t>(0u));
-
- // Determine the kind of output format requested (scientific, fixed, none).
- os_float_filed_type my_float_field;
-
- if ((my_flags & std::ios::scientific) != static_cast<std::ios::fmtflags>(0u)) { my_float_field = os_float_field_scientific; }
- else if((my_flags & std::ios::fixed) != static_cast<std::ios::fmtflags>(0u)) { my_float_field = os_float_field_fixed; }
- else { my_float_field = os_float_field_none; }
-
- bool use_scientific = false;
- bool use_fixed = false;
-
- if (my_float_field == os_float_field_scientific) { use_scientific = true; }
- else if(my_float_field == os_float_field_fixed) { use_fixed = true; }
- else // os_float_field_none
+ if(iszero())
   {
- if(my_exp < static_cast<INT64>(-4))
- {
- // The number is small in magnitude with a large, negative exponent.
- // Use exponential notation.
- use_scientific = true;
- }
- else if(my_exp >= (std::min)(static_cast<INT64>(std::numeric_limits<e_float>::digits10), (std::max)(static_cast<INT64>(os_precision), static_cast<INT64>(7))))
- {
- // The number is large in magnitude with a large, positive exponent.
- // Use exponential notation.
- use_scientific = true;
- }
- else
- {
- use_fixed = true;
- }
+ return static_cast<INT64>(0);
   }
+ else
+ {
+ const std::string str = Util::lexical_cast(data[0]);
+ const INT64 str_len_minus_one = static_cast<INT64>(static_cast<INT64>(str.length()) - static_cast<INT64>(1));
+ return static_cast<INT64>(exp + str_len_minus_one);
+ }
+}
 
- // Ascertain the number of digits requested from e_float.
- std::size_t the_number_of_digits_i_want_from_e_float = static_cast<std::size_t>(0u);
- const std::size_t max10_plus_one = static_cast<std::size_t>(std::numeric_limits<e_float>::max_digits10 + 1);
-
- if(use_scientific)
+INT64 efx::e_float::get_order_approximate(void) const
+{
+ if(iszero())
   {
- // The float-field is scientific. The number of digits is given by
- // (1 + the ostream's precision), not to exceed (max_digits10 + 1).
- const std::size_t prec_plus_one = static_cast<std::size_t>(1u + os_precision);
- the_number_of_digits_i_want_from_e_float = (std::min)(max10_plus_one, prec_plus_one);
+ return static_cast<INT64>(0);
   }
- else if(use_fixed)
+ else
   {
- // The float-field is scientific. The number of all-digits depends
- // on the form of the number.
-
- if(my_exp >= static_cast<INT64>(0))
- {
- // If the number is larger than 1 in absolute value, then the number of
- // digits is given by the width of the integer part plus the ostream's
- // precision, not to exceed (max_digits10 + 1).
- const std::size_t exp_plus_one = static_cast<std::size_t>(my_exp + 1);
- const std::size_t exp_plus_one_plus_my_precision = static_cast<std::size_t>(exp_plus_one + os_precision);
-
- the_number_of_digits_i_want_from_e_float = (std::min)(exp_plus_one_plus_my_precision, max10_plus_one);
- }
- else
- {
- const INT64 exp_plus_one = static_cast<INT64>(my_exp + 1);
- const INT64 exp_plus_one_plus_my_precision = static_cast<INT64>(exp_plus_one + static_cast<INT64>(os_precision));
-
- the_number_of_digits_i_want_from_e_float = (std::min)(static_cast<std::size_t>((std::max)(exp_plus_one_plus_my_precision, static_cast<INT64>(0))), max10_plus_one);
- }
+ const double dx = ::log10(static_cast<double>(data[0])) + 0.5;
+ return static_cast<INT64>(exp + static_cast<INT64>(dx));
   }
+}
 
+void efx::e_float::get_output_string(std::string& str, INT64& my_exp, const std::size_t number_of_digits) const
+{
   // Determine the number of elements needed to provide the requested digits from e_float.
- const std::size_t number_of_elements = (std::min)(static_cast<std::size_t>((the_number_of_digits_i_want_from_e_float / static_cast<std::size_t>(ef_elem_digits10)) + 2u),
+ const std::size_t number_of_elements = (std::min)(static_cast<std::size_t>((number_of_digits / static_cast<std::size_t>(ef_elem_digits10)) + 2u),
                                                     static_cast<std::size_t>(ef_elem_number));
 
   // Extract the remaining digits from e_float after the decimal point.
+ str = Util::lexical_cast(data[0]);
+
+ // Extract all of the digits from e_float, beginning with the first data element.
   for(std::size_t i = static_cast<std::size_t>(1u); i < number_of_elements; i++)
   {
     std::stringstream ss;
@@ -1737,45 +1670,6 @@
     str += ss.str();
   }
 
- // Trim (and round) the output string to the size of the precision.
- round_output_string(str, my_exp, the_number_of_digits_i_want_from_e_float);
-
- // Obtain additional format information.
- const bool my_uppercase = ((my_flags & std::ios::uppercase) != static_cast<std::ios::fmtflags>(0u));
- const bool my_showpoint = ((my_flags & std::ios::showpoint) != static_cast<std::ios::fmtflags>(0u));
-
- // Write the output string in the desired format.
- if (my_float_field == os_float_field_scientific) { wr_string_scientific(str, my_exp, os_precision, my_showpoint, my_uppercase); }
- else if(my_float_field == os_float_field_fixed) { wr_string_fixed(str, my_exp, os_precision, my_showpoint); }
- else // os_float_field_none
- {
- (use_scientific ? wr_string_scientific(str, my_exp, os_precision, my_showpoint, my_uppercase, true)
- : wr_string_fixed(str, my_exp, os_precision, my_showpoint, true));
- }
-
- // Append the sign.
- if (isneg()) { str.insert(static_cast<std::size_t>(0u), "-"); }
- else if(my_showpos) { str.insert(static_cast<std::size_t>(0u), "+"); }
-
- // Handle std::setw(...), std::setfill(...), std::left, std::right, std::internal.
- const std::size_t my_width = ((os.width() >= static_cast<std::streamsize>(0)) ? static_cast<std::size_t>(os.width())
- : static_cast<std::size_t>(0u));
-
- if(my_width > str.length())
- {
- // Get the number of fill characters.
- const std::size_t n_fill = static_cast<std::size_t>(my_width - str.length());
-
- // Left-justify is the exception, std::right and std::internal justify right.
- const bool my_left = ((my_flags & std::ios::left) != static_cast<std::ios::fmtflags>(0u));
-
- // Justify left or right and insert the fill characters.
- str.insert((my_left ? str.end() : str.begin()), n_fill, os.fill());
- }
-}
-
-void efx::e_float::round_output_string(std::string& str, INT64& my_exp, const std::size_t number_of_digits)
-{
   // Cut the output to the size of the precision.
   if(str.length() > number_of_digits)
   {

Modified: sandbox/e_float/libs/e_float/src/e_float/mpfr/e_float_mpfr.cpp
==============================================================================
--- sandbox/e_float/libs/e_float/src/e_float/mpfr/e_float_mpfr.cpp (original)
+++ sandbox/e_float/libs/e_float/src/e_float/mpfr/e_float_mpfr.cpp 2011-08-06 05:44:37 EDT (Sat, 06 Aug 2011)
@@ -415,76 +415,22 @@
   return ((!b_neg) ? dx : -dx);
 }
 
-INT64 mpfr::e_float::order(void) const
+INT64 mpfr::e_float::get_order_exact(void) const
 {
- const e_float xx = ef::fabs(*this);
-
- if(xx.iszero() || xx.isone())
- {
- return static_cast<INT64>(0);
- }
- else
- {
- signed long int n2;
- const double d2 = ::mpfr_get_d_2exp(&n2, xx.rop, GMP_RNDN);
- const double lg10x = static_cast<double>(::log10(d2) + (static_cast<double>(n2) * ::d_log2()));
-
- return ((lg10x < 0.0) ? static_cast<INT64>(lg10x - 0.5)
- : static_cast<INT64>(lg10x + 0.5));
- }
-}
-
-void mpfr::e_float::get_raw_digits_from_scientific_string(std::string& str)
-{
- // Get the raw digits from a string in scientific notation (lowercase, showpos).
-
- // Erase the negative sign, if present.
- if(str.at(0u) == static_cast<char>('-'))
- {
- str.erase(str.begin(), str.begin() + 1u);
- }
-
- // Erase the exponent.
- const std::size_t pos_letter_e = str.rfind(static_cast<char>('e'));
-
- if(pos_letter_e != std::string::npos)
- {
- str.erase(str.begin() + pos_letter_e, str.end());
- }
-
- // Erase the decimal point.
- const std::size_t pos_decimal_point = str.rfind(static_cast<char>('.'));
-
- if(pos_decimal_point != std::string::npos)
- {
- str.erase(str.begin() + pos_decimal_point, str.begin() + (pos_decimal_point + 1u));
- }
-}
-
-void mpfr::e_float::wr_string(std::string& str, std::ostream& os) const
-{
- // Assess the format flags.
- const std::ios::fmtflags my_flags = os.flags();
-
- // Obtain the showpos flag.
- const bool my_showpos = ((my_flags & std::ios::showpos) != static_cast<std::ios::fmtflags>(0u));
-
- // Handle INF and NaN.
- if(isnan()) { str = "NaN"; return; }
- if(isinf()) { str = ((!isneg()) ? (my_showpos ? std::string("+INF") : std::string("INF")) : std::string("-INF")); return; }
+ // Get the order-10 of the e_float. This is done using a partial
+ // string extraction with 10 decimal digits.
 
-
- // Get the order-10 of the e_float. This is done using a partial string
- // extraction with 10 decimal digits.
   // Create a format string for 10-digits and scientific notation.
   std::string str_fmt = std::string("%.10RNe");
 
   // Get the ten digits.
- std::tr1::array<char, static_cast<std::size_t>(e_float::ef_digits10_tol + 32)> buf = {{ static_cast<char>(0) }};
+ std::tr1::array<char, 64u> buf = {{ static_cast<char>(0) }};
+
   ::mpfr_sprintf(buf.data(), str_fmt.c_str(), rop);
- str = std::string(buf.data());
 
- // Extract the exponent.
+ const std::string str = std::string(buf.data());
+
+ // Extract the base-10 exponent.
   INT64 my_exp;
 
   const std::size_t pos_letter_e = str.rfind(static_cast<char>('e'));
@@ -492,7 +438,7 @@
   if(pos_letter_e != std::string::npos)
   {
     std::stringstream ss;
- ss << (str.c_str() + (pos_letter_e + 1u));
+ ss << static_cast<const char*>(str.c_str() + (pos_letter_e + 1u));
     ss >> my_exp;
   }
   else
@@ -500,125 +446,72 @@
     my_exp = static_cast<INT64>(0);
   }
 
- // Get the output stream's precision and limit it to max_digits10.
- // Erroneous negative precision will be set to the zero.
- const std::size_t os_precision = ((os.precision() > std::streamsize(-1)) ? static_cast<std::size_t>(os.precision())
- : static_cast<std::size_t>(0u));
-
- // Determine the kind of output format requested (scientific, fixed, none).
- os_float_filed_type my_float_field;
-
- if ((my_flags & std::ios::scientific) != static_cast<std::ios::fmtflags>(0u)) { my_float_field = os_float_field_scientific; }
- else if((my_flags & std::ios::fixed) != static_cast<std::ios::fmtflags>(0u)) { my_float_field = os_float_field_fixed; }
- else { my_float_field = os_float_field_none; }
-
- bool use_scientific = false;
- bool use_fixed = false;
-
- if (my_float_field == os_float_field_scientific) { use_scientific = true; }
- else if(my_float_field == os_float_field_fixed) { use_fixed = true; }
- else // os_float_field_none
- {
- if(my_exp < static_cast<INT64>(-4))
- {
- // The number is small in magnitude with a large, negative exponent.
- // Use exponential notation.
- use_scientific = true;
- }
- else if(my_exp >= (std::min)(static_cast<INT64>(std::numeric_limits<e_float>::digits10), (std::max)(static_cast<INT64>(os_precision), static_cast<INT64>(7))))
- {
- // The number is large in magnitude with a large, positive exponent.
- // Use exponential notation.
- use_scientific = true;
- }
- else
- {
- use_fixed = true;
- }
- }
-
- // Ascertain the number of digits requested from e_float.
- std::size_t the_number_of_digits_i_want_from_e_float = static_cast<std::size_t>(0u);
- const std::size_t max10_plus_one = static_cast<std::size_t>(std::numeric_limits<e_float>::max_digits10 + 1);
-
- if(use_scientific)
- {
- // The float-field is scientific. The number of digits is given by
- // (1 + the ostream's precision), not to exceed (max_digits10 + 1).
- const std::size_t prec_plus_one = static_cast<std::size_t>(1u + os_precision);
- the_number_of_digits_i_want_from_e_float = (std::min)(max10_plus_one, prec_plus_one);
- }
- else if(use_fixed)
- {
- // The float-field is scientific. The number of all-digits depends
- // on the form of the number.
-
- if(my_exp >= static_cast<INT64>(0))
- {
- // If the number is larger than 1 in absolute value, then the number of
- // digits is given by the width of the integer part plus the ostream's
- // precision, not to exceed (max_digits10 + 1).
- const std::size_t exp_plus_one = static_cast<std::size_t>(my_exp + 1);
- const std::size_t exp_plus_one_plus_my_precision = static_cast<std::size_t>(exp_plus_one + os_precision);
-
- the_number_of_digits_i_want_from_e_float = (std::min)(exp_plus_one_plus_my_precision, max10_plus_one);
- }
- else
- {
- const INT64 exp_plus_one = static_cast<INT64>(my_exp + 1);
- const INT64 exp_plus_one_plus_my_precision = static_cast<INT64>(exp_plus_one + static_cast<INT64>(os_precision));
+ return my_exp;
+}
+
+INT64 mpfr::e_float::get_order_approximate(void) const
+{
+ const e_float xx = ef::fabs(*this);
 
- the_number_of_digits_i_want_from_e_float = (std::min)(static_cast<std::size_t>((std::max)(exp_plus_one_plus_my_precision, static_cast<INT64>(0))), max10_plus_one);
- }
+ if(xx.iszero() || xx.isone())
+ {
+ return static_cast<INT64>(0);
   }
+ else
+ {
+ signed long int n2;
+ const double d2 = ::mpfr_get_d_2exp(&n2, xx.rop, GMP_RNDN);
+ const double lg10x = static_cast<double>(::log10(d2) + (static_cast<double>(n2) * ::d_log2()));
+
+ return ((lg10x < 0.0) ? static_cast<INT64>(lg10x - 0.5)
+ : static_cast<INT64>(lg10x + 0.5));
+ }
+}
+
+void mpfr::e_float::get_output_string(std::string& str, INT64& my_exp, const std::size_t number_of_digits) const
+{
+ static_cast<void>(my_exp);
 
   // Create a format string such as "%+.99RNe" in order to extract 100 digits
   // in scientific notation with the lowercase and noshowpos flags.
- const std::size_t the_number_of_digits_scientific = static_cast<std::size_t>((std::max)(the_number_of_digits_i_want_from_e_float, static_cast<std::size_t>(1u)) - static_cast<std::size_t>(1u));
- str_fmt = std::string("%.") + (Util::lexical_cast(the_number_of_digits_scientific) + "RNe");
+ const std::size_t the_number_of_digits_scientific = static_cast<std::size_t>((std::max)(number_of_digits, static_cast<std::size_t>(1u)) - static_cast<std::size_t>(1u));
+
+ const std::string str_fmt = std::string("%.") + (Util::lexical_cast(the_number_of_digits_scientific) + "RNe");
 
   // Get the string representation of the e_float in scientific notation (lowercase, noshowpos).
- std::fill(buf.begin(), buf.end(), static_cast<char>(0));
+ std::tr1::array<char, static_cast<std::size_t>(e_float::ef_digits10_tol + 32)> buf = {{ static_cast<char>(0) }};
+
   ::mpfr_sprintf(buf.data(), str_fmt.c_str(), rop);
+
   str = std::string(buf.data());
 
   // Obtain the raw digits from the scientific notation string.
+
   // TBD: Well, this is a bit silly. First get the string in
   // scientific notation, then reduce it to raw digits.
   // Perhaps this can be improved.
- get_raw_digits_from_scientific_string(str);
-
- // Obtain additional format information.
- const bool my_uppercase = ((my_flags & std::ios::uppercase) != static_cast<std::ios::fmtflags>(0u));
- const bool my_showpoint = ((my_flags & std::ios::showpoint) != static_cast<std::ios::fmtflags>(0u));
+ // Get the raw digits from a string in scientific notation (lowercase, showpos).
 
- // Write the output string in the desired format.
- if (my_float_field == os_float_field_scientific) { wr_string_scientific(str, my_exp, os_precision, my_showpoint, my_uppercase); }
- else if(my_float_field == os_float_field_fixed) { wr_string_fixed(str, my_exp, os_precision, my_showpoint); }
- else // os_float_field_none
+ // Erase the negative sign, if present.
+ if(str.at(0u) == static_cast<char>('-'))
   {
- (use_scientific ? wr_string_scientific(str, my_exp, os_precision, my_showpoint, my_uppercase, true)
- : wr_string_fixed(str, my_exp, os_precision, my_showpoint, true));
+ str.erase(str.begin(), str.begin() + 1u);
   }
 
- // Append the sign.
- if (isneg()) { str.insert(static_cast<std::size_t>(0u), "-"); }
- else if(my_showpos) { str.insert(static_cast<std::size_t>(0u), "+"); }
-
- // Handle std::setw(...), std::setfill(...), std::left, std::right, std::internal.
- const std::size_t my_width = ((os.width() >= static_cast<std::streamsize>(0)) ? static_cast<std::size_t>(os.width())
- : static_cast<std::size_t>(0u));
+ // Erase the exponent.
+ const std::size_t pos_letter_e = str.rfind(static_cast<char>('e'));
 
- if(my_width > str.length())
+ if(pos_letter_e != std::string::npos)
   {
- // Get the number of fill characters.
- const std::size_t n_fill = static_cast<std::size_t>(my_width - str.length());
+ str.erase(str.begin() + pos_letter_e, str.end());
+ }
 
- // Left-justify is the exception, std::right and std::internal justify right.
- const bool my_left = ((my_flags & std::ios::left) != static_cast<std::ios::fmtflags>(0u));
+ // Erase the decimal point.
+ const std::size_t pos_decimal_point = str.rfind(static_cast<char>('.'));
 
- // Justify left or right and insert the fill characters.
- str.insert((my_left ? str.end() : str.begin()), n_fill, os.fill());
+ if(pos_decimal_point != std::string::npos)
+ {
+ str.erase(str.begin() + pos_decimal_point, str.begin() + (pos_decimal_point + 1u));
   }
 }
 


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