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