Home | History | Annotate | Download | only in include
      1 // ratio -*- C++ -*-
      2 
      3 // Copyright (C) 2008, 2009 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the 
      7 // terms of the GNU General Public License as published by the 
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file ratio
     26  *  This is a Standard C++ Library header.
     27  */
     28 
     29 #ifndef _GLIBCXX_RATIO
     30 #define _GLIBCXX_RATIO 1
     31 
     32 #pragma GCC system_header
     33 
     34 #ifndef __GXX_EXPERIMENTAL_CXX0X__
     35 # include <c++0x_warning.h>
     36 #else
     37 
     38 #include <type_traits>
     39 #include <cstdint>
     40 
     41 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
     42 
     43 namespace std
     44 {
     45   /**
     46    * @defgroup ratio Rational Arithmetic
     47    * @ingroup utilities
     48    *
     49    * Compile time representation of fininte rational numbers.
     50    * @{
     51    */
     52 
     53   template<intmax_t _Pn>
     54     struct __static_sign
     55     : integral_constant<intmax_t, (_Pn < 0) ? -1 : 1>
     56     { };
     57 
     58   template<intmax_t _Pn>
     59     struct __static_abs
     60     : integral_constant<intmax_t, _Pn * __static_sign<_Pn>::value>
     61     { };
     62 
     63   template<intmax_t _Pn, intmax_t _Qn>
     64     struct __static_gcd;
     65  
     66   template<intmax_t _Pn, intmax_t _Qn>
     67     struct __static_gcd
     68     : __static_gcd<_Qn, (_Pn % _Qn)>
     69     { };
     70 
     71   template<intmax_t _Pn>
     72     struct __static_gcd<_Pn, 0>
     73     : integral_constant<intmax_t, __static_abs<_Pn>::value>
     74     { };
     75 
     76   template<intmax_t _Qn>
     77     struct __static_gcd<0, _Qn>
     78     : integral_constant<intmax_t, __static_abs<_Qn>::value>
     79     { };
     80 
     81   // Let c = 2^(half # of bits in an intmax_t)
     82   // then we find a1, a0, b1, b0 s.t. N = a1*c + a0, M = b1*c + b0
     83   // The multiplication of N and M becomes,
     84   // N * M = (a1 * b1)c^2 + (a0 * b1 + b0 * a1)c + a0 * b0
     85   // Multiplication is safe if each term and the sum of the terms
     86   // is representable by intmax_t.
     87   template<intmax_t _Pn, intmax_t _Qn>
     88     struct __safe_multiply
     89     {
     90     private:
     91       static const uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4);
     92 
     93       static const uintmax_t __a0 = __static_abs<_Pn>::value % __c;
     94       static const uintmax_t __a1 = __static_abs<_Pn>::value / __c;
     95       static const uintmax_t __b0 = __static_abs<_Qn>::value % __c;
     96       static const uintmax_t __b1 = __static_abs<_Qn>::value / __c;
     97 
     98       static_assert(__a1 == 0 || __b1 == 0, 
     99         "overflow in multiplication");
    100       static_assert(__a0 * __b1 + __b0 * __a1 < (__c >> 1), 
    101         "overflow in multiplication");
    102       static_assert(__b0 * __a0 <= __INTMAX_MAX__, 
    103         "overflow in multiplication");
    104       static_assert((__a0 * __b1 + __b0 * __a1) * __c <= 
    105         __INTMAX_MAX__ -  __b0 * __a0, "overflow in multiplication");
    106 
    107     public:
    108       static const intmax_t value = _Pn * _Qn;
    109     };
    110 
    111   // Helpers for __safe_add
    112   template<intmax_t _Pn, intmax_t _Qn, bool>
    113     struct __add_overflow_check_impl
    114     : integral_constant<bool, (_Pn <= __INTMAX_MAX__ - _Qn)>
    115     { };
    116 
    117   template<intmax_t _Pn, intmax_t _Qn>
    118     struct __add_overflow_check_impl<_Pn, _Qn, false>
    119     : integral_constant<bool, (_Pn >= -__INTMAX_MAX__ - _Qn)>
    120     { };
    121 
    122   template<intmax_t _Pn, intmax_t _Qn>
    123     struct __add_overflow_check
    124     : __add_overflow_check_impl<_Pn, _Qn, (_Qn >= 0)>
    125     { };
    126 
    127   template<intmax_t _Pn, intmax_t _Qn>
    128     struct __safe_add
    129     {
    130       static_assert(__add_overflow_check<_Pn, _Qn>::value != 0, 
    131         "overflow in addition");
    132 
    133       static const intmax_t value = _Pn + _Qn;
    134     };
    135 
    136   /**
    137    *  @brief Provides compile-time rational arithmetic.
    138    *
    139    *  This class template represents any finite rational number with a
    140    *  numerator and denominator representable by compile-time constants of
    141    *  type intmax_t. The ratio is simplified when instantiated.
    142    *
    143    *  For example:
    144    *  @code
    145    *    std::ratio<7,-21>::num == -1;
    146    *    std::ratio<7,-21>::den == 3;
    147    *  @endcode
    148    *  
    149   */
    150   template<intmax_t _Num, intmax_t _Den = 1>
    151     struct ratio
    152     {
    153       static_assert(_Den != 0, "denominator cannot be zero");
    154       static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__,
    155 		    "out of range");
    156 
    157       // Note: sign(N) * abs(N) == N
    158       static const intmax_t num =
    159         _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value;
    160 
    161       static const intmax_t den =
    162         __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value;
    163     };
    164 
    165   template<intmax_t _Num, intmax_t _Den>
    166     const intmax_t ratio<_Num, _Den>::num;
    167 
    168   template<intmax_t _Num, intmax_t _Den>
    169     const intmax_t ratio<_Num, _Den>::den;
    170 
    171   /// ratio_add
    172   template<typename _R1, typename _R2>
    173     struct ratio_add
    174     {
    175     private:
    176       static const intmax_t __gcd =
    177         __static_gcd<_R1::den, _R2::den>::value;
    178       
    179     public:
    180       typedef ratio<
    181         __safe_add<
    182           __safe_multiply<_R1::num, (_R2::den / __gcd)>::value,
    183           __safe_multiply<_R2::num, (_R1::den / __gcd)>::value>::value,
    184         __safe_multiply<_R1::den, (_R2::den / __gcd)>::value> type;
    185     };
    186 
    187   /// ratio_subtract
    188   template<typename _R1, typename _R2>
    189     struct ratio_subtract
    190     {
    191       typedef typename ratio_add<
    192         _R1,
    193         ratio<-_R2::num, _R2::den>>::type type;
    194     };
    195 
    196   /// ratio_multiply
    197   template<typename _R1, typename _R2>
    198     struct ratio_multiply
    199     {
    200     private:
    201       static const intmax_t __gcd1 =
    202         __static_gcd<_R1::num, _R2::den>::value;
    203       static const intmax_t __gcd2 =
    204         __static_gcd<_R2::num, _R1::den>::value;
    205 
    206     public:
    207       typedef ratio<
    208         __safe_multiply<(_R1::num / __gcd1),
    209                         (_R2::num / __gcd2)>::value,
    210         __safe_multiply<(_R1::den / __gcd2),
    211                         (_R2::den / __gcd1)>::value> type;
    212     };
    213 
    214   /// ratio_divide
    215   template<typename _R1, typename _R2>
    216     struct ratio_divide
    217     {
    218       static_assert(_R2::num != 0, "division by 0");
    219 
    220       typedef typename ratio_multiply<
    221         _R1,
    222         ratio<_R2::den, _R2::num>>::type type;
    223     };
    224 
    225   /// ratio_equal
    226   template<typename _R1, typename _R2>
    227     struct ratio_equal
    228     : integral_constant<bool, _R1::num == _R2::num && _R1::den == _R2::den>
    229     { };
    230   
    231   /// ratio_not_equal
    232   template<typename _R1, typename _R2>
    233     struct ratio_not_equal
    234     : integral_constant<bool, !ratio_equal<_R1, _R2>::value>
    235     { };
    236   
    237   template<typename _R1, typename _R2>
    238     struct __ratio_less_simple_impl
    239     : integral_constant<bool,
    240 			(__safe_multiply<_R1::num, _R2::den>::value
    241 			 < __safe_multiply<_R2::num, _R1::den>::value)>
    242     { };
    243 
    244   // If the denominators are equal or the signs differ, we can just compare
    245   // numerators, otherwise fallback to the simple cross-multiply method.
    246   template<typename _R1, typename _R2>
    247     struct __ratio_less_impl
    248     : conditional<(_R1::den == _R2::den
    249 		   || (__static_sign<_R1::num>::value
    250 		       != __static_sign<_R2::num>::value)),
    251       integral_constant<bool, (_R1::num < _R2::num)>,
    252       __ratio_less_simple_impl<_R1, _R2>>::type
    253     { };
    254 
    255   /// ratio_less
    256   template<typename _R1, typename _R2>
    257     struct ratio_less
    258     : __ratio_less_impl<_R1, _R2>::type
    259     { };
    260     
    261   /// ratio_less_equal
    262   template<typename _R1, typename _R2>
    263     struct ratio_less_equal
    264     : integral_constant<bool, !ratio_less<_R2, _R1>::value>
    265     { };
    266   
    267   /// ratio_greater
    268   template<typename _R1, typename _R2>
    269     struct ratio_greater
    270     : integral_constant<bool, ratio_less<_R2, _R1>::value>
    271     { };
    272 
    273   /// ratio_greater_equal
    274   template<typename _R1, typename _R2>
    275     struct ratio_greater_equal
    276     : integral_constant<bool, !ratio_less<_R1, _R2>::value>
    277     { };
    278 
    279   typedef ratio<1,       1000000000000000000> atto;
    280   typedef ratio<1,          1000000000000000> femto;
    281   typedef ratio<1,             1000000000000> pico;
    282   typedef ratio<1,                1000000000> nano;
    283   typedef ratio<1,                   1000000> micro;
    284   typedef ratio<1,                      1000> milli;
    285   typedef ratio<1,                       100> centi;
    286   typedef ratio<1,                        10> deci;
    287   typedef ratio<                       10, 1> deca;
    288   typedef ratio<                      100, 1> hecto;
    289   typedef ratio<                     1000, 1> kilo;
    290   typedef ratio<                  1000000, 1> mega;
    291   typedef ratio<               1000000000, 1> giga;
    292   typedef ratio<            1000000000000, 1> tera;
    293   typedef ratio<         1000000000000000, 1> peta;
    294   typedef ratio<      1000000000000000000, 1> exa;
    295 
    296   // @} group ratio
    297 }
    298 
    299 #endif //_GLIBCXX_USE_C99_STDINT_TR1
    300 
    301 #endif //__GXX_EXPERIMENTAL_CXX0X__
    302 
    303 #endif //_GLIBCXX_RATIO
    304