350 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			350 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| // Boost.Units - A C++ library for zero-overhead dimensional analysis and 
 | |
| // unit/quantity manipulation and conversion
 | |
| //
 | |
| // Copyright (C) 2003-2008 Matthias Christian Schabel
 | |
| // Copyright (C) 2008 Steven Watanabe
 | |
| //
 | |
| // Distributed under the Boost Software License, Version 1.0. (See
 | |
| // accompanying file LICENSE_1_0.txt or copy at
 | |
| // http://www.boost.org/LICENSE_1_0.txt)
 | |
| 
 | |
| #ifndef BOOST_UNITS_STATIC_RATIONAL_HPP 
 | |
| #define BOOST_UNITS_STATIC_RATIONAL_HPP
 | |
| 
 | |
| #include <boost/integer/common_factor_ct.hpp>
 | |
| #include <boost/mpl/less.hpp>
 | |
| #include <boost/mpl/arithmetic.hpp>
 | |
| 
 | |
| #ifdef __BORLANDC__
 | |
| #include <boost/mpl/eval_if.hpp>
 | |
| #include <boost/mpl/integral_c.hpp>
 | |
| #include <boost/mpl/identity.hpp>
 | |
| #endif
 | |
| 
 | |
| #include <boost/units/config.hpp>
 | |
| #include <boost/units/operators.hpp>
 | |
| 
 | |
| /// \file 
 | |
| /// \brief Compile-time rational numbers and operators.
 | |
| 
 | |
| namespace boost {
 | |
| 
 | |
| namespace units { 
 | |
| 
 | |
| namespace detail {
 | |
| 
 | |
| struct static_rational_tag {};
 | |
| 
 | |
| }
 | |
| 
 | |
| typedef long   integer_type;
 | |
| 
 | |
| /// Compile time absolute value.
 | |
| template<integer_type Value>
 | |
| struct static_abs
 | |
| {
 | |
|     BOOST_STATIC_CONSTANT(integer_type,value = Value < 0 ? -Value : Value);
 | |
| };
 | |
| 
 | |
| // Compile time rational number.
 | |
| /** 
 | |
| This is an implementation of a compile time rational number, where @c static_rational<N,D> represents
 | |
| a rational number with numerator @c N and denominator @c D. Because of the potential for ambiguity arising 
 | |
| from multiple equivalent values of @c static_rational (e.g. @c static_rational<6,2>==static_rational<3>), 
 | |
| static rationals should always be accessed through @c static_rational<N,D>::type. Template specialization 
 | |
| prevents instantiation of zero denominators (i.e. @c static_rational<N,0>). The following compile-time 
 | |
| arithmetic operators are provided for static_rational variables only (no operators are defined between 
 | |
| long and static_rational):
 | |
|     - @c mpl::negate
 | |
|     - @c mpl::plus
 | |
|     - @c mpl::minus
 | |
|     - @c mpl::times
 | |
|     - @c mpl::divides
 | |
| 
 | |
| Neither @c static_power nor @c static_root are defined for @c static_rational. This is because template types 
 | |
| may not be floating point values, while powers and roots of rational numbers can produce floating point 
 | |
| values. 
 | |
| */
 | |
| #ifdef __BORLANDC__
 | |
| 
 | |
| template<integer_type X>
 | |
| struct make_integral_c {
 | |
|     typedef boost::mpl::integral_c<integer_type, X> type;
 | |
| };
 | |
| 
 | |
| template<integer_type N,integer_type D = 1>
 | |
| class static_rational
 | |
| {
 | |
|     public:
 | |
| 
 | |
|         typedef static_rational this_type;
 | |
| 
 | |
|         typedef boost::mpl::integral_c<integer_type, N> N_type;
 | |
|         typedef boost::mpl::integral_c<integer_type, D> D_type;
 | |
| 
 | |
|         typedef typename make_integral_c<
 | |
|             (::boost::integer::static_gcd<
 | |
|                 ::boost::units::static_abs<N>::value,
 | |
|                 ::boost::units::static_abs<D>::value
 | |
|             >::value)>::type gcd_type;
 | |
|         typedef typename boost::mpl::eval_if<
 | |
|             boost::mpl::less<
 | |
|                 D_type,
 | |
|                 boost::mpl::integral_c<integer_type, 0>
 | |
|             >,
 | |
|             boost::mpl::negate<gcd_type>,
 | |
|             gcd_type
 | |
|         >::type den_type;
 | |
|         
 | |
|     public: 
 | |
|         // for mpl arithmetic support
 | |
|         typedef detail::static_rational_tag tag;
 | |
|         
 | |
|         BOOST_STATIC_CONSTANT(integer_type, Numerator =
 | |
|             (::boost::mpl::divides<N_type, den_type>::value));
 | |
|         BOOST_STATIC_CONSTANT(integer_type, Denominator =
 | |
|             (::boost::mpl::divides<D_type, den_type>::value));
 | |
|         
 | |
|         /// INTERNAL ONLY
 | |
|         typedef static_rational<N,D>    this_type;
 | |
|         
 | |
|         /// static_rational<N,D> reduced by GCD
 | |
|         typedef static_rational<
 | |
|             (::boost::mpl::divides<N_type, den_type>::value),
 | |
|             (::boost::mpl::divides<D_type, den_type>::value)
 | |
|         >  type;
 | |
|                                  
 | |
|         static integer_type numerator()      { return Numerator; }
 | |
|         static integer_type denominator()    { return Denominator; }
 | |
|         
 | |
|         // INTERNAL ONLY
 | |
|         static_rational() { }
 | |
|         //~static_rational() { }
 | |
| };
 | |
| #else
 | |
| template<integer_type N,integer_type D = 1>
 | |
| class static_rational
 | |
| {
 | |
|     private:
 | |
| 
 | |
|         static const integer_type   nabs = static_abs<N>::value,
 | |
|                                     dabs = static_abs<D>::value;
 | |
|         
 | |
|         /// greatest common divisor of N and D
 | |
|         // need cast to signed because static_gcd returns unsigned long
 | |
|         static const integer_type   den = 
 | |
|             static_cast<integer_type>(boost::integer::static_gcd<nabs,dabs>::value) * ((D < 0) ? -1 : 1);
 | |
|         
 | |
|     public: 
 | |
|         // for mpl arithmetic support
 | |
|         typedef detail::static_rational_tag tag;
 | |
|         
 | |
|         static const integer_type   Numerator = N/den,
 | |
|             Denominator = D/den;
 | |
|         
 | |
|         /// INTERNAL ONLY
 | |
|         typedef static_rational<N,D>    this_type;
 | |
|         
 | |
|         /// static_rational<N,D> reduced by GCD
 | |
|         typedef static_rational<Numerator,Denominator>  type;
 | |
|                                  
 | |
|         static integer_type numerator()      { return Numerator; }
 | |
|         static integer_type denominator()    { return Denominator; }
 | |
|         
 | |
|         // INTERNAL ONLY
 | |
|         static_rational() { }
 | |
|         //~static_rational() { }   
 | |
| };
 | |
| #endif
 | |
| 
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| #if BOOST_UNITS_HAS_BOOST_TYPEOF
 | |
| 
 | |
| #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
 | |
| 
 | |
| BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::static_rational, (long)(long))
 | |
| 
 | |
| #endif
 | |
| 
 | |
| namespace boost {
 | |
| 
 | |
| namespace units {
 | |
| 
 | |
| // prohibit zero denominator
 | |
| template<integer_type N> class static_rational<N,0>;
 | |
| 
 | |
| /// get decimal value of @c static_rational
 | |
| template<class T,integer_type N,integer_type D>
 | |
| inline typename divide_typeof_helper<T,T>::type 
 | |
| value(const static_rational<N,D>&)
 | |
| {
 | |
|     return T(N)/T(D);
 | |
| }
 | |
| 
 | |
| } // namespace units
 | |
| 
 | |
| #ifndef BOOST_UNITS_DOXYGEN
 | |
| 
 | |
| namespace mpl {
 | |
| 
 | |
| #ifdef __BORLANDC__
 | |
| 
 | |
| template<>
 | |
| struct plus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<
 | |
|             ::boost::mpl::plus<
 | |
|                 boost::mpl::times<typename T0::N_type, typename T1::D_type>,
 | |
|                 boost::mpl::times<typename T1::N_type, typename T0::D_type>
 | |
|             >::value,
 | |
|             ::boost::mpl::times<typename T0::D_type, typename T1::D_type>::value
 | |
|         >::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct minus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<
 | |
|             ::boost::mpl::minus<
 | |
|                 boost::mpl::times<typename T0::N_type, typename T1::D_type>,
 | |
|                 boost::mpl::times<typename T1::N_type, typename T0::D_type>
 | |
|             >::value,
 | |
|             ::boost::mpl::times<typename T0::D_type, typename T1::D_type>::value
 | |
|         >::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct times_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<
 | |
|             ::boost::mpl::times<typename T0::N_type, typename T1::N_type>::value,
 | |
|             ::boost::mpl::times<typename T0::D_type, typename T1::D_type>::value
 | |
|         >::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct divides_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<
 | |
|             ::boost::mpl::times<typename T0::N_type, typename T1::D_type>::value,
 | |
|             ::boost::mpl::times<typename T0::D_type, typename T1::N_type>::value
 | |
|         >::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct negate_impl<boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<
 | |
|             ::boost::mpl::negate<typename T0::N_type>::value,
 | |
|             ::boost::mpl::identity<T0>::type::Denominator
 | |
|         >::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct less_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply
 | |
|     {
 | |
|         typedef mpl::bool_<((mpl::minus<T0, T1>::type::Numerator) < 0)> type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| #else
 | |
| 
 | |
| template<>
 | |
| struct plus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<
 | |
|             T0::Numerator*T1::Denominator+T1::Numerator*T0::Denominator,
 | |
|             T0::Denominator*T1::Denominator
 | |
|         >::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct minus_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<
 | |
|             T0::Numerator*T1::Denominator-T1::Numerator*T0::Denominator,
 | |
|             T0::Denominator*T1::Denominator
 | |
|         >::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct times_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<
 | |
|             T0::Numerator*T1::Numerator,
 | |
|             T0::Denominator*T1::Denominator
 | |
|         >::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct divides_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<
 | |
|             T0::Numerator*T1::Denominator,
 | |
|             T0::Denominator*T1::Numerator
 | |
|         >::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct negate_impl<boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0>
 | |
|     struct apply {
 | |
|         typedef typename boost::units::static_rational<-T0::Numerator,T0::Denominator>::type type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| template<>
 | |
| struct less_impl<boost::units::detail::static_rational_tag, boost::units::detail::static_rational_tag>
 | |
| {
 | |
|     template<class T0, class T1>
 | |
|     struct apply
 | |
|     {
 | |
|         typedef mpl::bool_<((mpl::minus<T0, T1>::type::Numerator) < 0)> type;
 | |
|     };
 | |
| };
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| } // namespace boost
 | |
| 
 | |
| #endif // BOOST_UNITS_STATIC_RATIONAL_HPP
 | 
