basix_doc 0.1
/Users/mourrain/Devel/mmx/basix/include/basix/int.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : int.hpp
00004 * DESCRIPTION: additional operations for hardware integers
00005 * COPYRIGHT  : (C) 2008  Gregoire Lecerf
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #ifndef __MMX__INT__HPP
00014 #define __MMX__INT__HPP
00015 #include "basix/port.hpp"
00016 
00017 namespace mmx {
00018 
00019 inline void set_maximal (int& x) {
00020   x= (int) (((nat) (-1)) >> 1); }
00021 inline void set_minimal (int& x) {
00022   x= (int) ((((nat) (-1)) >> 1) + 1); }
00023 inline void set_maximal (nat& x) {
00024   x= (nat) (-1); }
00025 inline void set_minimal (nat& x) {
00026   x= (nat) 0; }
00027 inline void set_maximal (long int& x) {
00028   x= (long int) (((long unsigned int) (-1)) >> 1); }
00029 inline void set_minimal (long int& x) {
00030   x= (long int) ((((long unsigned int) (-1)) >> 1) + 1); }
00031 inline void set_maximal (long unsigned int& x) {
00032   x= (long unsigned int) (-1); }
00033 inline void set_minimal (long unsigned int& x) {
00034   x= (long unsigned int) 0; }
00035 
00036 inline nat
00037 log_2 (nat p) {
00038   nat i=0;
00039   while (p>1) {
00040     p >>= 1;
00041     i++;
00042   }
00043   return i;
00044 }
00045 
00046 inline nat
00047 next_power_of_two (nat p) {
00048   // return 0 in case of overflow
00049   nat n= 1;
00050   while (n < p && n != 0)
00051     n = n << 1;
00052   return n;
00053 }
00054 
00055 inline bool
00056 is_power_of_two (nat p) {
00057   if (p == 0) return false;
00058   while ((p & 1) == 0) p >>= 1;
00059   return p == 1;
00060 }
00061 
00062 inline nat // inline instead of static in order to avoid warnings
00063 log_3 (nat p) {
00064   nat i=0;
00065   while (p>1) {
00066     p /= 3;
00067     i++;
00068   }
00069   return i;
00070 }
00071 
00072 inline nat
00073 next_power_of_three (nat p) {
00074   // return 0 in case of overflow
00075   nat n= 1;
00076   while (n < p)
00077     n *= 3;
00078   return (n<p) ? 0 : n;
00079 }
00080 
00082 
00083 // These two macro prevent the compiler from complaining
00084 // when n = 8 * sizeof(C)
00085 #define MMX_SAFE_LEFT_SHIFT_INT(C,a,n)                          \
00086   (((n) >= 8*sizeof(C)) ? ((C) 0) : (((C) a) << ((n)/2)) << ((n)-(n)/2))
00087 
00088 #define MMX_SAFE_RIGHT_SHIFT_INT(C,a,n)                         \
00089   (((n) >= 8*sizeof(C)) ? ((C) 0) : (((C) a) >> ((n)/2)) >> ((n)-(n)/2))
00090 
00092 template<nat s>
00093 struct unsigned_int_with_size_at_least_helper {
00094 private:
00095   template<bool b, typename T, typename E>
00096   struct if_helper { typedef T ret; };
00097   template<typename T, typename E>
00098   struct if_helper<false,T,E> { typedef E ret; };
00099 public:
00100   typedef
00101     typename if_helper<sizeof(unsigned char)>=s, unsigned char,
00102     typename if_helper<sizeof(short unsigned int)>=s, short unsigned int,
00103     typename if_helper<sizeof(unsigned int)>=s, unsigned int,
00104     typename if_helper<sizeof(long unsigned int)>=s, long unsigned int,
00105     typename if_helper<sizeof(long long unsigned int)>=s,
00106                               long long unsigned int,
00107       void >::ret >::ret >::ret >::ret >::ret type ; };
00108 
00110 template<typename C>
00111 struct unsigned_int_with_double_size_helper {
00112   typedef typename
00113   unsigned_int_with_size_at_least_helper<2*sizeof(C)>::type
00114   type; };
00115 
00117 template<typename C>
00118 struct signed_of_helper {
00119   typedef void type; };
00120 
00121 template<>
00122 struct signed_of_helper<double> {
00123   typedef double type; };
00124 
00125 template<>
00126 struct signed_of_helper<char> {
00127   typedef signed char type; };
00128 
00129 template<>
00130 struct signed_of_helper<signed char> {
00131   typedef signed char type; };
00132 
00133 template<>
00134 struct signed_of_helper<short int> {
00135   typedef short int type; };
00136 
00137 template<>
00138 struct signed_of_helper<int> {
00139   typedef int type; };
00140 
00141 template<>
00142 struct signed_of_helper<long int> {
00143   typedef long int type; };
00144 
00145 template<>
00146 struct signed_of_helper<long long int> {
00147   typedef long long int type; };
00148 
00149 template<>
00150 struct signed_of_helper<unsigned char> {
00151   typedef signed char type; };
00152 
00153 template<>
00154 struct signed_of_helper<short unsigned int> {
00155   typedef short int type; };
00156 
00157 template<>
00158 struct signed_of_helper<unsigned int> {
00159   typedef int type; };
00160 
00161 template<>
00162 struct signed_of_helper<long unsigned int> {
00163   typedef long int type; };
00164 
00165 template<>
00166 struct signed_of_helper<long long unsigned int> {
00167   typedef long long int type; };
00168 
00170 template<typename C>
00171 struct unsigned_of_helper {
00172   typedef void type; };
00173 
00174 template<>
00175 struct unsigned_of_helper<char> {
00176   typedef unsigned char type; };
00177 
00178 template<>
00179 struct unsigned_of_helper<signed char> {
00180   typedef unsigned char type; };
00181 
00182 template<>
00183 struct unsigned_of_helper<short int> {
00184   typedef unsigned short int type; };
00185 
00186 template<>
00187 struct unsigned_of_helper<int> {
00188   typedef unsigned int type; };
00189 
00190 template<>
00191 struct unsigned_of_helper<long int> {
00192   typedef long unsigned int type; };
00193 
00194 template<>
00195 struct unsigned_of_helper<long long int> {
00196   typedef long long unsigned int type; };
00197 
00198 template<>
00199 struct unsigned_of_helper<unsigned char> {
00200   typedef unsigned char type; };
00201 
00202 template<>
00203 struct unsigned_of_helper<short unsigned int> {
00204   typedef short unsigned int type; };
00205 
00206 template<>
00207 struct unsigned_of_helper<unsigned int> {
00208   typedef unsigned int type; };
00209 
00210 template<>
00211 struct unsigned_of_helper<long unsigned int> {
00212   typedef long unsigned int type; };
00213 
00214 template<>
00215 struct unsigned_of_helper<long long unsigned int> {
00216   typedef long long unsigned int type; };
00217 
00219 template<typename C>
00220 struct is_signed_helper {
00221   static const bool value = false; };
00222 
00223 template<>
00224 struct is_signed_helper<signed char> {
00225   static const bool value = true; };
00226 
00227 template<>
00228 struct is_signed_helper<char> {
00229   static const bool value = true; };
00230 
00231 template<>
00232 struct is_signed_helper<short int> {
00233   static const bool value = true; };
00234 
00235 template<>
00236 struct is_signed_helper<int> {
00237   static const bool value = true; };
00238 
00239 template<>
00240 struct is_signed_helper<long int> {
00241   static const bool value = true; };
00242 
00243 template<>
00244 struct is_signed_helper<long long int> {
00245   static const bool value = true; };
00246 
00248 template<typename uC, nat s, uC x>
00249 struct int_bitsize_helper_rec {
00250   static const nat s2  = s >> 1;
00251   static const uC mask = (uC) MMX_SAFE_LEFT_SHIFT_INT(uC,-1,s2);
00252   static const uC size = (x & mask) ?
00253     (s2 + int_bitsize_helper_rec< uC, s2, (x >> s2)>::size) :
00254     int_bitsize_helper_rec< uC, s2, x >::size;
00255 };
00256   
00257 template<typename uC, uC x>
00258 struct int_bitsize_helper_rec <uC, 1, x> {
00259   static const uC size = (x == 0) ? 0 : 1; };
00260 
00261 template<typename uC, uC x>
00262 struct int_bitsize_helper_rec <uC, 0, x> {
00263   static const uC size = 0; };
00264 
00265 template<typename C, C p>
00266 struct int_bitsize_helper {
00267   typedef typename unsigned_of_helper<C>::type uC;
00268   static const uC up = (p < 0) ? -p : p;
00269 
00270   static const nat value =
00271     int_bitsize_helper_rec < uC, 8*sizeof(C), up >::size;
00272 };
00273 
00275 template<typename C> static inline nat
00276 bit_size (const C& p) {
00277   typedef typename unsigned_of_helper<C>::type uC;
00278   if (p == 0) return 0;
00279   uC up = abs (p);
00280   nat s = 0;
00281   nat k = 4 * sizeof(C);
00282   uC mask = ((uC) -1) << k;
00283   while (k != 0) {
00284     if (up & mask) { up >>= k; s += k; }
00285     k >>= 1;
00286     mask >>= k;
00287   }
00288   return up == 0 ? s : s + 1;
00289 }
00290 
00291 template<typename C>
00292 class long_int_mul_op {
00293   typedef typename unsigned_of_helper<C>::type uC;
00294   static const nat n2 = 4 * sizeof (uC);
00295   static const nat n  = 2 * n2;
00296   static const uC lo_mask = ((uC) -1) >> n2;
00297   static const uC carry = ((uC) 1) << n2;
00298   // Let B = (1 << n2),  R = B^2.
00299 
00300   static inline uC
00301   lo (const uC& s) { return s & lo_mask; }
00302     
00303   static inline uC
00304   hi (const uC& s) { return s >> n2; }
00305 
00306 public:
00308   static void
00309   op (uC& dest1, uC& dest0, const uC& a, const uC& b) {
00310     uC t0, t1;
00311     uC lo_a = lo (a);
00312     uC hi_a = hi (a);
00313     uC lo_b = lo (b);
00314     uC hi_b = hi (b);
00315     dest0 = lo_a * lo_b;
00316     dest1 = hi_a * hi_b;
00317     t0 = hi_a * lo_b;
00318     t1 = t0 + lo_a * hi_b;
00319     if (t1 < t0) dest1 += carry;
00320     t0 = lo (t1) << n2;
00321     dest0 += t0;
00322     dest1 += hi (t1);
00323     if (dest0 < t0) dest1++;
00324   }
00325 };
00326 
00327 template<typename C>
00328 struct long_int_rshift_op {
00329   typedef typename unsigned_of_helper<C>::type uC;
00330   static const nat n2 = 4 * sizeof (uC);
00331   static const nat n  = 2 * n2;
00332   // Let B = (1 << n2),  R = B^2.
00333 
00335   static inline void
00336   op (uC& dest1, uC& dest0, nat s) {
00337     if (s == 0) return;
00338     if (s < n) {
00339       dest0 = (dest0 >> s) | (dest1 << (n - s));
00340       dest1 = dest1 >> s;
00341     }
00342     else {
00343       dest0 = dest1 >> (s - n);
00344       dest1 = 0;
00345     }
00346   }
00347     
00350   static inline bool
00351   op_b (uC& dest1, uC& dest0, nat s) {
00352     bool ans;
00353     if (s == 0) return false;
00354     if (s < n) {
00355       ans = (dest0 & (((uC) -1) >> (n - s))) != 0;
00356       dest0 = (dest0 >> s) | (dest1 << (n - s));
00357       dest1 = dest1 >> s;
00358     }
00359     else {
00360       ans = dest0 != 0 || (dest1 & (((uC) -1) >> (2*n - s))) != 0;
00361       dest0 = dest1 >> (s - n);
00362       dest1 = 0;
00363     }
00364     return ans;
00365   }
00366 };
00367 
00368 template<typename C>
00369 struct long_int_lshift_op {
00370   typedef typename unsigned_of_helper<C>::type uC;
00371   static const nat n2 = 4 * sizeof (uC);
00372   static const nat n  = 2 * n2;
00373   // Let B = (1 << n2),  R = B^2.
00374 
00376   static inline void
00377   op (uC& dest1, uC& dest0, nat s) {
00378     if (s == 0) return;
00379     if (s < n) {
00380       dest1 = (dest1 << s) | (dest0 >> (n - s));
00381       dest0 = dest0 << s;
00382     }
00383     else {
00384       dest1 = dest0 << (s - n);
00385       dest0 = 0;
00386     }
00387   }
00388 };
00389 
00390 template<typename C>
00391 struct long_int_sub_op {
00392   typedef typename unsigned_of_helper<C>::type uC;
00393 
00395   static inline void
00396   op (uC& dest1, uC& dest0, const uC& s1, const uC& s0) {
00397     if (dest0 >= s0) {
00398       dest0 -= s0;
00399       dest1 -= s1;
00400     }
00401     else {
00402       dest0 -= s0;
00403       dest1 -= s1 + 1;
00404     }
00405   }
00406 };
00407 
00408 template<typename C>
00409 struct long_int_ge_op {
00410   typedef typename unsigned_of_helper<C>::type uC;
00411 
00413   static inline bool
00414   op (const uC& s1, const uC& s0, const uC& t1, const uC& t0) {
00415     if (s1 > t1) return true;
00416     if (s1 < t1) return false;
00417     return s0 >= t0;
00418   }
00419 };
00420 
00421 /******************************************************************************
00422 * Division
00423 ******************************************************************************/
00424 
00425 #define INT_DIV_DECLARE(I)                                              \
00426   inline bool divides (const I& n, const I& m) { return (m % n) == 0; } \
00427   inline I rem (const I& n, const I& m) { return m == 0 ? n : n % m; }  \
00428   inline I quo (const I& n, const I& m) { return m == 0 ? 0 : n / m; }  \
00429   inline I rem (const I& n, const I& m, I& q) {                         \
00430     I _q= quo (n, m); I _r= n - _q * m; q= _q; return _r; }
00431 INT_DIV_DECLARE(signed char)
00432 INT_DIV_DECLARE(short int)
00433 INT_DIV_DECLARE(int)
00434 INT_DIV_DECLARE(long int)
00435 INT_DIV_DECLARE(long long int)
00436 INT_DIV_DECLARE(unsigned char)
00437 INT_DIV_DECLARE(unsigned short int)
00438 INT_DIV_DECLARE(unsigned int)
00439 INT_DIV_DECLARE(unsigned long int)
00440 INT_DIV_DECLARE(unsigned long long int)
00441 #undef INT_DIV_DECLARE
00442 
00443 /******************************************************************************
00444 * Gcd
00445 ******************************************************************************/
00446 
00447 struct int_gcd_helper {
00448   template<typename I>
00449   static I gcd (const I& a, const I& b) {
00450     typedef typename unsigned_of_helper<I>::type U;
00451     I r0 = a, r1 = b, q, t;
00452     if ((r0 == 0) && (r1 != 0)) {
00453       q = (((U) r0) - ((U) r1)) / ((U) r1) + 1;
00454       t = r0 - q * r1;
00455       r0 = r1;
00456       r1 = t;
00457     }
00458     while (r1 != 0) {
00459       q = r0 / r1;
00460       t = r0 - q * r1;
00461       r0 = r1;
00462       r1 = t;
00463     }
00464     return r0;
00465   }
00466 
00467   template<typename I>
00468   static I gcd (const I& a, const I& b, I& co_a) {
00469     typedef typename unsigned_of_helper<I>::type U;
00470     I r0 = a, r1 = b, co_a0 = 1, co_a1 = 0, q, t;
00471     if ((r0 == 0) && (r1 != 0)) {
00472       q = (((U) r0) - ((U) r1)) / ((U) r1) + 1;
00473       t = r0 - q * r1;
00474       r0 = r1;
00475       r1 = t;
00476       t = co_a1;
00477       co_a1 = co_a0 - q * co_a1;
00478       co_a0 = t;
00479     }
00480     while (r1 != 0) {
00481       q = r0 / r1;
00482       t = r0 - q * r1;
00483       r0 = r1;
00484       r1 = t;
00485       t = co_a1;
00486       co_a1 = co_a0 - q * co_a1;
00487       co_a0 = t;
00488     }
00489     co_a = co_a0;
00490     return r0;
00491   }
00492   
00493   template<typename I>
00494   static I gcd (const I& a, const I& b, I& co_a, I& co_b) {
00495     typedef typename unsigned_of_helper<I>::type U;
00496     I r0 = a, r1 = b, co_a0 = 1, co_a1 = 0, co_b0 = 0, co_b1 = 1, q, t;
00497     if ((r0 == 0) && (r1 != 0)) {
00498       q = (((U) r0) - ((U) r1)) / ((U) r1) + 1;
00499       t = r0 - q * r1;
00500       r0 = r1;
00501       r1 = t;
00502       t = co_a1;
00503       co_a1 = co_a0 - q * co_a1;
00504       co_a0 = t;
00505       t = co_b1;
00506       co_b1 = co_b0 - q * co_b1;
00507       co_b0 = t;
00508     }
00509     while (r1 != 0) {
00510       q = r0 / r1;
00511       t = r0 - q * r1;
00512       r0 = r1;
00513       r1 = t;
00514       t = co_a1;
00515       co_a1 = co_a0 - q * co_a1;
00516       co_a0 = t;
00517       t = co_b1;
00518       co_b1 = co_b0 - q * co_b1;
00519       co_b0 = t;
00520     }
00521     co_a = co_a0;
00522     co_b = co_b0;
00523     return r0;
00524   }
00525 };
00526 
00527 struct unsigned_int_gcd_helper {
00528   template<typename I>
00529   static I gcd (const I& a, const I& b) {
00530     I r0=a, r1=b, q, t; 
00531     if ((r0 == 0) && (r1 != 0)) {
00532       q = (r0-r1) / r1 + 1;
00533       t = r0 - q * r1;
00534       r0 = r1;
00535       r1 = t;
00536     }
00537     while (r1 != 0) {
00538       q = r0 / r1;
00539       t = r0 - q * r1;
00540       r0 = r1;
00541       r1 = t;
00542     }
00543     return r0;
00544   }
00545 };
00546 
00547 #define INT_GCD_DECLARE(I)                                              \
00548   inline I gcd (const I a, const I b) {                                 \
00549     return int_gcd_helper::gcd (a, b); }                                \
00550                                                                         \
00551   inline I gcd (const I a, const I b, I& co_a) {                        \
00552     return int_gcd_helper::gcd (a, b, co_a); }                          \
00553                                                                         \
00554   inline I gcd (const I a, const I b, I& co_a, I& co_b) {               \
00555     return int_gcd_helper::gcd (a, b, co_a, co_b); }
00556   
00557 INT_GCD_DECLARE(signed char)
00558 INT_GCD_DECLARE(short int)
00559 INT_GCD_DECLARE(int)
00560 INT_GCD_DECLARE(long int)
00561 INT_GCD_DECLARE(long long int)
00562 #undef INT_GCD_DECLARE
00563 
00564 #define UINT_GCD_DECLARE(I)                                             \
00565   inline I gcd (const I a, const I b) {                                 \
00566     return unsigned_int_gcd_helper::gcd (a, b); }
00567 
00568 UINT_GCD_DECLARE(unsigned char)
00569 UINT_GCD_DECLARE(unsigned short int)
00570 UINT_GCD_DECLARE(unsigned int)
00571 UINT_GCD_DECLARE(unsigned long int)
00572 UINT_GCD_DECLARE(unsigned long long int)
00573 #undef UINT_GCD_DECLARE
00574 
00575 }// namespace mmx
00576 #endif //__MMX__INT__HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines