1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
2 // unit/quantity manipulation and conversion
4 // Copyright (C) 2003-2008 Matthias Christian Schabel
5 // Copyright (C) 2008 Steven Watanabe
7 // Distributed under the Boost Software License, Version 1.0. (See
8 // accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef BOOST_UNITS_CONSTANTS_HPP
12 #define BOOST_UNITS_CONSTANTS_HPP
14 #include <boost/config/no_tr1/cmath.hpp>
18 #include <boost/io/ios_state.hpp>
20 #include <boost/units/static_constant.hpp>
21 #include <boost/units/units_fwd.hpp>
22 #include <boost/units/operators.hpp>
23 #include <boost/units/static_rational.hpp>
24 #include <boost/units/detail/one.hpp>
33 typedef typename Base::value_type value_type;
34 operator value_type() const { return Base().value(); }
35 value_type value() const { return Base().value(); }
36 value_type uncertainty() const { return Base().uncertainty(); }
37 value_type lower_bound() const { return Base().lower_bound(); }
38 value_type upper_bound() const { return Base().upper_bound(); }
42 struct physical_constant
44 typedef typename Base::value_type value_type;
45 operator value_type() const { return Base().value(); }
46 value_type value() const { return Base().value(); }
47 value_type uncertainty() const { return Base().uncertainty(); }
48 value_type lower_bound() const { return Base().lower_bound(); }
49 value_type upper_bound() const { return Base().upper_bound(); }
52 #define BOOST_UNITS_DEFINE_HELPER(name, symbol, template_name) \
54 template<class T, class Arg1, class Arg2> \
55 struct name ## _typeof_helper<constant<T>, template_name<Arg1, Arg2> >\
57 typedef typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type type;\
60 template<class T, class Arg1, class Arg2> \
61 struct name ## _typeof_helper<template_name<Arg1, Arg2>, constant<T> >\
63 typedef typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type type;\
66 template<class T, class Arg1, class Arg2> \
67 typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type \
68 operator symbol(const constant<T>& t, const template_name<Arg1, Arg2>& u)\
70 return(t.value() symbol u); \
73 template<class T, class Arg1, class Arg2> \
74 typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type \
75 operator symbol(const template_name<Arg1, Arg2>& u, const constant<T>& t)\
77 return(u symbol t.value()); \
80 BOOST_UNITS_DEFINE_HELPER(add, +, unit)
81 BOOST_UNITS_DEFINE_HELPER(add, +, quantity)
82 BOOST_UNITS_DEFINE_HELPER(subtract, -, unit)
83 BOOST_UNITS_DEFINE_HELPER(subtract, -, quantity)
84 BOOST_UNITS_DEFINE_HELPER(multiply, *, unit)
85 BOOST_UNITS_DEFINE_HELPER(multiply, *, quantity)
86 BOOST_UNITS_DEFINE_HELPER(divide, /, unit)
87 BOOST_UNITS_DEFINE_HELPER(divide, /, quantity)
89 #undef BOOST_UNITS_DEFINE_HELPER
91 #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \
93 template<class T1, class T2> \
94 struct name ## _typeof_helper<constant<T1>, constant<T2> > \
96 typedef typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type type;\
99 template<class T1, class T2> \
100 typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type \
101 operator symbol(const constant<T1>& t, const constant<T2>& u) \
103 return(t.value() symbol u.value()); \
106 template<class T1, class T2> \
107 struct name ## _typeof_helper<constant<T1>, T2> \
109 typedef typename name ## _typeof_helper<typename T1::value_type, T2>::type type;\
112 template<class T1, class T2> \
113 struct name ## _typeof_helper<T1, constant<T2> > \
115 typedef typename name ## _typeof_helper<T1, typename T2::value_type>::type type;\
118 template<class T1, class T2> \
119 typename name ## _typeof_helper<typename T1::value_type, T2>::type \
120 operator symbol(const constant<T1>& t, const T2& u) \
122 return(t.value() symbol u); \
125 template<class T1, class T2> \
126 typename name ## _typeof_helper<T1, typename T2::value_type>::type \
127 operator symbol(const T1& t, const constant<T2>& u) \
129 return(t symbol u.value()); \
132 BOOST_UNITS_DEFINE_HELPER(add, +)
133 BOOST_UNITS_DEFINE_HELPER(subtract, -)
134 BOOST_UNITS_DEFINE_HELPER(multiply, *)
135 BOOST_UNITS_DEFINE_HELPER(divide, /)
137 #undef BOOST_UNITS_DEFINE_HELPER
139 #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \
142 struct name ## _typeof_helper<constant<T1>, one> \
144 typedef typename name ## _typeof_helper<typename T1::value_type, one>::type type;\
148 struct name ## _typeof_helper<one, constant<T2> > \
150 typedef typename name ## _typeof_helper<one, typename T2::value_type>::type type;\
154 typename name ## _typeof_helper<typename T1::value_type, one>::type \
155 operator symbol(const constant<T1>& t, const one& u) \
157 return(t.value() symbol u); \
161 typename name ## _typeof_helper<one, typename T2::value_type>::type \
162 operator symbol(const one& t, const constant<T2>& u) \
164 return(t symbol u.value()); \
167 BOOST_UNITS_DEFINE_HELPER(multiply, *)
168 BOOST_UNITS_DEFINE_HELPER(divide, /)
170 #undef BOOST_UNITS_DEFINE_HELPER
172 template<class T1, long N, long D>
173 struct power_typeof_helper<constant<T1>, static_rational<N,D> >
175 typedef power_typeof_helper<typename T1::value_type, static_rational<N,D> > base;
176 typedef typename base::type type;
177 static type value(const constant<T1>& arg)
179 return base::value(arg.value());
183 #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \
185 template<class T1, class E> \
186 struct name ## _typeof_helper<constant<T1> > \
188 typedef typename name ## _typeof_helper<typename T1::value_type, E>::type type;\
192 typename name ## _typeof_helper<typename T1::value_type, one>::type \
193 operator symbol(const constant<T1>& t, const one& u) \
195 return(t.value() symbol u); \
199 typename name ## _typeof_helper<one, typename T2::value_type>::type \
200 operator symbol(const one& t, const constant<T2>& u) \
202 return(t symbol u.value()); \
205 #define BOOST_UNITS_PHYSICAL_CONSTANT(name, type, value_, uncertainty_) \
206 struct name ## _t { \
207 typedef type value_type; \
208 operator value_type() const { return value_; } \
209 value_type value() const { return value_; } \
210 value_type uncertainty() const { return uncertainty_; } \
211 value_type lower_bound() const { return value_-uncertainty_; } \
212 value_type upper_bound() const { return value_+uncertainty_; } \
214 BOOST_UNITS_STATIC_CONSTANT(name, boost::units::constant<boost::units::physical_constant<name ## _t> >) = { }
217 template<class Char, class Traits, class Y>
219 std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const physical_constant<Y>& val)
221 boost::io::ios_precision_saver precision_saver(os);
222 //boost::io::ios_width_saver width_saver(os);
223 boost::io::ios_flags_saver flags_saver(os);
225 //os << std::setw(21);
226 typedef typename Y::value_type value_type;
228 if (val.uncertainty() > value_type())
230 const double relative_uncertainty = std::abs(val.uncertainty()/val.value());
232 const double exponent = std::log10(relative_uncertainty);
233 const long digits_of_precision = static_cast<long>(std::ceil(std::abs(exponent)))+3;
235 // should try to replicate NIST CODATA syntax
236 os << std::setprecision(digits_of_precision)
237 //<< std::setw(digits_of_precision+8)
240 // << long(10*(relative_uncertainty/std::pow(Y(10),Y(exponent))));
242 os << " (rel. unc. = "
243 << std::setprecision(1)
246 << relative_uncertainty << ")";
250 os << val.value() << " (exact)";
257 template<class Char, class Traits, class Y>
259 std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const constant<Y>&)
269 #endif // BOOST_UNITS_CONSTANTS_HPP