Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #1653 from strk/master-float-scientific

Implement scientific notation for double-to-string
  • Loading branch information...
commit e7891a99ce61caf39bc624d63eedbf9e77c2fd5f 2 parents c7ed1f9 + e8b7b82
@artemp artemp authored
View
74 include/mapnik/util/conversions.hpp
@@ -70,12 +70,80 @@ template <typename T>
struct double_policy : boost::spirit::karma::real_policies<T>
{
typedef boost::spirit::karma::real_policies<T> base_type;
- static int floatfield(T n) { return base_type::fmtflags::fixed; }
- static unsigned precision(T n) { return static_cast<unsigned>(15 - boost::math::trunc(log10(n))); }
+
+ static int floatfield(T n) {
+ using namespace boost::spirit; // for traits
+
+ if (traits::test_zero(n))
+ return base_type::fmtflags::fixed;
+
+ T abs_n = traits::get_absolute_value(n);
+ return (abs_n >= 1e16 || abs_n < 1e-4)
+ ? base_type::fmtflags::scientific : base_type::fmtflags::fixed;
+ }
+
+ static unsigned precision(T n) {
+ if ( n == 0.0 ) return 0;
+ using namespace boost::spirit; // for traits
+ return static_cast<unsigned>(15 - boost::math::trunc(log10(traits::get_absolute_value(n))));
+ }
+
template <typename OutputIterator>
static bool dot(OutputIterator& sink, T n, unsigned precision) {
- return n ? *sink = '.', true : false;
+ if (n == 0.0) return true; // avoid trailing zeroes
+ return base_type::dot(sink, n, precision);
+ }
+
+ template <typename OutputIterator>
+ static bool fraction_part (OutputIterator& sink, T n
+ , unsigned precision_, unsigned precision)
+ {
+ // NOTE: copied from karma only to avoid trailing zeroes
+ // (maybe a bug ?)
+
+ // allow for ADL to find the correct overload for floor and log10
+ using namespace std;
+
+ using namespace boost::spirit; // for traits
+ using namespace boost::spirit::karma; // for char_inserter
+ using namespace boost; // for remove_const
+
+ if ( traits::test_zero(n) ) return true; // this part added to karma
+
+ // The following is equivalent to:
+ // generate(sink, right_align(precision, '0')[ulong], n);
+ // but it's spelled out to avoid inter-modular dependencies.
+
+ typename remove_const<T>::type digits =
+ (traits::test_zero(n) ? 0 : floor(log10(n))) + 1;
+ bool r = true;
+ for (/**/; r && digits < precision_; digits = digits + 1)
+ r = char_inserter<>::call(sink, '0');
+ if (precision && r)
+ r = int_inserter<10>::call(sink, n);
+ return r;
}
+
+ template <typename CharEncoding, typename Tag, typename OutputIterator>
+ static bool exponent (OutputIterator& sink, long n)
+ {
+ // NOTE: copied from karma to force sign in exponent
+ const bool force_sign = true;
+
+ using namespace boost::spirit; // for traits
+ using namespace boost::spirit::karma; // for char_inserter, sign_inserter
+
+ long abs_n = traits::get_absolute_value(n);
+ bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') &&
+ sign_inserter::call(sink, traits::test_zero(n)
+ , traits::test_negative(n), force_sign);
+
+ // the C99 Standard requires at least two digits in the exponent
+ if (r && abs_n < 10)
+ r = char_inserter<CharEncoding, Tag>::call(sink, '0');
+ return r && int_inserter<10>::call(sink, abs_n);
+ }
+
};
View
4 tests/cpp_tests/conversions_test.cpp
@@ -49,11 +49,11 @@ int main( int, char*[] )
out.clear();
to_string(out, double(1e-05));
- BOOST_TEST_EQ( out, "0.00001" );
+ BOOST_TEST_EQ( out, "1e-05" );
out.clear();
to_string(out, double(-1e-05));
- BOOST_TEST_EQ( out, "-0.00001" );
+ BOOST_TEST_EQ( out, "-1e-05" );
out.clear();
to_string(out, double(0.0001));
Please sign in to comment.
Something went wrong with that request. Please try again.