]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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; | |
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(); } | |
39 | }; | |
40 | ||
41 | template<class Base> | |
42 | struct physical_constant | |
43 | { | |
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(); } | |
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 | 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)\ | |
69 | { \ | |
70 | return(t.value() symbol u); \ | |
71 | } \ | |
72 | \ | |
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)\ | |
76 | { \ | |
77 | return(u symbol t.value()); \ | |
78 | } | |
79 | ||
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) | |
88 | ||
89 | #undef BOOST_UNITS_DEFINE_HELPER | |
90 | ||
91 | #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \ | |
92 | \ | |
93 | template<class T1, class T2> \ | |
94 | struct name ## _typeof_helper<constant<T1>, constant<T2> > \ | |
95 | { \ | |
96 | typedef typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type type;\ | |
97 | }; \ | |
98 | \ | |
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) \ | |
102 | { \ | |
103 | return(t.value() symbol u.value()); \ | |
104 | } \ | |
105 | \ | |
106 | template<class T1, class T2> \ | |
107 | struct name ## _typeof_helper<constant<T1>, T2> \ | |
108 | { \ | |
109 | typedef typename name ## _typeof_helper<typename T1::value_type, T2>::type type;\ | |
110 | }; \ | |
111 | \ | |
112 | template<class T1, class T2> \ | |
113 | struct name ## _typeof_helper<T1, constant<T2> > \ | |
114 | { \ | |
115 | typedef typename name ## _typeof_helper<T1, typename T2::value_type>::type type;\ | |
116 | }; \ | |
117 | \ | |
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) \ | |
121 | { \ | |
122 | return(t.value() symbol u); \ | |
123 | } \ | |
124 | \ | |
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) \ | |
128 | { \ | |
129 | return(t symbol u.value()); \ | |
130 | } | |
131 | ||
132 | BOOST_UNITS_DEFINE_HELPER(add, +) | |
133 | BOOST_UNITS_DEFINE_HELPER(subtract, -) | |
134 | BOOST_UNITS_DEFINE_HELPER(multiply, *) | |
135 | BOOST_UNITS_DEFINE_HELPER(divide, /) | |
136 | ||
137 | #undef BOOST_UNITS_DEFINE_HELPER | |
138 | ||
139 | #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \ | |
140 | \ | |
141 | template<class T1> \ | |
142 | struct name ## _typeof_helper<constant<T1>, one> \ | |
143 | { \ | |
144 | typedef typename name ## _typeof_helper<typename T1::value_type, one>::type type;\ | |
145 | }; \ | |
146 | \ | |
147 | template<class T2> \ | |
148 | struct name ## _typeof_helper<one, constant<T2> > \ | |
149 | { \ | |
150 | typedef typename name ## _typeof_helper<one, typename T2::value_type>::type type;\ | |
151 | }; \ | |
152 | \ | |
153 | template<class T1> \ | |
154 | typename name ## _typeof_helper<typename T1::value_type, one>::type \ | |
155 | operator symbol(const constant<T1>& t, const one& u) \ | |
156 | { \ | |
157 | return(t.value() symbol u); \ | |
158 | } \ | |
159 | \ | |
160 | template<class T2> \ | |
161 | typename name ## _typeof_helper<one, typename T2::value_type>::type \ | |
162 | operator symbol(const one& t, const constant<T2>& u) \ | |
163 | { \ | |
164 | return(t symbol u.value()); \ | |
165 | } | |
166 | ||
167 | BOOST_UNITS_DEFINE_HELPER(multiply, *) | |
168 | BOOST_UNITS_DEFINE_HELPER(divide, /) | |
169 | ||
170 | #undef BOOST_UNITS_DEFINE_HELPER | |
171 | ||
172 | template<class T1, long N, long D> | |
173 | struct power_typeof_helper<constant<T1>, static_rational<N,D> > | |
174 | { | |
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) | |
178 | { | |
179 | return base::value(arg.value()); | |
180 | } | |
181 | }; | |
182 | ||
183 | #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \ | |
184 | \ | |
185 | template<class T1, class E> \ | |
186 | struct name ## _typeof_helper<constant<T1> > \ | |
187 | { \ | |
188 | typedef typename name ## _typeof_helper<typename T1::value_type, E>::type type;\ | |
189 | }; \ | |
190 | \ | |
191 | template<class T1> \ | |
192 | typename name ## _typeof_helper<typename T1::value_type, one>::type \ | |
193 | operator symbol(const constant<T1>& t, const one& u) \ | |
194 | { \ | |
195 | return(t.value() symbol u); \ | |
196 | } \ | |
197 | \ | |
198 | template<class T2> \ | |
199 | typename name ## _typeof_helper<one, typename T2::value_type>::type \ | |
200 | operator symbol(const one& t, const constant<T2>& u) \ | |
201 | { \ | |
202 | return(t symbol u.value()); \ | |
203 | } | |
204 | ||
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_; } \ | |
213 | }; \ | |
214 | BOOST_UNITS_STATIC_CONSTANT(name, boost::units::constant<boost::units::physical_constant<name ## _t> >) = { } | |
215 | ||
216 | // stream output | |
217 | template<class Char, class Traits, class Y> | |
218 | inline | |
219 | std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const physical_constant<Y>& val) | |
220 | { | |
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); | |
224 | ||
225 | //os << std::setw(21); | |
226 | typedef typename Y::value_type value_type; | |
227 | ||
228 | if (val.uncertainty() > value_type()) | |
229 | { | |
230 | const double relative_uncertainty = std::abs(val.uncertainty()/val.value()); | |
231 | ||
232 | const double exponent = std::log10(relative_uncertainty); | |
233 | const long digits_of_precision = static_cast<long>(std::ceil(std::abs(exponent)))+3; | |
234 | ||
235 | // should try to replicate NIST CODATA syntax | |
236 | os << std::setprecision(digits_of_precision) | |
237 | //<< std::setw(digits_of_precision+8) | |
238 | //<< std::scientific | |
239 | << val.value(); | |
240 | // << long(10*(relative_uncertainty/std::pow(Y(10),Y(exponent)))); | |
241 | ||
242 | os << " (rel. unc. = " | |
243 | << std::setprecision(1) | |
244 | //<< std::setw(7) | |
245 | << std::scientific | |
246 | << relative_uncertainty << ")"; | |
247 | } | |
248 | else | |
249 | { | |
250 | os << val.value() << " (exact)"; | |
251 | } | |
252 | ||
253 | return os; | |
254 | } | |
255 | ||
256 | // stream output | |
257 | template<class Char, class Traits, class Y> | |
258 | inline | |
259 | std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const constant<Y>&) | |
260 | { | |
261 | os << Y(); | |
262 | return os; | |
263 | } | |
264 | ||
265 | } // namespace units | |
266 | ||
267 | } // namespace boost | |
268 | ||
269 | #endif // BOOST_UNITS_CONSTANTS_HPP |