// -*- C++ -*- // Copyright (C) 2008 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 2, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this library; see the file COPYING. If not, write to // the Free Software Foundation, 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. // As a special exception, you may use this file as part of a free software // library without restriction. Specifically, if other files instantiate // templates or use macros or inline functions from this file, or you compile // this file and link it with other files to produce an executable, this // file does not by itself cause the resulting executable to be covered by // the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. /** @file ratio * This is a Standard C++ Library header. */ #ifndef _GLIBCXX_RATIO #define _GLIBCXX_RATIO 1 #pragma GCC system_header #ifndef __GXX_EXPERIMENTAL_CXX0X__ # include #else #include #include #ifdef _GLIBCXX_USE_C99_STDINT_TR1 namespace std { template struct __static_sign : integral_constant { }; template struct __static_abs : integral_constant::value> { }; template struct __static_gcd; template struct __static_gcd : __static_gcd<_Qn, (_Pn % _Qn)> { }; template struct __static_gcd<_Pn, 0> : integral_constant::value> { }; template struct __static_gcd<0, _Qn> : integral_constant::value> { }; // Let c = 2^(half # of bits in an intmax_t) // then we find a1, a0, b1, b0 s.t. N = a1*c + a0, M = b1*c + b0 // The multiplication of N and M becomes, // N * M = (a1 * b1)c^2 + (a0 * b1 + b0 * a1)c + a0 * b0 // Multiplication is safe if each term and the sum of the terms // is representable by intmax_t. template struct __safe_multiply { private: static const uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); static const uintmax_t __a0 = __static_abs<_Pn>::value % __c; static const uintmax_t __a1 = __static_abs<_Pn>::value / __c; static const uintmax_t __b0 = __static_abs<_Qn>::value % __c; static const uintmax_t __b1 = __static_abs<_Qn>::value / __c; static_assert(__a1 == 0 || __b1 == 0, "overflow in multiplication"); static_assert(__a0 * __b1 + __b0 * __a1 < (__c >> 1), "overflow in multiplication"); static_assert(__b0 * __a0 <= __INTMAX_MAX__, "overflow in multiplication"); static_assert((__a0 * __b1 + __b0 * __a1) * __c <= __INTMAX_MAX__ - __b0 * __a0, "overflow in multiplication"); public: static const intmax_t value = _Pn * _Qn; }; // Helpers for __safe_add template struct __add_overflow_check_impl : integral_constant { }; template struct __add_overflow_check_impl<_Pn, _Qn, false> : integral_constant= -__INTMAX_MAX__ - _Qn)> { }; template struct __add_overflow_check : __add_overflow_check_impl<_Pn, _Qn, (_Qn >= 0)> { }; template struct __safe_add { static_assert(__add_overflow_check<_Pn, _Qn>::value != 0, "overflow in addition"); static const intmax_t value = _Pn + _Qn; }; /** * @brief Provides compile-time rational arithmetic. * * This class template represents any finite rational number with a * numerator and denominator representable by compile-time constants of * type intmax_t. The ratio is simplified when instantiated. * * For example: * @code * std::ratio<7,-21>::num == -1; * std::ratio<7,-21>::den == 3; * @endcode * */ template struct ratio { static_assert(_Den != 0, "denominator cannot be zero"); static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__, "out of range"); // Note: sign(N) * abs(N) == N static const intmax_t num = _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value; static const intmax_t den = __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value; }; template const intmax_t ratio<_Num, _Den>::num; template const intmax_t ratio<_Num, _Den>::den; /// ratio_add template struct ratio_add { private: static const intmax_t __gcd = __static_gcd<_R1::den, _R2::den>::value; public: typedef ratio< __safe_add< __safe_multiply<_R1::num, (_R2::den / __gcd)>::value, __safe_multiply<_R2::num, (_R1::den / __gcd)>::value>::value, __safe_multiply<_R1::den, (_R2::den / __gcd)>::value> type; }; /// ratio_subtract template struct ratio_subtract { typedef typename ratio_add< _R1, ratio<-_R2::num, _R2::den>>::type type; }; /// ratio_multiply template struct ratio_multiply { private: static const intmax_t __gcd1 = __static_gcd<_R1::num, _R2::den>::value; static const intmax_t __gcd2 = __static_gcd<_R2::num, _R1::den>::value; public: typedef ratio< __safe_multiply<(_R1::num / __gcd1), (_R2::num / __gcd2)>::value, __safe_multiply<(_R1::den / __gcd2), (_R2::den / __gcd1)>::value> type; }; /// ratio_divide template struct ratio_divide { static_assert(_R2::num != 0, "division by 0"); typedef typename ratio_multiply< _R1, ratio<_R2::den, _R2::num>>::type type; }; /// ratio_equal template struct ratio_equal : integral_constant { }; /// ratio_not_equal template struct ratio_not_equal : integral_constant::value> { }; template struct __ratio_less_simple_impl : integral_constant::value < __safe_multiply<_R2::num, _R1::den>::value)> { }; // If the denominators are equal or the signs differ, we can just compare // numerators, otherwise fallback to the simple cross-multiply method. template struct __ratio_less_impl : conditional<(_R1::den == _R2::den || (__static_sign<_R1::num>::value != __static_sign<_R2::num>::value)), integral_constant, __ratio_less_simple_impl<_R1, _R2>>::type { }; /// ratio_less template struct ratio_less : __ratio_less_impl<_R1, _R2>::type { }; /// ratio_less_equal template struct ratio_less_equal : integral_constant::value> { }; /// ratio_greater template struct ratio_greater : integral_constant::value> { }; /// ratio_greater_equal template struct ratio_greater_equal : integral_constant::value> { }; typedef ratio<1, 1000000000000000000> atto; typedef ratio<1, 1000000000000000> femto; typedef ratio<1, 1000000000000> pico; typedef ratio<1, 1000000000> nano; typedef ratio<1, 1000000> micro; typedef ratio<1, 1000> milli; typedef ratio<1, 100> centi; typedef ratio<1, 10> deci; typedef ratio< 10, 1> deca; typedef ratio< 100, 1> hecto; typedef ratio< 1000, 1> kilo; typedef ratio< 1000000, 1> mega; typedef ratio< 1000000000, 1> giga; typedef ratio< 1000000000000, 1> tera; typedef ratio< 1000000000000000, 1> peta; typedef ratio< 1000000000000000000, 1> exa; } #endif //_GLIBCXX_USE_C99_STDINT_TR1 #endif //__GXX_EXPERIMENTAL_CXX0X__ #endif //_GLIBCXX_RATIO