|
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