• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
2 // unit/quantity manipulation and conversion
3 //
4 // Copyright (C) 2003-2008 Matthias Christian Schabel
5 // Copyright (C) 2008 Steven Watanabe
6 //
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)
10 
11 #ifndef BOOST_UNITS_CONSTANTS_HPP
12 #define BOOST_UNITS_CONSTANTS_HPP
13 
14 #include <boost/config/no_tr1/cmath.hpp>
15 #include <iosfwd>
16 #include <iomanip>
17 
18 #include <boost/io/ios_state.hpp>
19 
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>
25 
26 namespace boost {
27 
28 namespace units {
29 
30 template<class Base>
31 struct constant
32 {
33     typedef typename Base::value_type value_type;
operator value_typeboost::units::constant34     BOOST_CONSTEXPR operator value_type() const    { return Base().value(); }
valueboost::units::constant35     BOOST_CONSTEXPR value_type value() const       { return Base().value(); }
uncertaintyboost::units::constant36     BOOST_CONSTEXPR value_type uncertainty() const { return Base().uncertainty(); }
lower_boundboost::units::constant37     BOOST_CONSTEXPR value_type lower_bound() const { return Base().lower_bound(); }
upper_boundboost::units::constant38     BOOST_CONSTEXPR value_type upper_bound() const { return Base().upper_bound(); }
39 };
40 
41 template<class Base>
42 struct physical_constant
43 {
44     typedef typename Base::value_type value_type;
operator value_typeboost::units::physical_constant45     BOOST_CONSTEXPR operator value_type() const    { return Base().value(); }
valueboost::units::physical_constant46     BOOST_CONSTEXPR value_type value() const       { return Base().value(); }
uncertaintyboost::units::physical_constant47     BOOST_CONSTEXPR value_type uncertainty() const { return Base().uncertainty(); }
lower_boundboost::units::physical_constant48     BOOST_CONSTEXPR value_type lower_bound() const { return Base().lower_bound(); }
upper_boundboost::units::physical_constant49     BOOST_CONSTEXPR value_type upper_bound() const { return Base().upper_bound(); }
50 };
51 
52 #define BOOST_UNITS_DEFINE_HELPER(name, symbol, template_name)  \
53                                                                 \
54 template<class T, class Arg1, class Arg2>                       \
55 struct name ## _typeof_helper<constant<T>, template_name<Arg1, Arg2> >\
56 {                                                               \
57     typedef typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type type;\
58 };                                                              \
59                                                                 \
60 template<class T, class Arg1, class Arg2>                       \
61 struct name ## _typeof_helper<template_name<Arg1, Arg2>, constant<T> >\
62 {                                                               \
63     typedef typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type type;\
64 };                                                              \
65                                                                 \
66 template<class T, class Arg1, class Arg2>                       \
67 BOOST_CONSTEXPR                                                 \
68 typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type \
69 operator symbol(const constant<T>& t, const template_name<Arg1, Arg2>& u)\
70 {                                                               \
71     return(t.value() symbol u);                                 \
72 }                                                               \
73                                                                 \
74 template<class T, class Arg1, class Arg2>                       \
75 BOOST_CONSTEXPR                                                 \
76 typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type \
77 operator symbol(const template_name<Arg1, Arg2>& u, const constant<T>& t)\
78 {                                                               \
79     return(u symbol t.value());                                 \
80 }
81 
82 BOOST_UNITS_DEFINE_HELPER(add, +, unit)
83 BOOST_UNITS_DEFINE_HELPER(add, +, quantity)
84 BOOST_UNITS_DEFINE_HELPER(subtract, -, unit)
85 BOOST_UNITS_DEFINE_HELPER(subtract, -, quantity)
86 BOOST_UNITS_DEFINE_HELPER(multiply, *, unit)
87 BOOST_UNITS_DEFINE_HELPER(multiply, *, quantity)
88 BOOST_UNITS_DEFINE_HELPER(divide, /, unit)
89 BOOST_UNITS_DEFINE_HELPER(divide, /, quantity)
90 
91 #undef BOOST_UNITS_DEFINE_HELPER
92 
93 #define BOOST_UNITS_DEFINE_HELPER(name, symbol)                     \
94                                                                     \
95 template<class T1, class T2>                                        \
96 struct name ## _typeof_helper<constant<T1>, constant<T2> >          \
97 {                                                                   \
98     typedef typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type type;\
99 };                                                                  \
100                                                                     \
101 template<class T1, class T2>                                        \
102 BOOST_CONSTEXPR                                                     \
103 typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type \
104 operator symbol(const constant<T1>& t, const constant<T2>& u)       \
105 {                                                                   \
106     return(t.value() symbol u.value());                             \
107 }                                                                   \
108                                                                     \
109 template<class T1, class T2>                                        \
110 struct name ## _typeof_helper<constant<T1>, T2>                     \
111 {                                                                   \
112     typedef typename name ## _typeof_helper<typename T1::value_type, T2>::type type;\
113 };                                                                  \
114                                                                     \
115 template<class T1, class T2>                                        \
116 struct name ## _typeof_helper<T1, constant<T2> >                    \
117 {                                                                   \
118     typedef typename name ## _typeof_helper<T1, typename T2::value_type>::type type;\
119 };                                                                  \
120                                                                     \
121 template<class T1, class T2>                                        \
122 BOOST_CONSTEXPR                                                     \
123 typename name ## _typeof_helper<typename T1::value_type, T2>::type  \
124 operator symbol(const constant<T1>& t, const T2& u)                 \
125 {                                                                   \
126     return(t.value() symbol u);                                     \
127 }                                                                   \
128                                                                     \
129 template<class T1, class T2>                                        \
130 BOOST_CONSTEXPR                                                     \
131 typename name ## _typeof_helper<T1, typename T2::value_type>::type  \
132 operator symbol(const T1& t, const constant<T2>& u)                 \
133 {                                                                   \
134     return(t symbol u.value());                                     \
135 }
136 
137 BOOST_UNITS_DEFINE_HELPER(add, +)
138 BOOST_UNITS_DEFINE_HELPER(subtract, -)
139 BOOST_UNITS_DEFINE_HELPER(multiply, *)
140 BOOST_UNITS_DEFINE_HELPER(divide, /)
141 
142 #undef BOOST_UNITS_DEFINE_HELPER
143 
144 #define BOOST_UNITS_DEFINE_HELPER(name, symbol)                     \
145                                                                     \
146 template<class T1>                                                  \
147 struct name ## _typeof_helper<constant<T1>, one>                    \
148 {                                                                   \
149     typedef typename name ## _typeof_helper<typename T1::value_type, one>::type type;\
150 };                                                                  \
151                                                                     \
152 template<class T2>                                                  \
153 struct name ## _typeof_helper<one, constant<T2> >                   \
154 {                                                                   \
155     typedef typename name ## _typeof_helper<one, typename T2::value_type>::type type;\
156 };                                                                  \
157                                                                     \
158 template<class T1>                                                  \
159 BOOST_CONSTEXPR                                                     \
160 typename name ## _typeof_helper<typename T1::value_type, one>::type \
161 operator symbol(const constant<T1>& t, const one& u)                \
162 {                                                                   \
163     return(t.value() symbol u);                                     \
164 }                                                                   \
165                                                                     \
166 template<class T2>                                                  \
167 BOOST_CONSTEXPR                                                     \
168 typename name ## _typeof_helper<one, typename T2::value_type>::type \
169 operator symbol(const one& t, const constant<T2>& u)                \
170 {                                                                   \
171     return(t symbol u.value());                                     \
172 }
173 
174 BOOST_UNITS_DEFINE_HELPER(multiply, *)
175 BOOST_UNITS_DEFINE_HELPER(divide, /)
176 
177 #undef BOOST_UNITS_DEFINE_HELPER
178 
179 template<class T1, long N, long D>
180 struct power_typeof_helper<constant<T1>, static_rational<N,D> >
181 {
182     typedef power_typeof_helper<typename T1::value_type, static_rational<N,D> > base;
183     typedef typename base::type type;
valueboost::units::power_typeof_helper184     static BOOST_CONSTEXPR type value(const constant<T1>& arg)
185     {
186         return base::value(arg.value());
187     }
188 };
189 
190 #define BOOST_UNITS_DEFINE_HELPER(name, symbol)                     \
191                                                                     \
192 template<class T1, class E>                                         \
193 struct name ## _typeof_helper<constant<T1> >                        \
194 {                                                                   \
195     typedef typename name ## _typeof_helper<typename T1::value_type, E>::type type;\
196 };                                                                  \
197                                                                     \
198 template<class T1>                                                  \
199 BOOST_CONSTEXPR                                                     \
200 typename name ## _typeof_helper<typename T1::value_type, one>::type \
201 operator symbol(const constant<T1>& t, const one& u)                \
202 {                                                                   \
203     return(t.value() symbol u);                                     \
204 }                                                                   \
205                                                                     \
206 template<class T2>                                                  \
207 BOOST_CONSTEXPR                                                     \
208 typename name ## _typeof_helper<one, typename T2::value_type>::type \
209 operator symbol(const one& t, const constant<T2>& u)                \
210 {                                                                   \
211     return(t symbol u.value());                                     \
212 }
213 
214 #define BOOST_UNITS_PHYSICAL_CONSTANT(name, type, value_, uncertainty_)             \
215 struct name ## _t {                                                                 \
216     typedef type value_type;                                                        \
217     BOOST_CONSTEXPR operator value_type() const    { return value_; }               \
218     BOOST_CONSTEXPR value_type value() const       { return value_; }               \
219     BOOST_CONSTEXPR value_type uncertainty() const { return uncertainty_; }         \
220     BOOST_CONSTEXPR value_type lower_bound() const { return value_-uncertainty_; }  \
221     BOOST_CONSTEXPR value_type upper_bound() const { return value_+uncertainty_; }  \
222 };                                                                                  \
223 BOOST_UNITS_STATIC_CONSTANT(name, boost::units::constant<boost::units::physical_constant<name ## _t> >) = { }
224 
225 // stream output
226 template<class Char, class Traits, class Y>
227 inline
operator <<(std::basic_ostream<Char,Traits> & os,const physical_constant<Y> & val)228 std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const physical_constant<Y>& val)
229 {
230     boost::io::ios_precision_saver precision_saver(os);
231     //boost::io::ios_width_saver width_saver(os);
232     boost::io::ios_flags_saver flags_saver(os);
233 
234     //os << std::setw(21);
235     typedef typename Y::value_type value_type;
236 
237     if (val.uncertainty() > value_type())
238     {
239         const double relative_uncertainty = std::abs(val.uncertainty()/val.value());
240 
241         const double  exponent = std::log10(relative_uncertainty);
242         const long digits_of_precision = static_cast<long>(std::ceil(std::abs(exponent)))+3;
243 
244         // should try to replicate NIST CODATA syntax
245         os << std::setprecision(digits_of_precision)
246            //<< std::setw(digits_of_precision+8)
247            //<< std::scientific
248            << val.value();
249 //           << long(10*(relative_uncertainty/std::pow(Y(10),Y(exponent))));
250 
251         os << " (rel. unc. = "
252            << std::setprecision(1)
253            //<< std::setw(7)
254            << std::scientific
255            << relative_uncertainty << ")";
256     }
257     else
258     {
259         os << val.value() << " (exact)";
260     }
261 
262     return os;
263 }
264 
265 // stream output
266 template<class Char, class Traits, class Y>
267 inline
operator <<(std::basic_ostream<Char,Traits> & os,const constant<Y> &)268 std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const constant<Y>&)
269 {
270     os << Y();
271     return os;
272 }
273 
274 } // namespace units
275 
276 } // namespace boost
277 
278 #endif // BOOST_UNITS_CONSTANTS_HPP
279