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