Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r67558 - in trunk: boost/units libs/units/test
From: steven_at_[hidden]
Date: 2011-01-01 21:33:16


Author: steven_watanabe
Date: 2011-01-01 21:33:14 EST (Sat, 01 Jan 2011)
New Revision: 67558
URL: http://svn.boost.org/trac/boost/changeset/67558

Log:
Don't require std::abs for printing quantities. Fix test_output on Linux. Fixes #4785.
Text files modified:
   trunk/boost/units/io.hpp | 83 ++++++++++++++++++++++++++++++---------
   trunk/libs/units/test/Jamfile.v2 | 2
   trunk/libs/units/test/test_output.cpp | 52 ++++++++++++++++++------
   3 files changed, 103 insertions(+), 34 deletions(-)

Modified: trunk/boost/units/io.hpp
==============================================================================
--- trunk/boost/units/io.hpp (original)
+++ trunk/boost/units/io.hpp 2011-01-01 21:33:14 EST (Sat, 01 Jan 2011)
@@ -649,17 +649,55 @@
 
 // For automatically applying the appropriate prefixes.
 
+}
+
+#ifdef BOOST_UNITS_DOXYGEN
+
+/// ADL customization point for automatic prefixing.
+/// Returns a non-negative value. Implemented as std::abs
+/// for built-in types.
+template<class T>
+double autoprefix_norm(const T& arg);
+
+#else
+
+template<class T, bool C = boost::is_arithmetic<T>::value>
+struct autoprefix_norm_impl;
+
+template<class T>
+struct autoprefix_norm_impl<T, true>
+{
+ typedef double type;
+ static double call(const T& arg) { return std::abs(arg); }
+};
+
+template<class T>
+struct autoprefix_norm_impl<T, false>
+{
+ typedef one type;
+ static one call(const T&) { return one(); }
+};
+
+template<class T>
+typename autoprefix_norm_impl<T>::type autoprefix_norm(const T& arg)
+{
+ return autoprefix_norm_impl<T>::call(arg);
+}
+
+#endif
+
+namespace detail {
+
 template<class End, class Prev, class T, class F>
-bool find_matching_scale_impl(End, End, Prev, T, F)
+bool find_matching_scale_impl(End, End, Prev, T, double, F)
 {
     return false;
 }
 
 template<class Begin, class End, class Prev, class T, class F>
-bool find_matching_scale_impl(Begin, End end, Prev prev, T t, F f)
+bool find_matching_scale_impl(Begin, End end, Prev prev, T t, double x, F f)
 {
- using std::abs;
- if(Begin::item::value() > abs(t)) {
+ if(Begin::item::value() > x) {
         f(prev, t);
         return true;
     } else {
@@ -668,32 +706,32 @@
             end,
             typename Begin::item(),
             t,
+ x,
             f
         );
     }
 }
 
 template<class End, class T, class F>
-bool find_matching_scale_i(End, End, T, F)
+bool find_matching_scale_i(End, End, T, double, F)
 {
     return false;
 }
 
 template<class Begin, class End, class T, class F>
-bool find_matching_scale_i(Begin, End end, T t, F f)
+bool find_matching_scale_i(Begin, End end, T t, double x, F f)
 {
- using std::abs;
- if(Begin::item::value() > abs(t)) {
+ if(Begin::item::value() > x) {
         return false;
     } else {
- return detail::find_matching_scale_impl(typename Begin::next(), end, typename Begin::item(), t, f);
+ return detail::find_matching_scale_impl(typename Begin::next(), end, typename Begin::item(), t, x, f);
     }
 }
 
 template<class Scales, class T, class F>
-bool find_matching_scale(T t, F f)
+bool find_matching_scale(T t, double x, F f)
 {
- return detail::find_matching_scale_i(Scales(), dimensionless_type(), t, f);
+ return detail::find_matching_scale_i(Scales(), dimensionless_type(), t, x, f);
 }
 
 typedef list<scale<10, static_rational<-24> >,
@@ -814,7 +852,7 @@
 void do_print_prefixed_impl(std::basic_ostream<CharT, Traits>& os, const quantity<Unit, T>& q, F default_)
 {
     bool prefixed;
- if(detail::find_matching_scale<Prefixes>(q.value(), detail::print_scale(os, prefixed))) {
+ if(detail::find_matching_scale<Prefixes>(q.value(), autoprefix_norm(q.value()), detail::print_scale(os, prefixed))) {
         if(prefixed) {
             switch(units::get_format(os)) {
                 case symbol_fmt: do_print(os, maybe_parenthesize(Unit(), format_symbol_impl())); break;
@@ -857,7 +895,8 @@
>
>,
         T
- >& q)
+ >& q,
+ mpl::true_)
 {
     quantity<
         unit<
@@ -893,7 +932,8 @@
>
>,
         T
- >& q)
+ >& q,
+ mpl::true_)
 {
     quantity<
         unit<
@@ -912,17 +952,20 @@
 }
 
 template<class Prefixes, class CharT, class Traits, class Dimension, class System, class T>
-void do_print_prefixed(std::basic_ostream<CharT, Traits>& os, const quantity<unit<Dimension, System>, T>& q)
+void do_print_prefixed(std::basic_ostream<CharT, Traits>& os, const quantity<unit<Dimension, System>, T>& q, mpl::true_ norm_test)
 {
- detail::do_print_prefixed<Prefixes>(os, quantity<unit<Dimension, typename make_heterogeneous_system<Dimension, System>::type>, T>(q));
+ detail::do_print_prefixed<Prefixes>(os, quantity<unit<Dimension, typename make_heterogeneous_system<Dimension, System>::type>, T>(q), norm_test);
 }
 
-template<class Prefixes, class CharT, class Traits, class Unit, class T>
-void do_print_prefixed(std::basic_ostream<CharT, Traits>& os, const quantity<Unit, T>& q)
+template<class Prefixes, class CharT, class Traits, class Unit, class T, class NormTest>
+void do_print_prefixed(std::basic_ostream<CharT, Traits>& os, const quantity<Unit, T>& q, NormTest)
 {
     detail::print_default(os, q)();
 }
 
+inline mpl::true_ test_norm(double) { return mpl::true_(); }
+inline mpl::false_ test_norm(one) { return mpl::false_(); }
+
 } // namespace detail
 
 template<class Dimension,class System>
@@ -994,11 +1037,11 @@
     }
     else if (units::get_autoprefix(os) == autoprefix_engineering)
     {
- detail::do_print_prefixed<detail::engineering_prefixes>(os, q);
+ detail::do_print_prefixed<detail::engineering_prefixes>(os, q, detail::test_norm(autoprefix_norm(q.value())));
     }
     else if (units::get_autoprefix(os) == autoprefix_binary)
     {
- detail::do_print_prefixed<detail::binary_prefixes>(os, q);
+ detail::do_print_prefixed<detail::binary_prefixes>(os, q, detail::test_norm(autoprefix_norm(q.value())));
     }
     else
     {

Modified: trunk/libs/units/test/Jamfile.v2
==============================================================================
--- trunk/libs/units/test/Jamfile.v2 (original)
+++ trunk/libs/units/test/Jamfile.v2 2011-01-01 21:33:14 EST (Sat, 01 Jan 2011)
@@ -52,7 +52,7 @@
 run test_scaled_conversion.cpp ;
 run test_lambda.cpp ;
 run test_scaled_unit.cpp test_framework ;
-run test_output.cpp test_framework ;
+run test_output.cpp test_framework /boost//regex ;
 run test_trig.cpp test_framework ;
 
 compile-fail fail_implicit_conversion.cpp ;

Modified: trunk/libs/units/test/test_output.cpp
==============================================================================
--- trunk/libs/units/test/test_output.cpp (original)
+++ trunk/libs/units/test/test_output.cpp 2011-01-01 21:33:14 EST (Sat, 01 Jan 2011)
@@ -33,6 +33,8 @@
 #include <boost/units/physical_dimensions/acceleration.hpp>
 #include <boost/units/physical_dimensions/area.hpp>
 
+#include <boost/regex.hpp>
+
 #include <sstream>
 #include <boost/config.hpp>
 #include <limits>
@@ -115,6 +117,21 @@
     BOOST_CHECK(ss.str() == BOOST_PP_CAT(L, expected)); \
 }
 
+#define BOOST_UNITS_TEST_OUTPUT_REGEX(v, expected) \
+{ \
+ std::ostringstream ss; \
+ ss FORMATTERS << v; \
+ boost::regex r(expected); \
+ BOOST_CHECK_MESSAGE(boost::regex_match(ss.str(), r), \
+ ss.str() + " does not match " + expected); \
+} \
+{ \
+ std::wostringstream ss; \
+ ss FORMATTERS << v; \
+ boost::wregex r(BOOST_PP_CAT(L, expected)); \
+ BOOST_CHECK(boost::regex_match(ss.str(), r)); \
+}
+
 #else
 
 #define BOOST_UNITS_TEST_OUTPUT(v, expected) \
@@ -124,6 +141,15 @@
     BOOST_CHECK_EQUAL(ss.str(), expected); \
 }
 
+#define BOOST_UNITS_TEST_OUTPUT_REGEX(v, expected) \
+{ \
+ std::ostringstream ss; \
+ ss FORMATTERS << v; \
+ boost::regex r(expected); \
+ BOOST_CHECK_MESSAGE(boost::regex_match(ss.str(), r), \
+ ss.str() + " does not match " + expected); \
+}
+
 #endif
 
 BOOST_AUTO_TEST_CASE(test_output_unit_symbol)
@@ -277,13 +303,13 @@
     BOOST_UNITS_TEST_OUTPUT(0.0000000012345 * meter_base_unit::unit_type(), "1.2345 nanometer");
 
   // Too small or large for a multiple name.
- BOOST_UNITS_TEST_OUTPUT(9.99999e-25 * meter_base_unit::unit_type(), "9.99999e-025 meter"); // Just too small for multiple.
- BOOST_UNITS_TEST_OUTPUT(1e+28 * meter_base_unit::unit_type(), "1e+028 meter"); // Just too large for multiple.
- BOOST_UNITS_TEST_OUTPUT(1.5e-25 * meter_base_unit::unit_type(), "1.5e-025 meter"); // Too small for multiple.
- BOOST_UNITS_TEST_OUTPUT(1.5e+28 * meter_base_unit::unit_type(), "1.5e+028 meter"); // Too large for multiple.
+ BOOST_UNITS_TEST_OUTPUT_REGEX(9.99999e-25 * meter_base_unit::unit_type(), "9\\.99999e-0?25 meter"); // Just too small for multiple.
+ BOOST_UNITS_TEST_OUTPUT_REGEX(1e+28 * meter_base_unit::unit_type(), "1e\\+0?28 meter"); // Just too large for multiple.
+ BOOST_UNITS_TEST_OUTPUT_REGEX(1.5e-25 * meter_base_unit::unit_type(), "1\\.5e-0?25 meter"); // Too small for multiple.
+ BOOST_UNITS_TEST_OUTPUT_REGEX(1.5e+28 * meter_base_unit::unit_type(), "1\\.5e\\+0?28 meter"); // Too large for multiple.
   // Too 'biggest or too smallest'.
- BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<float>::max()*meter_base_unit::unit_type(), "3.40282e+038 meter");
- BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<float>::min()*meter_base_unit::unit_type(), "1.17549e-038 meter");
+ BOOST_UNITS_TEST_OUTPUT_REGEX(std::numeric_limits<float>::max()*meter_base_unit::unit_type(), "3\\.40282e\\+0?38 meter");
+ BOOST_UNITS_TEST_OUTPUT_REGEX(std::numeric_limits<float>::min()*meter_base_unit::unit_type(), "1\\.17549e-0?38 meter");
     BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<double>::max()*meter_base_unit::unit_type(), "1.79769e+308 meter");
     BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<double>::min()*meter_base_unit::unit_type(), "2.22507e-308 meter");
    // Infinity and NaN
@@ -296,7 +322,7 @@
     BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<float>::infinity()*meter_base_unit::unit_type(), "inf meter");
     BOOST_UNITS_TEST_OUTPUT(-std::numeric_limits<float>::infinity()*meter_base_unit::unit_type(), "-inf meter");
     BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<double>::quiet_NaN()*meter_base_unit::unit_type(), "nan meter");
- BOOST_UNITS_TEST_OUTPUT(-std::numeric_limits<double>::quiet_NaN()*meter_base_unit::unit_type(), "nan meter");
+ BOOST_UNITS_TEST_OUTPUT(-std::numeric_limits<double>::quiet_NaN()*meter_base_unit::unit_type(), "-nan meter");
 #else
     // TODO infinity on other platforms?
 #endif
@@ -338,13 +364,13 @@
     BOOST_UNITS_TEST_OUTPUT(1.5e-8*meter_base_unit::unit_type(), "15 nm");
     BOOST_UNITS_TEST_OUTPUT(1.5e-10*meter_base_unit::unit_type(), "150 pm");
   // Too small or large for a multiple name.
- BOOST_UNITS_TEST_OUTPUT(9.99999e-25 * meter_base_unit::unit_type(), "9.99999e-025 m"); // Just too small for multiple.
- BOOST_UNITS_TEST_OUTPUT(1e+28 * meter_base_unit::unit_type(), "1e+028 m"); // Just too large for multiple.
- BOOST_UNITS_TEST_OUTPUT(1.5e-25 * meter_base_unit::unit_type(), "1.5e-025 m"); // Too small for multiple.
- BOOST_UNITS_TEST_OUTPUT(1.5e+28 * meter_base_unit::unit_type(), "1.5e+028 m"); // Too large for multiple.
+ BOOST_UNITS_TEST_OUTPUT_REGEX(9.99999e-25 * meter_base_unit::unit_type(), "9\\.99999e-0?25 m"); // Just too small for multiple.
+ BOOST_UNITS_TEST_OUTPUT_REGEX(1e+28 * meter_base_unit::unit_type(), "1e\\+0?28 m"); // Just too large for multiple.
+ BOOST_UNITS_TEST_OUTPUT_REGEX(1.5e-25 * meter_base_unit::unit_type(), "1\\.5e-0?25 m"); // Too small for multiple.
+ BOOST_UNITS_TEST_OUTPUT_REGEX(1.5e+28 * meter_base_unit::unit_type(), "1\\.5e\\+0?28 m"); // Too large for multiple.
   //
- BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<float>::max()*meter_base_unit::unit_type(), "3.40282e+038 m");
- BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<float>::min()*meter_base_unit::unit_type(), "1.17549e-038 m");
+ BOOST_UNITS_TEST_OUTPUT_REGEX(std::numeric_limits<float>::max()*meter_base_unit::unit_type(), "3\\.40282e\\+0?38 m");
+ BOOST_UNITS_TEST_OUTPUT_REGEX(std::numeric_limits<float>::min()*meter_base_unit::unit_type(), "1\\.17549e-0?38 m");
     BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<double>::max()*meter_base_unit::unit_type(), "1.79769e+308 m");
     BOOST_UNITS_TEST_OUTPUT(std::numeric_limits<double>::min()*meter_base_unit::unit_type(), "2.22507e-308 m");
 


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