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_STATIC_RATIONAL_HPP
12 #define BOOST_UNITS_STATIC_RATIONAL_HPP
14 #include <boost/math/common_factor_ct.hpp>
15 #include <boost/mpl/less.hpp>
16 #include <boost/mpl/arithmetic.hpp>
19 #include <boost/mpl/eval_if.hpp>
20 #include <boost/mpl/integral_c.hpp>
21 #include <boost/mpl/identity.hpp>
24 #include <boost/units/config.hpp>
25 #include <boost/units/operators.hpp>
28 /// \brief Compile-time rational numbers and operators.
36 struct static_rational_tag
{};
40 typedef long integer_type
;
42 /// Compile time absolute value.
43 template<integer_type Value
>
46 BOOST_STATIC_CONSTANT(integer_type
,value
= Value
< 0 ? -Value
: Value
);
49 /// Compile time rational number.
51 This is an implementation of a compile time rational number, where @c static_rational<N,D> represents
52 a rational number with numerator @c N and denominator @c D. Because of the potential for ambiguity arising
53 from multiple equivalent values of @c static_rational (e.g. @c static_rational<6,2>==static_rational<3>),
54 static rationals should always be accessed through @c static_rational<N,D>::type. Template specialization
55 prevents instantiation of zero denominators (i.e. @c static_rational<N,0>). The following compile-time
56 arithmetic operators are provided for static_rational variables only (no operators are defined between
57 long and static_rational):
64 Neither @c static_power nor @c static_root are defined for @c static_rational. This is because template types
65 may not be floating point values, while powers and roots of rational numbers can produce floating point
70 template<integer_type X
>
71 struct make_integral_c
{
72 typedef boost::mpl::integral_c
<integer_type
, X
> type
;
75 template<integer_type N
,integer_type D
= 1>
80 typedef static_rational this_type
;
82 typedef boost::mpl::integral_c
<integer_type
, N
> N_type
;
83 typedef boost::mpl::integral_c
<integer_type
, D
> D_type
;
85 typedef typename make_integral_c
<
86 (::boost::math::static_gcd
<
87 ::boost::units::static_abs
<N
>::value
,
88 ::boost::units::static_abs
<D
>::value
89 >::value
)>::type gcd_type
;
90 typedef typename
boost::mpl::eval_if
<
93 boost::mpl::integral_c
<integer_type
, 0>
95 boost::mpl::negate
<gcd_type
>,
100 // for mpl arithmetic support
101 typedef detail::static_rational_tag tag
;
103 BOOST_STATIC_CONSTANT(integer_type
, Numerator
=
104 (::boost::mpl::divides
<N_type
, den_type
>::value
));
105 BOOST_STATIC_CONSTANT(integer_type
, Denominator
=
106 (::boost::mpl::divides
<D_type
, den_type
>::value
));
109 typedef static_rational
<N
,D
> this_type
;
111 /// static_rational<N,D> reduced by GCD
112 typedef static_rational
<
113 (::boost::mpl::divides
<N_type
, den_type
>::value
),
114 (::boost::mpl::divides
<D_type
, den_type
>::value
)
117 static integer_type
numerator() { return Numerator
; }
118 static integer_type
denominator() { return Denominator
; }
121 static_rational() { }
122 //~static_rational() { }
125 template<integer_type N
,integer_type D
= 1>
126 class static_rational
130 static const integer_type nabs
= static_abs
<N
>::value
,
131 dabs
= static_abs
<D
>::value
;
133 /// greatest common divisor of N and D
134 // need cast to signed because static_gcd returns unsigned long
135 static const integer_type den
=
136 static_cast<integer_type
>(boost::math::static_gcd
<nabs
,dabs
>::value
) * ((D
< 0) ? -1 : 1);
139 // for mpl arithmetic support
140 typedef detail::static_rational_tag tag
;
142 static const integer_type Numerator
= N
/den
,
146 typedef static_rational
<N
,D
> this_type
;
148 /// static_rational<N,D> reduced by GCD
149 typedef static_rational
<Numerator
,Denominator
> type
;
151 static integer_type
numerator() { return Numerator
; }
152 static integer_type
denominator() { return Denominator
; }
155 static_rational() { }
156 //~static_rational() { }
164 #if BOOST_UNITS_HAS_BOOST_TYPEOF
166 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
168 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::static_rational
, (long)(long))
176 // prohibit zero denominator
177 template<integer_type N
> class static_rational
<N
,0>;
179 /// get decimal value of @c static_rational
180 template<class T
,integer_type N
,integer_type D
>
181 inline typename divide_typeof_helper
<T
,T
>::type
182 value(const static_rational
<N
,D
>&)
189 #ifndef BOOST_UNITS_DOXYGEN
196 struct plus_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
198 template<class T0
, class T1
>
200 typedef typename
boost::units::static_rational
<
202 boost::mpl::times
<typename
T0::N_type
, typename
T1::D_type
>,
203 boost::mpl::times
<typename
T1::N_type
, typename
T0::D_type
>
205 ::boost::mpl::times
<typename
T0::D_type
, typename
T1::D_type
>::value
211 struct minus_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
213 template<class T0
, class T1
>
215 typedef typename
boost::units::static_rational
<
217 boost::mpl::times
<typename
T0::N_type
, typename
T1::D_type
>,
218 boost::mpl::times
<typename
T1::N_type
, typename
T0::D_type
>
220 ::boost::mpl::times
<typename
T0::D_type
, typename
T1::D_type
>::value
226 struct times_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
228 template<class T0
, class T1
>
230 typedef typename
boost::units::static_rational
<
231 ::boost::mpl::times
<typename
T0::N_type
, typename
T1::N_type
>::value
,
232 ::boost::mpl::times
<typename
T0::D_type
, typename
T1::D_type
>::value
238 struct divides_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
240 template<class T0
, class T1
>
242 typedef typename
boost::units::static_rational
<
243 ::boost::mpl::times
<typename
T0::N_type
, typename
T1::D_type
>::value
,
244 ::boost::mpl::times
<typename
T0::D_type
, typename
T1::N_type
>::value
250 struct negate_impl
<boost::units::detail::static_rational_tag
>
254 typedef typename
boost::units::static_rational
<
255 ::boost::mpl::negate
<typename
T0::N_type
>::value
,
256 ::boost::mpl::identity
<T0
>::type::Denominator
262 struct less_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
264 template<class T0
, class T1
>
267 typedef mpl::bool_
<((mpl::minus
<T0
, T1
>::type::Numerator
) < 0)> type
;
274 struct plus_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
276 template<class T0
, class T1
>
278 typedef typename
boost::units::static_rational
<
279 T0::Numerator
*T1::Denominator
+T1::Numerator
*T0::Denominator
,
280 T0::Denominator
*T1::Denominator
286 struct minus_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
288 template<class T0
, class T1
>
290 typedef typename
boost::units::static_rational
<
291 T0::Numerator
*T1::Denominator
-T1::Numerator
*T0::Denominator
,
292 T0::Denominator
*T1::Denominator
298 struct times_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
300 template<class T0
, class T1
>
302 typedef typename
boost::units::static_rational
<
303 T0::Numerator
*T1::Numerator
,
304 T0::Denominator
*T1::Denominator
310 struct divides_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
312 template<class T0
, class T1
>
314 typedef typename
boost::units::static_rational
<
315 T0::Numerator
*T1::Denominator
,
316 T0::Denominator
*T1::Numerator
322 struct negate_impl
<boost::units::detail::static_rational_tag
>
326 typedef typename
boost::units::static_rational
<-T0::Numerator
,T0::Denominator
>::type type
;
331 struct less_impl
<boost::units::detail::static_rational_tag
, boost::units::detail::static_rational_tag
>
333 template<class T0
, class T1
>
336 typedef mpl::bool_
<((mpl::minus
<T0
, T1
>::type::Numerator
) < 0)> type
;
349 #endif // BOOST_UNITS_STATIC_RATIONAL_HPP