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_STATIC_RATIONAL_HPP
|
Chris@16
|
12 #define BOOST_UNITS_STATIC_RATIONAL_HPP
|
Chris@16
|
13
|
Chris@101
|
14 #include <boost/integer/common_factor_ct.hpp>
|
Chris@16
|
15 #include <boost/mpl/less.hpp>
|
Chris@16
|
16 #include <boost/mpl/arithmetic.hpp>
|
Chris@16
|
17
|
Chris@16
|
18 #ifdef __BORLANDC__
|
Chris@16
|
19 #include <boost/mpl/eval_if.hpp>
|
Chris@16
|
20 #include <boost/mpl/integral_c.hpp>
|
Chris@16
|
21 #include <boost/mpl/identity.hpp>
|
Chris@16
|
22 #endif
|
Chris@16
|
23
|
Chris@16
|
24 #include <boost/units/config.hpp>
|
Chris@16
|
25 #include <boost/units/operators.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 /// \file
|
Chris@16
|
28 /// \brief Compile-time rational numbers and operators.
|
Chris@16
|
29
|
Chris@16
|
30 namespace boost {
|
Chris@16
|
31
|
Chris@16
|
32 namespace units {
|
Chris@16
|
33
|
Chris@16
|
34 namespace detail {
|
Chris@16
|
35
|
Chris@16
|
36 struct static_rational_tag {};
|
Chris@16
|
37
|
Chris@16
|
38 }
|
Chris@16
|
39
|
Chris@16
|
40 typedef long integer_type;
|
Chris@16
|
41
|
Chris@16
|
42 /// Compile time absolute value.
|
Chris@16
|
43 template<integer_type Value>
|
Chris@16
|
44 struct static_abs
|
Chris@16
|
45 {
|
Chris@16
|
46 BOOST_STATIC_CONSTANT(integer_type,value = Value < 0 ? -Value : Value);
|
Chris@16
|
47 };
|
Chris@16
|
48
|
Chris@16
|
49 // Compile time rational number.
|
Chris@16
|
50 /**
|
Chris@16
|
51 This is an implementation of a compile time rational number, where @c static_rational<N,D> represents
|
Chris@16
|
52 a rational number with numerator @c N and denominator @c D. Because of the potential for ambiguity arising
|
Chris@16
|
53 from multiple equivalent values of @c static_rational (e.g. @c static_rational<6,2>==static_rational<3>),
|
Chris@16
|
54 static rationals should always be accessed through @c static_rational<N,D>::type. Template specialization
|
Chris@16
|
55 prevents instantiation of zero denominators (i.e. @c static_rational<N,0>). The following compile-time
|
Chris@16
|
56 arithmetic operators are provided for static_rational variables only (no operators are defined between
|
Chris@16
|
57 long and static_rational):
|
Chris@16
|
58 - @c mpl::negate
|
Chris@16
|
59 - @c mpl::plus
|
Chris@16
|
60 - @c mpl::minus
|
Chris@16
|
61 - @c mpl::times
|
Chris@16
|
62 - @c mpl::divides
|
Chris@16
|
63
|
Chris@16
|
64 Neither @c static_power nor @c static_root are defined for @c static_rational. This is because template types
|
Chris@16
|
65 may not be floating point values, while powers and roots of rational numbers can produce floating point
|
Chris@16
|
66 values.
|
Chris@16
|
67 */
|
Chris@16
|
68 #ifdef __BORLANDC__
|
Chris@16
|
69
|
Chris@16
|
70 template<integer_type X>
|
Chris@16
|
71 struct make_integral_c {
|
Chris@16
|
72 typedef boost::mpl::integral_c<integer_type, X> type;
|
Chris@16
|
73 };
|
Chris@16
|
74
|
Chris@16
|
75 template<integer_type N,integer_type D = 1>
|
Chris@16
|
76 class static_rational
|
Chris@16
|
77 {
|
Chris@16
|
78 public:
|
Chris@16
|
79
|
Chris@16
|
80 typedef static_rational this_type;
|
Chris@16
|
81
|
Chris@16
|
82 typedef boost::mpl::integral_c<integer_type, N> N_type;
|
Chris@16
|
83 typedef boost::mpl::integral_c<integer_type, D> D_type;
|
Chris@16
|
84
|
Chris@16
|
85 typedef typename make_integral_c<
|
Chris@101
|
86 (::boost::integer::static_gcd<
|
Chris@16
|
87 ::boost::units::static_abs<N>::value,
|
Chris@16
|
88 ::boost::units::static_abs<D>::value
|
Chris@16
|
89 >::value)>::type gcd_type;
|
Chris@16
|
90 typedef typename boost::mpl::eval_if<
|
Chris@16
|
91 boost::mpl::less<
|
Chris@16
|
92 D_type,
|
Chris@16
|
93 boost::mpl::integral_c<integer_type, 0>
|
Chris@16
|
94 >,
|
Chris@16
|
95 boost::mpl::negate<gcd_type>,
|
Chris@16
|
96 gcd_type
|
Chris@16
|
97 >::type den_type;
|
Chris@16
|
98
|
Chris@16
|
99 public:
|
Chris@16
|
100 // for mpl arithmetic support
|
Chris@16
|
101 typedef detail::static_rational_tag tag;
|
Chris@16
|
102
|
Chris@16
|
103 BOOST_STATIC_CONSTANT(integer_type, Numerator =
|
Chris@16
|
104 (::boost::mpl::divides<N_type, den_type>::value));
|
Chris@16
|
105 BOOST_STATIC_CONSTANT(integer_type, Denominator =
|
Chris@16
|
106 (::boost::mpl::divides<D_type, den_type>::value));
|
Chris@16
|
107
|
Chris@16
|
108 /// INTERNAL ONLY
|
Chris@16
|
109 typedef static_rational<N,D> this_type;
|
Chris@16
|
110
|
Chris@16
|
111 /// static_rational<N,D> reduced by GCD
|
Chris@16
|
112 typedef static_rational<
|
Chris@16
|
113 (::boost::mpl::divides<N_type, den_type>::value),
|
Chris@16
|
114 (::boost::mpl::divides<D_type, den_type>::value)
|
Chris@16
|
115 > type;
|
Chris@16
|
116
|
Chris@16
|
117 static integer_type numerator() { return Numerator; }
|
Chris@16
|
118 static integer_type denominator() { return Denominator; }
|
Chris@16
|
119
|
Chris@16
|
120 // INTERNAL ONLY
|
Chris@16
|
121 static_rational() { }
|
Chris@16
|
122 //~static_rational() { }
|
Chris@16
|
123 };
|
Chris@16
|
124 #else
|
Chris@16
|
125 template<integer_type N,integer_type D = 1>
|
Chris@16
|
126 class static_rational
|
Chris@16
|
127 {
|
Chris@16
|
128 private:
|
Chris@16
|
129
|
Chris@16
|
130 static const integer_type nabs = static_abs<N>::value,
|
Chris@16
|
131 dabs = static_abs<D>::value;
|
Chris@16
|
132
|
Chris@16
|
133 /// greatest common divisor of N and D
|
Chris@16
|
134 // need cast to signed because static_gcd returns unsigned long
|
Chris@16
|
135 static const integer_type den =
|
Chris@101
|
136 static_cast<integer_type>(boost::integer::static_gcd<nabs,dabs>::value) * ((D < 0) ? -1 : 1);
|
Chris@16
|
137
|
Chris@16
|
138 public:
|
Chris@16
|
139 // for mpl arithmetic support
|
Chris@16
|
140 typedef detail::static_rational_tag tag;
|
Chris@16
|
141
|
Chris@16
|
142 static const integer_type Numerator = N/den,
|
Chris@16
|
143 Denominator = D/den;
|
Chris@16
|
144
|
Chris@16
|
145 /// INTERNAL ONLY
|
Chris@16
|
146 typedef static_rational<N,D> this_type;
|
Chris@16
|
147
|
Chris@16
|
148 /// static_rational<N,D> reduced by GCD
|
Chris@16
|
149 typedef static_rational<Numerator,Denominator> type;
|
Chris@16
|
150
|
Chris@16
|
151 static integer_type numerator() { return Numerator; }
|
Chris@16
|
152 static integer_type denominator() { return Denominator; }
|
Chris@16
|
153
|
Chris@16
|
154 // INTERNAL ONLY
|
Chris@16
|
155 static_rational() { }
|
Chris@16
|
156 //~static_rational() { }
|
Chris@16
|
157 };
|
Chris@16
|
158 #endif
|
Chris@16
|
159
|
Chris@16
|
160 }
|
Chris@16
|
161
|
Chris@16
|
162 }
|
Chris@16
|
163
|
Chris@16
|
164 #if BOOST_UNITS_HAS_BOOST_TYPEOF
|
Chris@16
|
165
|
Chris@16
|
166 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
|
Chris@16
|
167
|
Chris@16
|
168 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::static_rational, (long)(long))
|
Chris@16
|
169
|
Chris@16
|
170 #endif
|
Chris@16
|
171
|
Chris@16
|
172 namespace boost {
|
Chris@16
|
173
|
Chris@16
|
174 namespace units {
|
Chris@16
|
175
|
Chris@16
|
176 // prohibit zero denominator
|
Chris@16
|
177 template<integer_type N> class static_rational<N,0>;
|
Chris@16
|
178
|
Chris@16
|
179 /// get decimal value of @c static_rational
|
Chris@16
|
180 template<class T,integer_type N,integer_type D>
|
Chris@16
|
181 inline typename divide_typeof_helper<T,T>::type
|
Chris@16
|
182 value(const static_rational<N,D>&)
|
Chris@16
|
183 {
|
Chris@16
|
184 return T(N)/T(D);
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 } // namespace units
|
Chris@16
|
188
|
Chris@16
|
189 #ifndef BOOST_UNITS_DOXYGEN
|
Chris@16
|
190
|
Chris@16
|
191 namespace mpl {
|
Chris@16
|
192
|
Chris@16
|
193 #ifdef __BORLANDC__
|
Chris@16
|
194
|
Chris@16
|
195 template<>
|
Chris@16
|
196 struct plus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
197 {
|
Chris@16
|
198 template<class T0, class T1>
|
Chris@16
|
199 struct apply {
|
Chris@16
|
200 typedef typename boost::units::static_rational<
|
Chris@16
|
201 ::boost::mpl::plus<
|
Chris@16
|
202 boost::mpl::times<typename T0::N_type, typename T1::D_type>,
|
Chris@16
|
203 boost::mpl::times<typename T1::N_type, typename T0::D_type>
|
Chris@16
|
204 >::value,
|
Chris@16
|
205 ::boost::mpl::times<typename T0::D_type, typename T1::D_type>::value
|
Chris@16
|
206 >::type type;
|
Chris@16
|
207 };
|
Chris@16
|
208 };
|
Chris@16
|
209
|
Chris@16
|
210 template<>
|
Chris@16
|
211 struct minus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
212 {
|
Chris@16
|
213 template<class T0, class T1>
|
Chris@16
|
214 struct apply {
|
Chris@16
|
215 typedef typename boost::units::static_rational<
|
Chris@16
|
216 ::boost::mpl::minus<
|
Chris@16
|
217 boost::mpl::times<typename T0::N_type, typename T1::D_type>,
|
Chris@16
|
218 boost::mpl::times<typename T1::N_type, typename T0::D_type>
|
Chris@16
|
219 >::value,
|
Chris@16
|
220 ::boost::mpl::times<typename T0::D_type, typename T1::D_type>::value
|
Chris@16
|
221 >::type type;
|
Chris@16
|
222 };
|
Chris@16
|
223 };
|
Chris@16
|
224
|
Chris@16
|
225 template<>
|
Chris@16
|
226 struct times_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
227 {
|
Chris@16
|
228 template<class T0, class T1>
|
Chris@16
|
229 struct apply {
|
Chris@16
|
230 typedef typename boost::units::static_rational<
|
Chris@16
|
231 ::boost::mpl::times<typename T0::N_type, typename T1::N_type>::value,
|
Chris@16
|
232 ::boost::mpl::times<typename T0::D_type, typename T1::D_type>::value
|
Chris@16
|
233 >::type type;
|
Chris@16
|
234 };
|
Chris@16
|
235 };
|
Chris@16
|
236
|
Chris@16
|
237 template<>
|
Chris@16
|
238 struct divides_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
239 {
|
Chris@16
|
240 template<class T0, class T1>
|
Chris@16
|
241 struct apply {
|
Chris@16
|
242 typedef typename boost::units::static_rational<
|
Chris@16
|
243 ::boost::mpl::times<typename T0::N_type, typename T1::D_type>::value,
|
Chris@16
|
244 ::boost::mpl::times<typename T0::D_type, typename T1::N_type>::value
|
Chris@16
|
245 >::type type;
|
Chris@16
|
246 };
|
Chris@16
|
247 };
|
Chris@16
|
248
|
Chris@16
|
249 template<>
|
Chris@16
|
250 struct negate_impl<boost::units::detail::static_rational_tag>
|
Chris@16
|
251 {
|
Chris@16
|
252 template<class T0>
|
Chris@16
|
253 struct apply {
|
Chris@16
|
254 typedef typename boost::units::static_rational<
|
Chris@16
|
255 ::boost::mpl::negate<typename T0::N_type>::value,
|
Chris@16
|
256 ::boost::mpl::identity<T0>::type::Denominator
|
Chris@16
|
257 >::type type;
|
Chris@16
|
258 };
|
Chris@16
|
259 };
|
Chris@16
|
260
|
Chris@16
|
261 template<>
|
Chris@16
|
262 struct less_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
263 {
|
Chris@16
|
264 template<class T0, class T1>
|
Chris@16
|
265 struct apply
|
Chris@16
|
266 {
|
Chris@16
|
267 typedef mpl::bool_<((mpl::minus<T0, T1>::type::Numerator) < 0)> type;
|
Chris@16
|
268 };
|
Chris@16
|
269 };
|
Chris@16
|
270
|
Chris@16
|
271 #else
|
Chris@16
|
272
|
Chris@16
|
273 template<>
|
Chris@16
|
274 struct plus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
275 {
|
Chris@16
|
276 template<class T0, class T1>
|
Chris@16
|
277 struct apply {
|
Chris@16
|
278 typedef typename boost::units::static_rational<
|
Chris@16
|
279 T0::Numerator*T1::Denominator+T1::Numerator*T0::Denominator,
|
Chris@16
|
280 T0::Denominator*T1::Denominator
|
Chris@16
|
281 >::type type;
|
Chris@16
|
282 };
|
Chris@16
|
283 };
|
Chris@16
|
284
|
Chris@16
|
285 template<>
|
Chris@16
|
286 struct minus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
287 {
|
Chris@16
|
288 template<class T0, class T1>
|
Chris@16
|
289 struct apply {
|
Chris@16
|
290 typedef typename boost::units::static_rational<
|
Chris@16
|
291 T0::Numerator*T1::Denominator-T1::Numerator*T0::Denominator,
|
Chris@16
|
292 T0::Denominator*T1::Denominator
|
Chris@16
|
293 >::type type;
|
Chris@16
|
294 };
|
Chris@16
|
295 };
|
Chris@16
|
296
|
Chris@16
|
297 template<>
|
Chris@16
|
298 struct times_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
299 {
|
Chris@16
|
300 template<class T0, class T1>
|
Chris@16
|
301 struct apply {
|
Chris@16
|
302 typedef typename boost::units::static_rational<
|
Chris@16
|
303 T0::Numerator*T1::Numerator,
|
Chris@16
|
304 T0::Denominator*T1::Denominator
|
Chris@16
|
305 >::type type;
|
Chris@16
|
306 };
|
Chris@16
|
307 };
|
Chris@16
|
308
|
Chris@16
|
309 template<>
|
Chris@16
|
310 struct divides_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
311 {
|
Chris@16
|
312 template<class T0, class T1>
|
Chris@16
|
313 struct apply {
|
Chris@16
|
314 typedef typename boost::units::static_rational<
|
Chris@16
|
315 T0::Numerator*T1::Denominator,
|
Chris@16
|
316 T0::Denominator*T1::Numerator
|
Chris@16
|
317 >::type type;
|
Chris@16
|
318 };
|
Chris@16
|
319 };
|
Chris@16
|
320
|
Chris@16
|
321 template<>
|
Chris@16
|
322 struct negate_impl<boost::units::detail::static_rational_tag>
|
Chris@16
|
323 {
|
Chris@16
|
324 template<class T0>
|
Chris@16
|
325 struct apply {
|
Chris@16
|
326 typedef typename boost::units::static_rational<-T0::Numerator,T0::Denominator>::type type;
|
Chris@16
|
327 };
|
Chris@16
|
328 };
|
Chris@16
|
329
|
Chris@16
|
330 template<>
|
Chris@16
|
331 struct less_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
332 {
|
Chris@16
|
333 template<class T0, class T1>
|
Chris@16
|
334 struct apply
|
Chris@16
|
335 {
|
Chris@16
|
336 typedef mpl::bool_<((mpl::minus<T0, T1>::type::Numerator) < 0)> type;
|
Chris@16
|
337 };
|
Chris@16
|
338 };
|
Chris@16
|
339
|
Chris@16
|
340 #endif
|
Chris@16
|
341
|
Chris@16
|
342
|
Chris@16
|
343 }
|
Chris@16
|
344
|
Chris@16
|
345 #endif
|
Chris@16
|
346
|
Chris@16
|
347 } // namespace boost
|
Chris@16
|
348
|
Chris@16
|
349 #endif // BOOST_UNITS_STATIC_RATIONAL_HPP
|