diff options
Diffstat (limited to 'boost/units/systems/detail')
-rw-r--r-- | boost/units/systems/detail/constants.hpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/boost/units/systems/detail/constants.hpp b/boost/units/systems/detail/constants.hpp new file mode 100644 index 0000000000..fac9b612cc --- /dev/null +++ b/boost/units/systems/detail/constants.hpp @@ -0,0 +1,201 @@ +// Boost.Units - A C++ library for zero-overhead dimensional analysis and +// unit/quantity manipulation and conversion +// +// Copyright (C) 2003-2008 Matthias Christian Schabel +// Copyright (C) 2008 Steven Watanabe +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_UNITS_CONSTANTS_HPP +#define BOOST_UNITS_CONSTANTS_HPP + +#include <boost/config/no_tr1/cmath.hpp> +#include <iosfwd> +#include <iomanip> + +#include <boost/io/ios_state.hpp> + +#include <boost/units/static_constant.hpp> +#include <boost/units/units_fwd.hpp> +#include <boost/units/operators.hpp> + +namespace boost { + +namespace units { + +template<class Base> +struct constant +{ + typedef typename Base::value_type value_type; + operator value_type() const { return Base().value(); } + value_type value() const { return Base().value(); } + value_type uncertainty() const { return Base().uncertainty(); } + value_type lower_bound() const { return Base().lower_bound(); } + value_type upper_bound() const { return Base().upper_bound(); } +}; + +template<class Base> +struct physical_constant +{ + typedef typename Base::value_type value_type; + operator value_type() const { return Base().value(); } + value_type value() const { return Base().value(); } + value_type uncertainty() const { return Base().uncertainty(); } + value_type lower_bound() const { return Base().lower_bound(); } + value_type upper_bound() const { return Base().upper_bound(); } +}; + +#define BOOST_UNITS_DEFINE_HELPER(name, symbol, template_name) \ + \ +template<class T, class Arg1, class Arg2> \ +struct name ## _typeof_helper<constant<T>, template_name<Arg1, Arg2> >\ +{ \ + typedef typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type type;\ +}; \ + \ +template<class T, class Arg1, class Arg2> \ +struct name ## _typeof_helper<template_name<Arg1, Arg2>, constant<T> >\ +{ \ + typedef typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type type;\ +}; \ + \ +template<class T, class Arg1, class Arg2> \ +typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type \ +operator symbol(const constant<T>& t, const template_name<Arg1, Arg2>& u)\ +{ \ + return(t.value() symbol u); \ +} \ + \ +template<class T, class Arg1, class Arg2> \ +typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type \ +operator symbol(const template_name<Arg1, Arg2>& u, const constant<T>& t)\ +{ \ + return(u symbol t.value()); \ +} + +BOOST_UNITS_DEFINE_HELPER(add, +, unit) +BOOST_UNITS_DEFINE_HELPER(add, +, quantity) +BOOST_UNITS_DEFINE_HELPER(subtract, -, unit) +BOOST_UNITS_DEFINE_HELPER(subtract, -, quantity) +BOOST_UNITS_DEFINE_HELPER(multiply, *, unit) +BOOST_UNITS_DEFINE_HELPER(multiply, *, quantity) +BOOST_UNITS_DEFINE_HELPER(divide, /, unit) +BOOST_UNITS_DEFINE_HELPER(divide, /, quantity) + +#undef BOOST_UNITS_DEFINE_HELPER + +#define BOOST_UNITS_DEFINE_HELPER(name, symbol) \ + \ +template<class T1, class T2> \ +struct name ## _typeof_helper<constant<T1>, constant<T2> > \ +{ \ + typedef typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type type;\ +}; \ + \ +template<class T1, class T2> \ +typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type \ +operator symbol(const constant<T1>& t, const constant<T2>& u) \ +{ \ + return(t.value() symbol u.value()); \ +} \ + \ +template<class T1, class T2> \ +struct name ## _typeof_helper<constant<T1>, T2> \ +{ \ + typedef typename name ## _typeof_helper<typename T1::value_type, T2>::type type;\ +}; \ + \ +template<class T1, class T2> \ +struct name ## _typeof_helper<T1, constant<T2> > \ +{ \ + typedef typename name ## _typeof_helper<T1, typename T2::value_type>::type type;\ +}; \ + \ +template<class T1, class T2> \ +typename name ## _typeof_helper<typename T1::value_type, T2>::type \ +operator symbol(const constant<T1>& t, const T2& u) \ +{ \ + return(t.value() symbol u); \ +} \ + \ +template<class T1, class T2> \ +typename name ## _typeof_helper<T1, typename T2::value_type>::type \ +operator symbol(const T1& t, const constant<T2>& u) \ +{ \ + return(t symbol u.value()); \ +} + +BOOST_UNITS_DEFINE_HELPER(add, +) +BOOST_UNITS_DEFINE_HELPER(subtract, -) +BOOST_UNITS_DEFINE_HELPER(multiply, *) +BOOST_UNITS_DEFINE_HELPER(divide, /) + +#undef BOOST_UNITS_DEFINE_HELPER + +#define BOOST_UNITS_PHYSICAL_CONSTANT(name, type, value_, uncertainty_) \ +struct name ## _t { \ + typedef type value_type; \ + operator value_type() const { return value_; } \ + value_type value() const { return value_; } \ + value_type uncertainty() const { return uncertainty_; } \ + value_type lower_bound() const { return value_-uncertainty_; } \ + value_type upper_bound() const { return value_+uncertainty_; } \ +}; \ +BOOST_UNITS_STATIC_CONSTANT(name, boost::units::constant<boost::units::physical_constant<name ## _t> >) = { } + +// stream output +template<class Char, class Traits, class Y> +inline +std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const physical_constant<Y>& val) +{ + boost::io::ios_precision_saver precision_saver(os); + //boost::io::ios_width_saver width_saver(os); + boost::io::ios_flags_saver flags_saver(os); + + //os << std::setw(21); + typedef typename Y::value_type value_type; + + if (val.uncertainty() > value_type()) + { + const double relative_uncertainty = std::abs(val.uncertainty()/val.value()); + + const double exponent = std::log10(relative_uncertainty); + const long digits_of_precision = static_cast<long>(std::ceil(std::abs(exponent)))+3; + + // should try to replicate NIST CODATA syntax + os << std::setprecision(digits_of_precision) + //<< std::setw(digits_of_precision+8) + //<< std::scientific + << val.value(); +// << long(10*(relative_uncertainty/std::pow(Y(10),Y(exponent)))); + + os << " (rel. unc. = " + << std::setprecision(1) + //<< std::setw(7) + << std::scientific + << relative_uncertainty << ")"; + } + else + { + os << val.value() << " (exact)"; + } + + return os; +} + +// stream output +template<class Char, class Traits, class Y> +inline +std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const constant<Y>&) +{ + os << Y(); + return os; +} + +} // namespace units + +} // namespace boost + +#endif // BOOST_UNITS_CONSTANTS_HPP |