basix_doc 0.1
|
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