diff --git a/include/xprec/ddouble.h b/include/xprec/ddouble.h index 51c6726..9d9b52c 100644 --- a/include/xprec/ddouble.h +++ b/include/xprec/ddouble.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "version.h" @@ -297,6 +298,7 @@ bool isinf(DDouble x); bool isnan(DDouble x); bool isnormal(DDouble x); bool iszero(DDouble x); +std::string to_string(DDouble d, size_t nDigits = 34); /** * Gauss-Chebyshev quadrature rule. diff --git a/src/io.cxx b/src/io.cxx index d810444..41603f0 100644 --- a/src/io.cxx +++ b/src/io.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #ifndef XPREC_API_EXPORT #define XPREC_API_EXPORT @@ -58,4 +59,65 @@ std::ostream &operator<<(std::ostream &out, DDouble x) return out; } +XPREC_API_EXPORT +std::string to_string(DDouble d, size_t nDigits){ + using namespace std; + + //Get some basic cases out of the way. + if(d.hi() == 0.0) + return "0.0"; + + if(isnan(d.hi())) + return "NaN"; + + if(isinf(d.hi())) + if(d.hi() > 0.0) + return "Inf"; + else + return "-Inf"; + + + //Alright. Get a string started. Handle sign. + string s; + + if(d.hi() < 0.0) s += "-"; + d = abs(d); + + + //Get the initial tens place and reduce d by it. This way, d becomes digit.nextdigits. + auto n = (int)floor(log10(d.hi())); + if(n < 0) n++; + + constexpr DDouble Ten = 10.0; + d /= pow(Ten, n); + + //Loop over digits, print them. + nDigits = min(max(nDigits, (size_t)3), (size_t)34); + + for(size_t i = 0; i != nDigits; i++){ + if(i == 1) s += "."; + + //Current digit to print is just the leading one. + auto m = (int)floor(d.hi()); + assert(m >= 0 && m < 10); + + s += std::to_string(m); + + //Remove leading digit, promote by ten to retain the digit.nextdigits form. + d = (d - DDouble(m))*Ten; + + //Emptied it - nothing more to print. + if(d.hi() == 0.0) + break; + + assert(d.hi() > 0.0); + } + + //Assuming you care more about the mantissa... always use exponential form. n == 0 imples e0. + if(n != 0) + s += "e" + to_string(n); + + return s; +} + } /* namespace xprec */