Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/units/static_rational.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Boost.Units - A C++ library for zero-overhead dimensional analysis and 
0002 // unit/quantity manipulation and conversion
0003 //
0004 // Copyright (C) 2003-2008 Matthias Christian Schabel
0005 // Copyright (C) 2008 Steven Watanabe
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See
0008 // accompanying file LICENSE_1_0.txt or copy at
0009 // http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 #ifndef BOOST_UNITS_STATIC_RATIONAL_HPP 
0012 #define BOOST_UNITS_STATIC_RATIONAL_HPP
0013 
0014 #include <boost/integer/common_factor_ct.hpp>
0015 #include <boost/mpl/less.hpp>
0016 #include <boost/mpl/arithmetic.hpp>
0017 
0018 #ifdef BOOST_BORLANDC
0019 #include <boost/mpl/eval_if.hpp>
0020 #include <boost/mpl/integral_c.hpp>
0021 #include <boost/mpl/identity.hpp>
0022 #endif
0023 
0024 #include <boost/units/config.hpp>
0025 #include <boost/units/operators.hpp>
0026 
0027 /// \file 
0028 /// \brief Compile-time rational numbers and operators.
0029 
0030 namespace boost {
0031 
0032 namespace units { 
0033 
0034 namespace detail {
0035 
0036 struct static_rational_tag {};
0037 
0038 }
0039 
0040 typedef long   integer_type;
0041 
0042 /// Compile time absolute value.
0043 template<integer_type Value>
0044 struct static_abs
0045 {
0046     BOOST_STATIC_CONSTANT(integer_type,value = Value < 0 ? -Value : Value);
0047 };
0048 
0049 // Compile time rational number.
0050 /** 
0051 This is an implementation of a compile time rational number, where @c static_rational<N,D> represents
0052 a rational number with numerator @c N and denominator @c D. Because of the potential for ambiguity arising 
0053 from multiple equivalent values of @c static_rational (e.g. @c static_rational<6,2>==static_rational<3>), 
0054 static rationals should always be accessed through @c static_rational<N,D>::type. Template specialization 
0055 prevents instantiation of zero denominators (i.e. @c static_rational<N,0>). The following compile-time 
0056 arithmetic operators are provided for static_rational variables only (no operators are defined between 
0057 long and static_rational):
0058     - @c mpl::negate
0059     - @c mpl::plus
0060     - @c mpl::minus
0061     - @c mpl::times
0062     - @c mpl::divides
0063 
0064 Neither @c static_power nor @c static_root are defined for @c static_rational. This is because template types 
0065 may not be floating point values, while powers and roots of rational numbers can produce floating point 
0066 values. 
0067 */
0068 #ifdef BOOST_BORLANDC
0069 
0070 template<integer_type X>
0071 struct make_integral_c {
0072     typedef boost::mpl::integral_c<integer_type, X> type;
0073 };
0074 
0075 template<integer_type N,integer_type D = 1>
0076 class static_rational
0077 {
0078     public:
0079 
0080         typedef static_rational this_type;
0081 
0082         typedef boost::mpl::integral_c<integer_type, N> N_type;
0083         typedef boost::mpl::integral_c<integer_type, D> D_type;
0084 
0085         typedef typename make_integral_c<
0086             (::boost::integer::static_gcd<
0087                 ::boost::units::static_abs<N>::value,
0088                 ::boost::units::static_abs<D>::value
0089             >::value)>::type gcd_type;
0090         typedef typename boost::mpl::eval_if<
0091             boost::mpl::less<
0092                 D_type,
0093                 boost::mpl::integral_c<integer_type, 0>
0094             >,
0095             boost::mpl::negate<gcd_type>,
0096             gcd_type
0097         >::type den_type;
0098         
0099     public: 
0100         // for mpl arithmetic support
0101         typedef detail::static_rational_tag tag;
0102         
0103         BOOST_STATIC_CONSTANT(integer_type, Numerator =
0104             (::boost::mpl::divides<N_type, den_type>::value));
0105         BOOST_STATIC_CONSTANT(integer_type, Denominator =
0106             (::boost::mpl::divides<D_type, den_type>::value));
0107         
0108         /// INTERNAL ONLY
0109         typedef static_rational<N,D>    this_type;
0110         
0111         /// static_rational<N,D> reduced by GCD
0112         typedef static_rational<
0113             (::boost::mpl::divides<N_type, den_type>::value),
0114             (::boost::mpl::divides<D_type, den_type>::value)
0115         >  type;
0116                                  
0117         static BOOST_CONSTEXPR integer_type numerator()     { return Numerator; }
0118         static BOOST_CONSTEXPR integer_type denominator()   { return Denominator; }
0119         
0120         // INTERNAL ONLY
0121         BOOST_CONSTEXPR static_rational() { }
0122         //~static_rational() { }
0123 };
0124 #else
0125 template<integer_type N,integer_type D = 1>
0126 class static_rational
0127 {
0128     private:
0129 
0130         BOOST_STATIC_CONSTEXPR integer_type nabs = static_abs<N>::value,
0131                                             dabs = static_abs<D>::value;
0132         
0133         /// greatest common divisor of N and D
0134         // need cast to signed because static_gcd returns unsigned long
0135         BOOST_STATIC_CONSTEXPR integer_type den = 
0136             static_cast<integer_type>(boost::integer::static_gcd<nabs,dabs>::value) * ((D < 0) ? -1 : 1);
0137         
0138     public: 
0139         // for mpl arithmetic support
0140         typedef detail::static_rational_tag tag;
0141         
0142         BOOST_STATIC_CONSTEXPR integer_type Numerator = N/den,
0143             Denominator = D/den;
0144         
0145         /// INTERNAL ONLY
0146         typedef static_rational<N,D>    this_type;
0147         
0148         /// static_rational<N,D> reduced by GCD
0149         typedef static_rational<Numerator,Denominator>  type;
0150                                  
0151         static BOOST_CONSTEXPR integer_type numerator()     { return Numerator; }
0152         static BOOST_CONSTEXPR integer_type denominator()   { return Denominator; }
0153         
0154         // INTERNAL ONLY
0155         BOOST_CONSTEXPR static_rational() { }
0156         //~static_rational() { }   
0157 };
0158 #endif
0159 
0160 }
0161 
0162 }
0163 
0164 #if BOOST_UNITS_HAS_BOOST_TYPEOF
0165 
0166 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
0167 
0168 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::static_rational, (long)(long))
0169 
0170 #endif
0171 
0172 namespace boost {
0173 
0174 namespace units {
0175 
0176 // prohibit zero denominator
0177 template<integer_type N> class static_rational<N,0>;
0178 
0179 /// get decimal value of @c static_rational
0180 template<class T,integer_type N,integer_type D>
0181 inline BOOST_CONSTEXPR typename divide_typeof_helper<T,T>::type 
0182 value(const static_rational<N,D>&)
0183 {
0184     return T(N)/T(D);
0185 }
0186 
0187 } // namespace units
0188 
0189 #ifndef BOOST_UNITS_DOXYGEN
0190 
0191 namespace mpl {
0192 
0193 #ifdef BOOST_BORLANDC
0194 
0195 template<>
0196 struct plus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0197 {
0198     template<class T0, class T1>
0199     struct apply {
0200         typedef typename boost::units::static_rational<
0201             ::boost::mpl::plus<
0202                 boost::mpl::times<typename T0::N_type, typename T1::D_type>,
0203                 boost::mpl::times<typename T1::N_type, typename T0::D_type>
0204             >::value,
0205             ::boost::mpl::times<typename T0::D_type, typename T1::D_type>::value
0206         >::type type;
0207     };
0208 };
0209 
0210 template<>
0211 struct minus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0212 {
0213     template<class T0, class T1>
0214     struct apply {
0215         typedef typename boost::units::static_rational<
0216             ::boost::mpl::minus<
0217                 boost::mpl::times<typename T0::N_type, typename T1::D_type>,
0218                 boost::mpl::times<typename T1::N_type, typename T0::D_type>
0219             >::value,
0220             ::boost::mpl::times<typename T0::D_type, typename T1::D_type>::value
0221         >::type type;
0222     };
0223 };
0224 
0225 template<>
0226 struct times_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0227 {
0228     template<class T0, class T1>
0229     struct apply {
0230         typedef typename boost::units::static_rational<
0231             ::boost::mpl::times<typename T0::N_type, typename T1::N_type>::value,
0232             ::boost::mpl::times<typename T0::D_type, typename T1::D_type>::value
0233         >::type type;
0234     };
0235 };
0236 
0237 template<>
0238 struct divides_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0239 {
0240     template<class T0, class T1>
0241     struct apply {
0242         typedef typename boost::units::static_rational<
0243             ::boost::mpl::times<typename T0::N_type, typename T1::D_type>::value,
0244             ::boost::mpl::times<typename T0::D_type, typename T1::N_type>::value
0245         >::type type;
0246     };
0247 };
0248 
0249 template<>
0250 struct negate_impl<boost::units::detail::static_rational_tag>
0251 {
0252     template<class T0>
0253     struct apply {
0254         typedef typename boost::units::static_rational<
0255             ::boost::mpl::negate<typename T0::N_type>::value,
0256             ::boost::mpl::identity<T0>::type::Denominator
0257         >::type type;
0258     };
0259 };
0260 
0261 template<>
0262 struct less_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0263 {
0264     template<class T0, class T1>
0265     struct apply
0266     {
0267         typedef mpl::bool_<((mpl::minus<T0, T1>::type::Numerator) < 0)> type;
0268     };
0269 };
0270 
0271 #else
0272 
0273 template<>
0274 struct plus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0275 {
0276     template<class T0, class T1>
0277     struct apply {
0278         typedef typename boost::units::static_rational<
0279             T0::Numerator*T1::Denominator+T1::Numerator*T0::Denominator,
0280             T0::Denominator*T1::Denominator
0281         >::type type;
0282     };
0283 };
0284 
0285 template<>
0286 struct minus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0287 {
0288     template<class T0, class T1>
0289     struct apply {
0290         typedef typename boost::units::static_rational<
0291             T0::Numerator*T1::Denominator-T1::Numerator*T0::Denominator,
0292             T0::Denominator*T1::Denominator
0293         >::type type;
0294     };
0295 };
0296 
0297 template<>
0298 struct times_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0299 {
0300     template<class T0, class T1>
0301     struct apply {
0302         typedef typename boost::units::static_rational<
0303             T0::Numerator*T1::Numerator,
0304             T0::Denominator*T1::Denominator
0305         >::type type;
0306     };
0307 };
0308 
0309 template<>
0310 struct divides_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0311 {
0312     template<class T0, class T1>
0313     struct apply {
0314         typedef typename boost::units::static_rational<
0315             T0::Numerator*T1::Denominator,
0316             T0::Denominator*T1::Numerator
0317         >::type type;
0318     };
0319 };
0320 
0321 template<>
0322 struct negate_impl<boost::units::detail::static_rational_tag>
0323 {
0324     template<class T0>
0325     struct apply {
0326         typedef typename boost::units::static_rational<-T0::Numerator,T0::Denominator>::type type;
0327     };
0328 };
0329 
0330 template<>
0331 struct less_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
0332 {
0333     template<class T0, class T1>
0334     struct apply
0335     {
0336         typedef mpl::bool_<((mpl::minus<T0, T1>::type::Numerator) < 0)> type;
0337     };
0338 };
0339 
0340 #endif
0341 
0342 
0343 }
0344 
0345 #endif
0346 
0347 } // namespace boost
0348 
0349 #endif // BOOST_UNITS_STATIC_RATIONAL_HPP