numerix_doc 0.4
/Users/mourrain/Devel/mmx/numerix/include/numerix/integer.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : integer.hpp
00004 * DESCRIPTION: Integers
00005 * COPYRIGHT  : (C) 2004  Joris van der Hoeven
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_INTEGER_HPP
00014 #define __MMX_INTEGER_HPP
00015 #include <basix/basix-config.hpp>
00016 #include <numerix/mmx_gmp.hpp>
00017 #include <basix/int.hpp>
00018 namespace mmx {
00019 
00020 class integer;
00021 class integer_rep;
00022 class rational;
00023 template<typename V> class floating;
00024 integer copy (const integer& i);
00025 template<typename T,typename F> struct as_helper;
00026 
00027 /******************************************************************************
00028 * The integer type
00029 ******************************************************************************/
00030 
00031 class integer_rep REP_STRUCT {
00032 private:
00033   mpz_t x;
00034 public:
00035   inline integer_rep () { mpz_init (x); }
00036   inline integer_rep (nat sz) { mpz_init2 (x, sz); }
00037   inline ~integer_rep () { mpz_clear (x); }
00038   friend class integer;
00039   friend class rational;
00040 };
00041 
00042 class integer {
00043 INDIRECT_PROTO (integer, integer_rep)
00044 public: //private:
00045   inline const mpz_t& operator * () const { return rep->x; }
00046   inline mpz_t& operator * () { secure(); return rep->x; }
00047 
00048 public:
00049   // constructors
00050   inline integer (): rep (new integer_rep ()) {}
00051   inline integer (signed char i):
00052     rep (new integer_rep ()) { mpz_set_si (rep->x, i); }
00053   inline integer (unsigned char i):
00054     rep (new integer_rep ()) { mpz_set_ui (rep->x, i); }
00055   inline integer (signed int i):
00056     rep (new integer_rep ()) { mpz_set_si (rep->x, i); }
00057   inline integer (unsigned int i):
00058     rep (new integer_rep ()) { mpz_set_ui (rep->x, i); }
00059   inline integer (signed short int i):
00060     rep (new integer_rep ()) { mpz_set_si (rep->x, i); }
00061   inline integer (unsigned short int i):
00062     rep (new integer_rep ()) { mpz_set_ui (rep->x, i); }
00063   inline integer (signed long int i):
00064     rep (new integer_rep ()) { mpz_set_si (rep->x, i); }
00065   inline integer (unsigned long int i):
00066     rep (new integer_rep ()) { mpz_set_ui (rep->x, i); }
00067 #if defined(BASIX_HAVE_LONG_LONG_INT)
00068   inline integer (signed long long int i):
00069     rep (new integer_rep ()) {
00070     static const nat s = 8*sizeof(unsigned long int);
00071     bool b = false;
00072     if (i<0) { b = true; i = -i; }
00073     mpz_set_ui (rep->x, (unsigned long int)
00074                 MMX_SAFE_RIGHT_SHIFT_INT (unsigned long long int,i,s));
00075     (*this) <<= s;
00076     mpz_add_ui (rep->x, rep->x, (unsigned long int) i);
00077     if (b) mpz_neg (rep->x, rep->x); }
00078   inline integer (unsigned long long int i):
00079     rep (new integer_rep ()) {
00080     static const nat s = 8*sizeof(unsigned long int);
00081     mpz_set_ui (rep->x, (unsigned long int)
00082                 MMX_SAFE_RIGHT_SHIFT_INT (unsigned long long int,i,s));
00083     (*this) <<= s;
00084     mpz_add_ui (rep->x, rep->x,(unsigned long int) i); }
00085 #endif
00086   inline integer (char* s, int base= 10):
00087     rep (new integer_rep ()) { mpz_set_str (rep->x, s, base); }
00088   inline integer (const string& s, int base= 10):
00089     rep (new integer_rep ()) {
00090       char* r= as_charp (s);
00091       mpz_set_str (rep->x, r, base);
00092       free_charp (r); }
00093 
00094   // conversion and input/output
00095   inline friend int as_int (const integer& x) {
00096     return (int) mpz_get_si (*x); }
00097 
00098   inline friend double as_double (const integer& x) {
00099     return mpz_get_d (*x); }
00100 
00101   friend string as_string (const integer& x);
00102 
00103   // basic arithmetic
00104   inline friend integer copy (const integer& x1) {
00105     integer r; mpz_set (*r, *x1); return r; }
00106 
00107   inline friend integer operator - (const integer& x1) {
00108     integer r; mpz_neg (*r, *x1); return r; }
00109 
00110   inline friend integer operator + (const integer& x1, const integer& x2) {
00111     integer r; mpz_add (*r, *x1, *x2); return r; }
00112 
00113   inline friend integer operator - (const integer& x1, const integer& x2) {
00114     integer r; mpz_sub (*r, *x1, *x2); return r; }
00115 
00116   inline friend integer operator * (const integer& x1, const integer& x2) {
00117     integer r; mpz_mul (*r, *x1, *x2); return r; }
00118 
00119   inline friend integer square (const integer& x1) {
00120     integer r; mpz_mul (*r, *x1, *x1); return r; }
00121 
00122   inline friend integer
00123   operator / (const integer& x1, const integer& x2) {
00124     ASSERT (mpz_sgn (*x2) != 0, "division by zero");
00125 #ifdef BASIX_ENABLE_VERIFY
00126     integer r; mpz_fdiv_r (*r, *x1, *x2);
00127     ASSERT (mpz_sgn (*r) == 0, "unexact division");
00128     mpz_divexact (*r, *x1, *x2); return r;
00129 #else
00130     integer r; mpz_divexact (*r, *x1, *x2); return r;
00131 #endif
00132   }
00133   inline friend integer quo (const integer& x1, const integer& x2) {
00134     if (mpz_sgn (*x2) == 0) return x2;
00135     integer r; mpz_fdiv_q (*r, *x1, *x2); return r; }
00136 
00137   inline friend integer rem (const integer& x1, const integer& x2) {
00138     if (mpz_sgn (*x2) == 0) return x1;
00139     integer r; mpz_fdiv_r (*r, *x1, *x2); return r; }
00140 
00141   inline friend bool divides (const integer& x1, const integer& x2) {
00142     return mpz_divisible_p (*x2, *x1); }
00143 
00144   inline friend integer rem (const integer& x1, const integer& x2,
00145                              integer& q) {
00146     if (mpz_sgn (*x2) == 0) { q= x2; return x1; }
00147     integer r; mpz_fdiv_qr (*q, *r, *x1, *x2); return r; }
00148 
00149   inline friend integer operator % (const integer& x1, const integer& x2) {
00150     return rem (x1, x2); }
00151 
00152   inline friend integer& operator %= (integer& x1, const integer& x2) {
00153     x1.secure (); x1= rem (x1, x2); return x1; }
00154 
00155   inline friend integer operator << (const integer& x1, int shift) {
00156     integer r; mpz_mul_2si (*r, *x1, shift); return r; }
00157 
00158   inline friend integer operator >> (const integer& x1, int shift) {
00159     integer r; mpz_mul_2si (*r, *x1, -shift); return r; }
00160 
00161   inline friend integer& operator += (integer& x1, const integer& x2) {
00162     x1.secure (); mpz_add (*x1, *x1, *x2); return x1; }
00163 
00164   inline friend integer& operator -= (integer& x1, const integer& x2) {
00165     x1.secure (); mpz_sub (*x1, *x1, *x2); return x1; }
00166 
00167   inline friend integer& operator *= (integer& x1, const integer& x2) {
00168     x1.secure (); mpz_mul (*x1, *x1, *x2); return x1; }
00169 
00170   inline friend integer& operator <<= (integer& x1, int shift) {
00171     x1.secure (); mpz_mul_2si (*x1, *x1, shift); return x1; }
00172 
00173   inline friend void
00174   neg (integer& r) { r.secure (); mpz_neg (*r, *r); }
00175 
00176   inline friend void
00177   neg (integer& r, const integer& x) { r.secure (); mpz_neg (*r, *x); }
00178 
00179   inline friend void
00180   add (integer& r, const integer& x1, const integer& x2) {
00181     r.secure (); mpz_add (*r, *x1, *x2); }
00182 
00183   inline friend void
00184   sub (integer& r, const integer& x1, const integer& x2) {
00185     r.secure (); mpz_sub (*r, *x1, *x2); }
00186 
00187   inline friend void
00188   mul (integer& r, const integer& x1, const integer& x2) {
00189     r.secure (); mpz_mul (*r, *x1, *x2); }
00190 
00191   inline friend void
00192   mul_add (integer& r, const integer& x1, const integer& x2) {
00193     r.secure (); mpz_addmul (*r, *x1, *x2); }
00194 
00195   inline friend void
00196   mul_sub (integer& r, const integer& x1, const integer& x2) {
00197     r.secure (); mpz_submul (*r, *x1, *x2); }
00198 
00199   // comparing integer numbers
00200   inline friend bool operator == (const integer& x1, const integer& x2) {
00201     return mpz_cmp (*x1, *x2) == 0; }
00202 
00203   inline friend bool operator != (const integer& x1, const integer& x2) {
00204     return mpz_cmp (*x1, *x2) != 0; }
00205 
00206   inline friend bool operator < (const integer& x1, const integer& x2) {
00207     return mpz_cmp (*x1, *x2) < 0; }
00208 
00209   inline friend bool operator > (const integer& x1, const integer& x2) {
00210     return mpz_cmp (*x1, *x2) > 0; }
00211 
00212   inline friend bool operator <= (const integer& x1, const integer& x2) {
00213     return mpz_cmp (*x1, *x2) <= 0; }
00214 
00215   inline friend bool operator >= (const integer& x1, const integer& x2) {
00216     return mpz_cmp (*x1, *x2) >= 0; }
00217 
00218   inline friend int sign (const integer& x1) {
00219     int r= mpz_sgn (*x1); return (r<0? -1: (r==0? 0: 1)); }
00220 
00221   inline friend integer abs (const integer& x1) {
00222     integer r; mpz_abs (*r, *x1); return r; }
00223 
00224   inline friend integer min (const integer& x1, const integer& x2) {
00225     return x1 <= x2? x1: x2; }
00226 
00227   inline friend integer max (const integer& x1, const integer& x2) {
00228     return x1 >= x2? x1: x2; }
00229 
00230   // bit operations
00231   inline friend integer operator & (const integer& x1, const integer& x2) {
00232     integer r; mpz_and (*r, *x1, *x2); return r; }
00233 
00234   inline friend integer operator | (const integer& x1, const integer& x2) {
00235     integer r; mpz_ior (*r, *x1, *x2); return r; }
00236 
00237   inline friend integer operator ^ (const integer& x1, const integer& x2) {
00238     integer r; mpz_xor (*r, *x1, *x2); return r; }
00239 
00240   inline friend integer operator ~ (const integer& x1) {
00241     integer r; mpz_com (*r, *x1); return r; }
00242 
00243   inline bool operator [] (nat index) const {
00244     return (bool) mpz_tstbit (rep->x, index); }
00245 
00246   inline friend nat hamming_norm (const integer& x1) {
00247     return mpz_popcount (*x1); }
00248 
00249   inline friend nat hamming_distance (const integer& x1, const integer& x2) {
00250     return mpz_hamdist (*x1, *x2); }
00251 
00252 // Mixed operations with hardware integers
00253 #define RIGHT_DOWNGRADE_INFIX(op, U, I)                                 \
00254   inline friend integer operator op (const integer& x1, U x2) {         \
00255     return x1 op (unsigned long int) x2; }                              \
00256   inline friend integer operator op (const integer& x1, I x2) {         \
00257     return x1 op (long int) x2; }                                       \
00258 
00259 #define LEFT_DOWNGRADE_INFIX(op, U, I)                                  \
00260   inline friend integer operator op (U x1, const integer& x2) {         \
00261     return (unsigned long int) x1 op x2; }                              \
00262   inline friend integer operator op (I x1, const integer& x2) { \
00263     return (long int) x1 op x2; }
00264 
00265 #define LEFT_DOWNGRADE_INFIX_COMMUTATIVE(op, U, I)                      \
00266   inline friend integer operator op (U x2, const integer& x1) {         \
00267     return x1 op (unsigned long int) x2; }                              \
00268   inline friend integer operator op (I x2, const integer& x1) {         \
00269     return x1 op (long int) x2; }
00270 
00271 #define DOWNGRADE_LONG_LONG(op)                                 \
00272   inline friend integer operator op (unsigned long long int x1,         \
00273                                      const integer& x2) {               \
00274     return integer (x1) op x2; }                                        \
00275   inline friend integer operator op (long long int x1,                  \
00276                                      const integer& x2) {               \
00277     return integer (x1) op x2; }                                        \
00278   inline friend integer operator op (const integer& x1,                 \
00279                                      unsigned long long int x2) {       \
00280     return x1 op integer (x2); }                                        \
00281   inline friend integer operator op (const integer& x1,                 \
00282                                      long long int x2) {                \
00283     return x1 op integer (x2); }
00284 
00285 #define DOWNGRADE_INPLACE(op, U, I)                                     \
00286   inline friend integer& operator op (integer& x1, U x2) {              \
00287     return x1 op (unsigned long int) x2; }                              \
00288   inline friend integer& operator op (integer& x1, I x2) {              \
00289     return x1 op (long int) x2; }
00290   
00291 #define DOWNGRADE_INPLACE_LONG_LONG(op)                                 \
00292   inline friend integer& operator op (integer& x1,                      \
00293                                       unsigned long long x2) {          \
00294     return x1 op integer (x2); }                                        \
00295   inline friend integer& operator op (integer& x1,                      \
00296                                       long long x2) {                   \
00297     return x1 op integer (x2); }
00298   
00299 #define RIGHT_DOWNGRADE_FUN_INPLACE(fun, U, I)                          \
00300   inline friend void fun (integer& r, const integer& x1, U x2) {        \
00301     fun (r, x1, (unsigned long int) x2); }                              \
00302   inline friend void fun (integer& r, const integer& x1, I x2) {        \
00303     fun (r, x1, (long int) x2); }
00304   
00305 #define LEFT_DOWNGRADE_FUN_INPLACE(fun, U, I)                           \
00306   inline friend void fun (integer& r, U x1, const integer& x2) {        \
00307     fun (r, (unsigned long int) x1, x2); }                              \
00308   inline friend void fun (integer& r, I x1, const integer& x2) {        \
00309     fun (r, (long int) x1, x2); }
00310   
00311 #define LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE(fun, U, I)               \
00312   inline friend void fun (integer& r, U x1, const integer& x2) {        \
00313     fun (r, x2, (unsigned long int) x1); }                              \
00314   inline friend void fun (integer& r, I x1, const integer& x2) {        \
00315     fun (r, x2, (long int) x1); }
00316 
00317 #define DOWNGRADE_FUN_INPLACE_LONG_LONG(fun)                            \
00318   inline friend void fun (integer& r, unsigned long long int x1,        \
00319                              const integer& x2) {                       \
00320     fun (r, integer (x1), x2); }                                        \
00321   inline friend void fun (integer& r, long long int x1,                 \
00322                           const integer& x2) {                          \
00323     fun (r, integer (x1), x2); }                                        \
00324   inline friend void fun (integer& r, const integer& x1,                \
00325                           unsigned long long int x2) {                  \
00326     fun (r, x1, integer (x2)); }                                        \
00327   inline friend void fun (integer& r, const integer& x2,                \
00328                           long long int x1) {                           \
00329     fun (r, x1, integer (x2)); }
00330   
00331 #define RIGHT_DOWNGRADE_FUN(fun, U, I)                                  \
00332   inline friend integer fun (const integer& x1, U x2) {                 \
00333     return fun (x1, (unsigned long int) x2); }                          \
00334   inline friend integer fun (const integer& x1, I x2) {                 \
00335     return fun (x1, (long int) x2); }
00336 
00337 #define RIGHT_DOWNGRADE_FUN_X(fun, U, I, X)                             \
00338   inline friend integer fun (const integer& x1, U x2, X x) {            \
00339     return fun (x1, (unsigned long int) x2, x); }                       \
00340   inline friend integer fun (const integer& x1, I x2, X x) {            \
00341     return fun (x1, (long int) x2, x); }
00342 
00343 #define LEFT_DOWNGRADE_FUN(fun, U, I)                                   \
00344   inline friend integer fun (U x1, const integer& x2) {                 \
00345     return fun ((unsigned long int) x1, x2); }                          \
00346   inline friend integer fun (I x1, const integer& x2) {                 \
00347     return fun ((long int) x1, x2); }
00348   
00349 #define LEFT_DOWNGRADE_FUN_X(fun, U, I, X)                              \
00350   inline friend integer fun (U x1, const integer& x2, X x) {            \
00351     return fun ((unsigned long int) x1, x2, x); }                       \
00352   inline friend integer fun (I x1, const integer& x2, X x) {            \
00353     return fun ((long int) x1, x2, x); }
00354 
00355 #define DOWNGRADE_FUN_LONG_LONG(fun)                                    \
00356   inline friend integer fun (unsigned long long int x1,                 \
00357                              const integer& x2) {                       \
00358     return fun (integer (x1), x2); }                                    \
00359   inline friend integer fun (long long int x1,                          \
00360                              const integer& x2) {                       \
00361     return fun (integer (x1), x2); }                                    \
00362   inline friend integer fun (const integer& x1,                         \
00363                              unsigned long long int x2) {               \
00364     return fun (x1, integer (x2)); }                                    \
00365   inline friend integer fun (const integer& x1,                         \
00366                              long long int x2) {                        \
00367     return fun (x1, integer (x2)); }
00368   
00369 #define DOWNGRADE_FUN_X_LONG_LONG(fun, X)                               \
00370   inline friend integer fun (unsigned long long int x1,                 \
00371                              const integer& x2, X x) {                  \
00372     return fun (integer (x1), x2, x); }                                 \
00373   inline friend integer fun (long long int x1,                          \
00374                              const integer& x2, X x) {                  \
00375     return fun (integer (x1), x2, x); }                                 \
00376   inline friend integer fun (const integer& x1,                         \
00377                              unsigned long long int x2, X x) {          \
00378     return fun (x1, integer (x2), x); }                                 \
00379   inline friend integer fun (const integer& x1,                         \
00380                              long long int x2, X x) {                   \
00381     return fun (x1, integer (x2), x); }
00382 
00383 #define RIGHT_DOWNGRADE_TEST(op, U, I)                                  \
00384   inline friend bool operator op (const integer& x1, U x2) {            \
00385     return x1 op (unsigned long int) x2; }                              \
00386   inline friend bool operator op (const integer& x1, I x2) {            \
00387     return x1 op (long int) x2; }                                       \
00388 
00389 #define LEFT_DOWNGRADE_TEST(op, U, I)                                   \
00390   inline friend bool operator op (U x1, const integer& x2) {            \
00391     return (unsigned long int) x1 op x2; }                              \
00392   inline friend bool operator op (I x1, const integer& x2) {            \
00393     return (long int) x1 op x2; }
00394 
00395 #define DOWNGRADE_TEST_LONG_LONG(op)                                    \
00396   inline friend bool operator op (const integer& x1,                    \
00397                                   unsigned long long int x2) {          \
00398     return x1 op integer (x2); }                                        \
00399   inline friend bool operator op (const integer& x1,                    \
00400                                   long long int x2) {                   \
00401     return x1 op integer (x2); }                                        \
00402   inline friend bool operator op (unsigned long long int x1,            \
00403                                   const integer& x2) {                  \
00404     return integer (x1) op x2; }                                        \
00405   inline friend bool operator op (long long int x1,                     \
00406                                   const integer& x2) {                  \
00407     return integer (x1) op x2; }
00408 
00409   inline friend integer operator + (const integer& x1,
00410                                     const unsigned long int& x2) {
00411     integer r; mpz_add_ui (*r, *x1, x2); return r; }
00412   inline friend integer operator + (const integer& x1,
00413                                     const long int& x2) {
00414     integer r;
00415     if (x2 < 0) mpz_sub_ui (*r, *x1, (unsigned long int) (-x2));
00416     else        mpz_add_ui (*r, *x1, (unsigned long int) x2);
00417     return r; }
00418   RIGHT_DOWNGRADE_INFIX (+, unsigned int, int)
00419   RIGHT_DOWNGRADE_INFIX (+, unsigned short int, short int)
00420   RIGHT_DOWNGRADE_INFIX (+, unsigned char, char)
00421   LEFT_DOWNGRADE_INFIX_COMMUTATIVE (+, long unsigned int, long int)
00422   LEFT_DOWNGRADE_INFIX_COMMUTATIVE (+, unsigned int, int)
00423   LEFT_DOWNGRADE_INFIX_COMMUTATIVE (+, unsigned short int, short int)
00424   LEFT_DOWNGRADE_INFIX_COMMUTATIVE (+, unsigned char, char)
00425 #if defined (BASIX_HAVE_LONG_LONG_INT)
00426   DOWNGRADE_LONG_LONG (+)
00427 #endif
00428 
00429   inline friend integer operator - (const integer& x1,
00430                                     unsigned long int x2) {
00431     integer r; mpz_sub_ui (*r, *x1, x2); return r; }
00432   inline friend integer operator - (const integer& x1,
00433                                     long int x2) {
00434     integer r;
00435     if (x2 < 0) mpz_add_ui (*r, *x1, (unsigned long int) (-x2));
00436     else        mpz_sub_ui (*r, *x1, (unsigned long int) x2);
00437     return r; }
00438   RIGHT_DOWNGRADE_INFIX (-, unsigned int, int)
00439   RIGHT_DOWNGRADE_INFIX (-, unsigned short int, short int)
00440   RIGHT_DOWNGRADE_INFIX (-, unsigned char, char)
00441 
00442   inline friend integer operator - (unsigned long int x1,
00443                                     const integer& x2) {
00444     integer r; mpz_ui_sub (*r, x1, *x2); return r; }
00445   inline friend integer operator - (long int x1,
00446                                     const integer& x2) {
00447     integer r;
00448     if (x1 < 0) { mpz_add_ui (*r, *x2, (unsigned long int) (-x1));
00449                   neg (r); }
00450     else          mpz_ui_sub (*r, (unsigned long int) x1, *x2);
00451     return r; }
00452   LEFT_DOWNGRADE_INFIX (-, unsigned int, int)
00453   LEFT_DOWNGRADE_INFIX (-, unsigned short int, short int)
00454   LEFT_DOWNGRADE_INFIX (-, unsigned char, char)
00455 #if defined(BASIX_HAVE_LONG_LONG_INT)
00456   DOWNGRADE_LONG_LONG (-)
00457 #endif
00458 
00459   inline friend integer operator * (const integer& x1,
00460                                     const unsigned long int& x2) {
00461     integer r; mpz_mul_ui (*r, *x1, x2); return r; }
00462   inline friend integer operator * (const integer& x1,
00463                                     const long int& x2) {
00464     integer r; mpz_mul_si (*r, *x1, x2); return r; }
00465   RIGHT_DOWNGRADE_INFIX (*, unsigned int, int)
00466   RIGHT_DOWNGRADE_INFIX (*, unsigned short int, short int)
00467   RIGHT_DOWNGRADE_INFIX (*, unsigned char, char)
00468   LEFT_DOWNGRADE_INFIX_COMMUTATIVE (*, long unsigned int, long int)
00469   LEFT_DOWNGRADE_INFIX_COMMUTATIVE (*, unsigned int, int)
00470   LEFT_DOWNGRADE_INFIX_COMMUTATIVE (*, unsigned short int, short int)
00471   LEFT_DOWNGRADE_INFIX_COMMUTATIVE (*, unsigned char, char)
00472 #if defined(BASIX_HAVE_LONG_LONG_INT)
00473   DOWNGRADE_LONG_LONG (*)
00474 #endif
00475 
00476   inline friend integer operator / (const integer& x1,
00477                                     unsigned long int x2) {
00478     ASSERT (x2 != 0, "division by zero");
00479     integer r; mpz_divexact_ui (*r, *x1, x2); return r; }
00480   inline friend integer operator / (const integer& x1,
00481                                     long int x2) {
00482     ASSERT (x2 != 0, "division by zero");
00483     integer r; 
00484     if (x2 < 0) { mpz_divexact_ui (*r, *x1, (unsigned long int) (-x2));
00485                   neg (r); }
00486     else          mpz_divexact_ui (*r, *x1, (unsigned long int) x2);
00487     return r; }
00488   RIGHT_DOWNGRADE_INFIX (/, unsigned int, int)
00489   RIGHT_DOWNGRADE_INFIX (/, unsigned short int, short int)
00490   RIGHT_DOWNGRADE_INFIX (/, unsigned char, char)
00491 
00492   inline friend integer operator / (unsigned long int x1,
00493                                     const integer& x2) {
00494     return integer (x1) / x2; }
00495   inline friend integer operator / (long int x1,
00496                                     const integer& x2) {
00497     return integer (x1) / x2; }
00498   LEFT_DOWNGRADE_INFIX (/, unsigned int, int)
00499   LEFT_DOWNGRADE_INFIX (/, unsigned short int, short int)
00500   LEFT_DOWNGRADE_INFIX (/, unsigned char, char)
00501 #if defined(BASIX_HAVE_LONG_LONG_INT)
00502   DOWNGRADE_LONG_LONG (/)
00503 #endif
00504 
00505   inline friend integer& operator += (integer& x1, unsigned long int x2) {
00506     x1.secure (); mpz_add_ui (*x1, *x1, x2); return x1; }
00507   inline friend integer& operator += (integer& x1, long int x2) {
00508     x1.secure ();
00509     if (x2 < 0) mpz_sub_ui (*x1, *x1, (unsigned long int) (-x2));
00510     else        mpz_add_ui (*x1, *x1, (unsigned long int) x2);
00511     return x1; }
00512   DOWNGRADE_INPLACE (+=, unsigned int, int)
00513   DOWNGRADE_INPLACE (+=, unsigned short int, short int)
00514   DOWNGRADE_INPLACE (+=, unsigned char, signed char)
00515 #if defined(BASIX_HAVE_LONG_LONG_INT)
00516   DOWNGRADE_INPLACE_LONG_LONG (+=)
00517 #endif
00518 
00519   inline friend integer& operator -= (integer& x1, unsigned long int x2) {
00520     x1.secure (); mpz_sub_ui (*x1, *x1, x2); return x1; }
00521   inline friend integer& operator -= (integer& x1, long int x2) {
00522     x1.secure ();
00523     if (x2 < 0) mpz_add_ui (*x1, *x1, (unsigned long int) (-x2));
00524     else        mpz_sub_ui (*x1, *x1, (unsigned long int) x2);
00525     return x1; }
00526   DOWNGRADE_INPLACE (-=, unsigned int, int)
00527   DOWNGRADE_INPLACE (-=, unsigned short int, short int)
00528   DOWNGRADE_INPLACE (-=, unsigned char, signed char)
00529 #if defined(BASIX_HAVE_LONG_LONG_INT)
00530   DOWNGRADE_INPLACE_LONG_LONG (-=)
00531 #endif
00532 
00533   inline friend integer& operator *= (integer& x1, unsigned long int x2) {
00534     x1.secure (); mpz_mul_ui (*x1, *x1, x2); return x1; }
00535   inline friend integer& operator *= (integer& x1, long int x2) {
00536     x1.secure (); mpz_mul_si (*x1, *x1, x2); return x1; }
00537   DOWNGRADE_INPLACE (*=, unsigned int, int)
00538   DOWNGRADE_INPLACE (*=, unsigned short int, short int)
00539   DOWNGRADE_INPLACE (*=, unsigned char, signed char)
00540 #if defined(BASIX_HAVE_LONG_LONG_INT)
00541   DOWNGRADE_INPLACE_LONG_LONG (*=)
00542 #endif
00543 #if defined(BASIX_HAVE_LONG_LONG_INT)
00544   inline friend void neg (integer& r, unsigned long long int x1) {
00545     neg (r, integer (x1)); }
00546   inline friend void neg (integer& r, long long int x1) {
00547     neg (r, integer (x1)); }
00548 #endif
00549   inline friend void neg (integer& r, unsigned long int x1) {
00550     r.secure (); mpz_set_ui (*r, x1); neg (r); }
00551   inline friend void neg (integer& r, long int x1) {
00552     r.secure (); mpz_set_si (*r, -x1); }
00553   inline friend void neg (integer& r, unsigned int x1) {
00554     r.secure (); mpz_set_ui (*r, x1); neg (r); }
00555   inline friend void neg (integer& r, int x1) {
00556     r.secure (); mpz_set_si (*r, -x1); }
00557   inline friend void neg (integer& r, unsigned short int x1) {
00558     r.secure (); mpz_set_ui (*r, x1); neg (r); }
00559   inline friend void neg (integer& r, short int x1) {
00560     r.secure (); mpz_set_si (*r, -x1); }
00561   inline friend void neg (integer& r, unsigned char x1) {
00562     r.secure (); mpz_set_ui (*r, x1); neg (r); }
00563   inline friend void neg (integer& r, signed char x1) {
00564     r.secure (); mpz_set_si (*r, -x1); }
00565 
00566   inline friend void
00567   add (integer& r, const integer& x1, unsigned long int x2) {
00568     r.secure (); mpz_add_ui (*r, *x1, x2); }
00569   inline friend void
00570   add (integer& r, const integer& x1, long int x2) {
00571     r.secure ();
00572     if (x2 < 0) mpz_sub_ui (*r, *x1, (unsigned long int) (-x2));
00573     else        mpz_add_ui (*r, *x1, (unsigned long int) x2); }
00574   RIGHT_DOWNGRADE_FUN_INPLACE (add, unsigned int, int)
00575   RIGHT_DOWNGRADE_FUN_INPLACE (add, unsigned short int, short int)
00576   RIGHT_DOWNGRADE_FUN_INPLACE (add, unsigned char, signed char)
00577   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (add, unsigned long int, long int)
00578   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (add, unsigned int, int)
00579   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (add, unsigned short int, short int)
00580   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (add, unsigned char, signed char)
00581 #if defined(BASIX_HAVE_LONG_LONG_INT)
00582   DOWNGRADE_FUN_INPLACE_LONG_LONG (add)
00583 #endif
00584 
00585   inline friend void
00586   sub (integer& r, const integer& x1, unsigned long int x2) {
00587     r.secure (); mpz_sub_ui (*r, *x1, x2); }
00588   inline friend void
00589   sub (integer& r, const integer& x1, long int x2) {
00590     r.secure (); 
00591     if (x2 < 0) mpz_add_ui (*r, *x1, (unsigned long int) (-x2));
00592     else        mpz_sub_ui (*r, *x1, (unsigned long int) x2); }
00593   RIGHT_DOWNGRADE_FUN_INPLACE (sub, unsigned int, int)
00594   RIGHT_DOWNGRADE_FUN_INPLACE (sub, unsigned short int, short int)
00595   RIGHT_DOWNGRADE_FUN_INPLACE (sub, unsigned char, signed char)
00596 
00597   inline friend void
00598   sub (integer& r, unsigned long int x1, const integer& x2) {
00599     r.secure (); mpz_ui_sub (*r, x1, *x2); }
00600   inline friend void
00601   sub (integer& r, long int x1, const integer& x2) {
00602     r.secure ();
00603     if (x1 < 0) { mpz_add_ui (*r, *x2, (unsigned long int) (-x1));
00604                   neg (r); }
00605     else          mpz_ui_sub (*r, (unsigned long int) x1, *x2); }
00606   LEFT_DOWNGRADE_FUN_INPLACE (sub, unsigned int, int)
00607   LEFT_DOWNGRADE_FUN_INPLACE (sub, unsigned short int, short int)
00608   LEFT_DOWNGRADE_FUN_INPLACE (sub, unsigned char, signed char)
00609 #if defined(BASIX_HAVE_LONG_LONG_INT)
00610   DOWNGRADE_FUN_INPLACE_LONG_LONG (sub)
00611 #endif
00612 
00613   inline friend void
00614   mul (integer& r, const integer& x1, unsigned long int x2) {
00615     r.secure (); mpz_mul_ui (*r, *x1, x2); }
00616   inline friend void
00617   mul (integer& r, const integer& x1, long int x2) {
00618     r.secure (); mpz_mul_si (*r, *x1, x2); }
00619   RIGHT_DOWNGRADE_FUN_INPLACE (mul, unsigned int, int)
00620   RIGHT_DOWNGRADE_FUN_INPLACE (mul, unsigned short int, short int)
00621   RIGHT_DOWNGRADE_FUN_INPLACE (mul, unsigned char, signed char)
00622   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul, unsigned long int, long int)
00623   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul, unsigned int, int)
00624   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul, unsigned short int, short int)
00625   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul, unsigned char, signed char)
00626 #if defined(BASIX_HAVE_LONG_LONG_INT)
00627   DOWNGRADE_FUN_INPLACE_LONG_LONG (mul)
00628 #endif
00629 
00630   inline friend void
00631   mul_add (integer& r, const integer& x1, unsigned long int x2) {
00632     r.secure (); mpz_addmul_ui (*r, *x1, x2); }
00633   inline friend void
00634   mul_add (integer& r, const integer& x1, long int x2) {
00635     r.secure ();
00636     if (x2 < 0) mpz_submul_ui (*r, *x1, (unsigned long int) (-x2));
00637     else        mpz_addmul_ui (*r, *x1, (unsigned long int) x2);}
00638   RIGHT_DOWNGRADE_FUN_INPLACE (mul_add, unsigned int, int)
00639   RIGHT_DOWNGRADE_FUN_INPLACE (mul_add, unsigned short int, short int)
00640   RIGHT_DOWNGRADE_FUN_INPLACE (mul_add, unsigned char, signed char)
00641   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul_add, unsigned long int, long int)
00642   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul_add, unsigned int, int)
00643   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul_add, unsigned short, short int)
00644   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul_add, unsigned char, signed char)
00645 #if defined(BASIX_HAVE_LONG_LONG_INT)
00646   DOWNGRADE_FUN_INPLACE_LONG_LONG (mul_add)
00647 #endif
00648 
00649   inline friend void
00650   mul_sub (integer& r, const integer& x1, unsigned long int x2) {
00651     r.secure (); mpz_submul_ui (*r, *x1, x2); }
00652   inline friend void
00653   mul_sub (integer& r, const integer& x1, long int x2) {
00654     r.secure ();
00655     if (x2 < 0) mpz_addmul_ui (*r, *x1, (unsigned long int) (-x2));
00656     else        mpz_submul_ui (*r, *x1, (unsigned long int) x2); }
00657   RIGHT_DOWNGRADE_FUN_INPLACE (mul_sub, unsigned int, int)
00658   RIGHT_DOWNGRADE_FUN_INPLACE (mul_sub, unsigned short int, short int)
00659   RIGHT_DOWNGRADE_FUN_INPLACE (mul_sub, unsigned char, signed char)
00660   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul_sub, unsigned long int, long int)
00661   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul_sub, unsigned int, int)
00662   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul_sub, unsigned short, short int)
00663   LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE (mul_sub, unsigned char, signed char)
00664 #if defined(BASIX_HAVE_LONG_LONG_INT)
00665   DOWNGRADE_FUN_INPLACE_LONG_LONG (mul_sub)
00666 #endif
00667 
00668   inline friend integer quo (const integer& x1,
00669                              unsigned long int x2) {
00670     if (x2 == 0) return x2;
00671     integer r; mpz_fdiv_q_ui (*r, *x1, x2); return r; }
00672   inline friend integer quo (const integer& x1,
00673                              const long int& x2) {
00674     return (x2 < 0) ? - quo (x1, (unsigned long int) (-x2)) :
00675       quo (x1, (unsigned long int) x2); }
00676   RIGHT_DOWNGRADE_FUN (quo, unsigned int, int)
00677   RIGHT_DOWNGRADE_FUN (quo, unsigned short int, short int)
00678   RIGHT_DOWNGRADE_FUN (quo, unsigned char, signed char)
00679 
00680   inline friend integer quo (unsigned long int x1,
00681                              const integer& x2) {
00682     return quo (integer (x1), x2); }
00683   inline friend integer quo (long int x1,
00684                              const integer& x2) {
00685     return quo (integer (x1), x2); }
00686   LEFT_DOWNGRADE_FUN (quo, unsigned int, int)
00687   LEFT_DOWNGRADE_FUN (quo, unsigned short int, short int)
00688   LEFT_DOWNGRADE_FUN (quo, unsigned char, signed char)
00689 #if defined(BASIX_HAVE_LONG_LONG_INT)
00690   DOWNGRADE_FUN_LONG_LONG (quo)
00691 #endif
00692 
00693   inline friend integer rem (const integer& x1, unsigned long int x2) {
00694     if (x2 == 0) return x1;
00695     integer r; mpz_fdiv_r_ui (*r, *x1, x2); return r; }
00696   inline friend integer rem (const integer& x1, long int x2) {
00697     return rem (x1, (unsigned long int) abs (x2)); }
00698   RIGHT_DOWNGRADE_FUN (rem, unsigned int, int)
00699   RIGHT_DOWNGRADE_FUN (rem, unsigned short int, short int)
00700   RIGHT_DOWNGRADE_FUN (rem, unsigned char, signed char)
00701 
00702   inline friend integer rem (unsigned long int x1,
00703                              const integer& x2) {
00704     return rem (integer (x1), x2); }
00705   inline friend integer rem (long int x1,
00706                              const integer& x2) {
00707     return rem (integer (x1), x2); }
00708   LEFT_DOWNGRADE_FUN (rem, unsigned int, int)
00709   LEFT_DOWNGRADE_FUN (rem, unsigned short int, short int)
00710   LEFT_DOWNGRADE_FUN (rem, unsigned char, signed char)
00711 #if defined(BASIX_HAVE_LONG_LONG_INT)
00712   DOWNGRADE_FUN_LONG_LONG (rem)
00713 #endif
00714 
00715   inline friend integer rem (const integer& x1, unsigned long int x2,
00716                              integer& q) {
00717     if (x2 == 0) { q= x2; return x1; }
00718     integer r; mpz_fdiv_qr_ui (*q, *r, *x1, x2); return r; }
00719   inline friend integer rem (const integer& x1, long int x2,
00720                              integer& q) {
00721     integer r= rem (x1, (unsigned long int) abs (x2), q);
00722     if (x2 < 0) neg (q); return r; }
00723   RIGHT_DOWNGRADE_FUN_X (rem, unsigned int, int, integer&)
00724   RIGHT_DOWNGRADE_FUN_X (rem, unsigned short int, short int, integer&)
00725   RIGHT_DOWNGRADE_FUN_X (rem, unsigned char, signed char, integer&)
00726 
00727   inline friend integer rem (unsigned long int x1, const integer& x2,
00728                              integer& q) {
00729     return rem (integer (x1), x2, q); }
00730   inline friend integer rem (long int x1, const integer& x2,
00731                              integer& q) {
00732     return rem (integer (x1), x2, q); }
00733   LEFT_DOWNGRADE_FUN_X (rem, unsigned int, int, integer&)
00734   LEFT_DOWNGRADE_FUN_X (rem, unsigned short int, short int, integer&)
00735   LEFT_DOWNGRADE_FUN_X (rem, unsigned char, signed char, integer&)
00736 #if defined(BASIX_HAVE_LONG_LONG_INT)
00737   DOWNGRADE_FUN_X_LONG_LONG (rem, integer&)
00738 #endif
00739 
00740   inline friend integer operator % (const integer& x1,
00741                                     unsigned long int x2) {
00742     return rem (x1, x2); }
00743   inline friend integer operator % (const integer& x1,
00744                                     long int x2) {
00745     return rem (x1, x2); }
00746   RIGHT_DOWNGRADE_INFIX (%, unsigned int, int);
00747   RIGHT_DOWNGRADE_INFIX (%, unsigned short int, short int);
00748   RIGHT_DOWNGRADE_INFIX (%, unsigned char, signed char);
00749 
00750   inline friend integer operator % (unsigned long int x1,
00751                                     const integer& x2) {
00752     return rem (x1, x2); }
00753   inline friend integer operator % (long int x1,
00754                                     const integer& x2) {
00755     return rem (x1, x2); }
00756   LEFT_DOWNGRADE_INFIX (%, unsigned int, int);
00757   LEFT_DOWNGRADE_INFIX (%, unsigned short int, short int);
00758   LEFT_DOWNGRADE_INFIX (%, unsigned char, signed char);
00759 #if defined(BASIX_HAVE_LONG_LONG_INT)
00760   DOWNGRADE_LONG_LONG (%)
00761 #endif
00762 
00763   inline friend bool operator == (const integer& x1, unsigned long int x2) {
00764     return mpz_cmp_ui (*x1, x2) == 0; }
00765   inline friend bool operator == (const integer& x1, long int x2) {
00766     return mpz_cmp_si (*x1, x2) == 0; }
00767   RIGHT_DOWNGRADE_TEST (==, unsigned int, int);
00768   RIGHT_DOWNGRADE_TEST (==, unsigned short int, short int);
00769   RIGHT_DOWNGRADE_TEST (==, unsigned char, signed char);
00770   
00771   inline friend bool operator == (unsigned long int x1, const integer& x2) {
00772     return mpz_cmp_ui (*x2, x1) == 0; }
00773   inline friend bool operator == (long int x1, const integer& x2) {
00774     return mpz_cmp_si (*x2, x1) == 0; }
00775   LEFT_DOWNGRADE_TEST (==, unsigned int, int);
00776   LEFT_DOWNGRADE_TEST (==, unsigned short int, short int);
00777   LEFT_DOWNGRADE_TEST (==, unsigned char, signed char);
00778 #if defined(BASIX_HAVE_LONG_LONG_INT)
00779   DOWNGRADE_TEST_LONG_LONG (==)
00780 #endif
00781 
00782   inline friend bool operator != (const integer& x1, unsigned long int x2) {
00783     return mpz_cmp_ui (*x1, x2) != 0; }
00784   inline friend bool operator != (const integer& x1, long int x2) {
00785     return mpz_cmp_si (*x1, x2) != 0; }
00786   RIGHT_DOWNGRADE_TEST (!=, unsigned int, int);
00787   RIGHT_DOWNGRADE_TEST (!=, unsigned short int, short int);
00788   RIGHT_DOWNGRADE_TEST (!=, unsigned char, signed char);
00789   
00790   inline friend bool operator != (unsigned long int x1, const integer& x2) {
00791     return mpz_cmp_ui (*x2, x1) != 0; }
00792   inline friend bool operator != (long int x1, const integer& x2) {
00793     return mpz_cmp_si (*x2, x1) != 0; }
00794   LEFT_DOWNGRADE_TEST (!=, unsigned int, int);
00795   LEFT_DOWNGRADE_TEST (!=, unsigned short int, short int);
00796   LEFT_DOWNGRADE_TEST (!=, unsigned char, signed char);
00797 #if defined(BASIX_HAVE_LONG_LONG_INT)
00798   DOWNGRADE_TEST_LONG_LONG (!=)
00799 #endif
00800 
00801   inline friend bool operator < (const integer& x1, unsigned long int x2) {
00802     return mpz_cmp_ui (*x1, x2) < 0; }
00803   inline friend bool operator < (const integer& x1, long int x2) {
00804     return mpz_cmp_si (*x1, x2) < 0; }
00805   RIGHT_DOWNGRADE_TEST (<, unsigned int, int);
00806   RIGHT_DOWNGRADE_TEST (<, unsigned short int, short int);
00807   RIGHT_DOWNGRADE_TEST (<, unsigned char, signed char);
00808   
00809   inline friend bool operator < (unsigned long int x1, const integer& x2) {
00810     return mpz_cmp_ui (*x2, x1) > 0; }
00811   inline friend bool operator < (long int x1, const integer& x2) {
00812     return mpz_cmp_si (*x2, x1) > 0; }
00813   LEFT_DOWNGRADE_TEST (<, unsigned int, int);
00814   LEFT_DOWNGRADE_TEST (<, unsigned short int, short int);
00815   LEFT_DOWNGRADE_TEST (<, unsigned char, signed char);
00816 #if defined(BASIX_HAVE_LONG_LONG_INT)
00817   DOWNGRADE_TEST_LONG_LONG (<)
00818 #endif
00819 
00820   inline friend bool operator > (const integer& x1, unsigned long int x2) {
00821     return mpz_cmp_ui (*x1, x2) > 0; }
00822   inline friend bool operator > (const integer& x1, long int x2) {
00823     return mpz_cmp_si (*x1, x2) > 0; }
00824   RIGHT_DOWNGRADE_TEST (>, unsigned int, int);
00825   RIGHT_DOWNGRADE_TEST (>, unsigned short int, short int);
00826   RIGHT_DOWNGRADE_TEST (>, unsigned char, signed char);
00827   
00828   inline friend bool operator > (unsigned long int x1, const integer& x2) {
00829     return mpz_cmp_ui (*x2, x1) < 0; }
00830   inline friend bool operator > (long int x1, const integer& x2) {
00831     return mpz_cmp_si (*x2, x1) < 0; }
00832   LEFT_DOWNGRADE_TEST (>, unsigned int, int);
00833   LEFT_DOWNGRADE_TEST (>, unsigned short int, short int);
00834   LEFT_DOWNGRADE_TEST (>, unsigned char, signed char);
00835 #if defined(BASIX_HAVE_LONG_LONG_INT)
00836   DOWNGRADE_TEST_LONG_LONG (>)
00837 #endif
00838 
00839   inline friend bool operator <= (const integer& x1, unsigned long int x2) {
00840     return mpz_cmp_ui (*x1, x2) <= 0; }
00841   inline friend bool operator <= (const integer& x1, long int x2) {
00842     return mpz_cmp_si (*x1, x2) <= 0; }
00843   RIGHT_DOWNGRADE_TEST (<=, unsigned int, int);
00844   RIGHT_DOWNGRADE_TEST (<=, unsigned short int, short int);
00845   RIGHT_DOWNGRADE_TEST (<=, unsigned char, signed char);
00846   
00847   inline friend bool operator <= (unsigned long int x1, const integer& x2) {
00848     return mpz_cmp_ui (*x2, x1) >= 0; }
00849   inline friend bool operator <= (long int x1, const integer& x2) {
00850     return mpz_cmp_si (*x2, x1) >= 0; }
00851   LEFT_DOWNGRADE_TEST (<=, unsigned int, int);
00852   LEFT_DOWNGRADE_TEST (<=, unsigned short int, short int);
00853   LEFT_DOWNGRADE_TEST (<=, unsigned char, signed char);
00854 #if defined(BASIX_HAVE_LONG_LONG_INT)
00855   DOWNGRADE_TEST_LONG_LONG (<=)
00856 #endif
00857 
00858   inline friend bool operator >= (const integer& x1, unsigned long int x2) {
00859     return mpz_cmp_ui (*x1, x2) >= 0; }
00860   inline friend bool operator >= (const integer& x1, long int x2) {
00861     return mpz_cmp_si (*x1, x2) >= 0; }
00862   RIGHT_DOWNGRADE_TEST (>=, unsigned int, int);
00863   RIGHT_DOWNGRADE_TEST (>=, unsigned short int, short int);
00864   RIGHT_DOWNGRADE_TEST (>=, unsigned char, signed char);
00865   
00866   inline friend bool operator >= (unsigned long int x1, const integer& x2) {
00867     return mpz_cmp_ui (*x2, x1) <= 0; }
00868   inline friend bool operator >= (long int x1, const integer& x2) {
00869     return mpz_cmp_si (*x2, x1) <= 0; }
00870   LEFT_DOWNGRADE_TEST (>=, unsigned int, int);
00871   LEFT_DOWNGRADE_TEST (>=, unsigned short int, short int);
00872   LEFT_DOWNGRADE_TEST (>=, unsigned char, signed char);
00873 #if defined(BASIX_HAVE_LONG_LONG_INT)
00874   DOWNGRADE_TEST_LONG_LONG (>=)
00875 #endif
00876 
00877 #undef RIGHT_DOWNGRADE_INFIX 
00878 #undef LEFT_DOWNGRADE_INFIX
00879 #undef LEFT_DOWNGRADE_INFIX_COMMUTATIVE
00880 #undef LEFT_DOWNGRADE_INFIX
00881 #undef DOWNGRADE_LONG_LONG
00882 #undef RIGHT_DOWNGRADE_FUN_INPLACE
00883 #undef LEFT_DOWNGRADE_FUN_INPLACE
00884 #undef LEFT_DOWNGRADE_FUN_INPLACE_COMMUTATIVE
00885 #undef DOWNGRADE_FUN_INPLACE_LONG_LONG
00886 #undef RIGHT_DOWNGRADE_FUN
00887 #undef RIGHT_DOWNGRADE_FUN_X
00888 #undef LEFT_DOWNGRADE_FUN
00889 #undef DOWNGRADE_FUN_LONG_LONG
00890 #undef RIGHT_DOWNGRADE_TEST 
00891 #undef LEFT_DOWNGRADE_TEST
00892 #undef DOWNGRADE_TEST_LONG_LONG
00893 
00894   // other functions on integers
00895   inline friend bool is_square (const integer& a) {
00896     return mpz_perfect_square_p (*a); }
00897 
00898   inline friend integer sqrt (const integer& a) {
00899     VERIFY (is_square (a), "not a perfect square");
00900     integer r; mpz_sqrt (*r, *a); return r; }
00901 
00902   inline friend integer pow (const integer& x1, const int& i) {
00903     ASSERT (i >= 0, "positive int expected");
00904     integer r; mpz_pow_ui (*r, *x1, (nat) i); return r; }
00905 
00906   inline friend integer pow (const integer& x1, const nat& i) {
00907     integer r; mpz_pow_ui (*r, *x1, i); return r; }
00908 
00909   inline friend integer pow (const integer& x1, const integer& i) {
00910     ASSERT (i >= 0, "positive int expected");
00911     if (i == 0) return 1;
00912     if (x1 == 0) return 0;
00913     if (i == 1) return x1;
00914     if (x1 == 1) return x1;
00915     if (x1 == -1) return as_int (i & 1) ? -1 : 1;
00916     ASSERT (mpz_fits_ulong_p (*i), "exponent too large");
00917     integer r; mpz_pow_ui (*r, *x1, mpz_get_ui (*i));
00918     return r; }
00919 
00920   inline friend integer gcd (const integer& a, const integer& b) {
00921     integer r; mpz_gcd (*r, *a, *b); return r; }
00922 
00923   inline friend integer gcd (const integer& a, const integer& b,
00924                              integer& co_a) {
00925     integer r; mpz_gcdext (*r, *co_a, NULL, *a, *b); return r; }
00926 
00927   inline friend integer gcd (const integer& a, const integer& b,
00928                              integer& co_a, integer& co_b) {
00929     integer r; mpz_gcdext (*r, *co_a, *co_b, *a, *b); return r; }
00930 
00931   inline friend integer lcm (const integer& a, const integer& b) {
00932     integer r; mpz_lcm (*r, *a, *b); return r; }
00933 
00934   inline friend xgcd_matrix<integer> xgcd(const integer& a, const integer& b) {
00935     integer g; xgcd_matrix<integer> r;
00936     mpz_gcdext (*g, *(r.a), *(r.b), *a, *b);
00937     r.c= -b/g; r.d= a/g; return r; }
00938 
00939   inline friend integer invert_modulo (const integer& a, const integer& b) {
00940     integer r; mpz_invert (*r, *a, *b); return r; }
00941 
00942   inline friend int jacobi (const integer& a, const integer& b) {
00943     ASSERT ((b&1) != 0, "second argument must be odd");
00944     return mpz_jacobi (*a, *b); }
00945 
00946   inline friend int legendre (const integer& a, const integer& b) {
00947     ASSERT ((b&1) != 0, "second argument must be odd");
00948     return mpz_legendre (*a, *b); }
00949 
00950   inline friend int kronecker (const integer& a, const integer& b) {
00951     return mpz_kronecker (*a, *b); }
00952 
00953   // trivial rounding routines
00954   inline friend integer floor (const integer& x) { return x; }
00955   inline friend integer trunc (const integer& x) { return x; }
00956   inline friend integer ceil (const integer& x) { return x; }
00957   inline friend integer round (const integer& x) { return x; }
00958 
00959   // miscellaneous functions
00960   inline friend integer raw_integer (nat limb_sz);
00961 
00962   inline friend nat hash (const integer& x) {
00963     const __mpz_struct& rep= (*x)[0];
00964     if (rep._mp_size == 0) return 0;
00965     return ((nat) (rep._mp_d[0])) ^ ((nat) (rep._mp_size << 11));
00966   }
00967 
00968   inline friend xnat size (const integer& x, nat base) {
00969     return mpz_sizeinbase (*x, base); }
00970 
00971   inline friend xnat bit_size (const integer& x) {
00972     return mpz_sizeinbase (*x, 2); }
00973 
00974   inline friend xnat limb_size (const integer& x) {
00975     return mpz_size (*x); }
00976 
00977   inline friend nat N (const integer& x) {
00978     return limb_size (x); }
00979 
00980   inline friend integer lshiftz (const integer& x1, nat shift) {
00981     if (shift == 0) return x1;
00982     if ((GMP_LIMB_BITS * shift) / GMP_LIMB_BITS != shift) // overflow
00983       return lshiftz (lshiftz (x1, shift >> 1) , shift - (shift >> 1));
00984     integer r; mpz_mul_2exp (*r, *x1, GMP_LIMB_BITS * shift); return r; }
00985 
00986   inline friend integer rshiftz (const integer& x1, nat shift) {
00987     if (shift == 0) return x1;
00988     if ((GMP_LIMB_BITS * shift) / GMP_LIMB_BITS != shift) // overflow
00989       return rshiftz (rshiftz (x1, shift >> 1) , shift - (shift >> 1));
00990     integer r; mpz_fdiv_q_2exp (*r, *x1, GMP_LIMB_BITS * shift); return r; }
00991 
00992   inline friend integer co_rshiftz (const integer& x1, nat shift) {
00993     if (shift == 0) return 0;
00994     if ((GMP_LIMB_BITS * shift) / GMP_LIMB_BITS != shift) // overflow
00995       return lshiftz (co_rshiftz (rshiftz (x1, shift >> 1),
00996                                   shift - (shift >> 1)), shift >> 1)
00997         + co_rshiftz (x1, shift >> 1);
00998     integer r; mpz_fdiv_r_2exp (*r, *x1, GMP_LIMB_BITS * shift); return r; }
00999 
01000   friend class rational;
01001   friend integer numerator (const rational& x1);
01002   friend integer denominator (const rational& x1);
01003   template<typename V> friend class floating;
01004   template<typename V> friend integer as_integer (const floating<V>& x);
01005 };
01006 INDIRECT_IMPL (integer, integer_rep)
01007 
01008 template<> struct symbolic_type_information<integer> {
01009   static const nat id= SYMBOLIC_INTEGER; };
01010 
01011 inline integer raw_integer (nat limb_sz) {
01012   return new integer_rep (limb_sz * BITS_PER_LIMB); }
01013 generic construct (const integer& i);
01014 template<> inline integer duplicate (const integer& i) { return copy (i); }
01015 
01016 TRUE_TO_EXACT_IDENTITY_SUGAR(,integer)
01017 POOR_MAN_ELEMENTARY_SUGAR(,integer)
01018 
01019 /******************************************************************************
01020 * Conversion related
01021 ******************************************************************************/
01022 
01023 syntactic flatten (const integer& i);
01024 
01025 template<>
01026 struct binary_helper<integer>: public void_binary_helper<integer> {
01027   static inline string short_type_name () { return "Z"; }
01028   static inline generic full_type_name () { return "Integer"; }
01029   static inline generic disassemble (const integer& x) {
01030     return as<generic> (as_string (x)); }
01031   static inline integer assemble (const generic& x) {
01032     return integer (as<string> (x)); }
01033   static inline void write (const port& out, const integer& i) {
01034     mpz_binary_write (out, *i); }
01035   static inline integer read (const port& in) {
01036     integer i; mpz_binary_read (in, *i); return i; }
01037 };
01038 
01039 template<>
01040 struct as_helper<signed char,integer> {
01041   static inline signed char cv (const integer& i) {
01042     VERIFY (mpz_fits_sshort_p (*i), "integer too large");
01043     signed short r= mpz_get_si (*i);
01044     VERIFY ((unsigned short) abs (r)
01045             <= (unsigned short) ((unsigned char) (-1)), "integer too large");
01046     return (signed char) r; }
01047 };
01048 
01049 template<>
01050 struct as_helper<unsigned char,integer> {
01051   static inline unsigned char cv (const integer& i) {
01052     VERIFY (mpz_fits_ushort_p (*i), "integer too large");
01053     unsigned short r= mpz_get_ui (*i);
01054     VERIFY (r <= (unsigned short) ((unsigned char) (-1)), "integer too large");
01055     return (unsigned char) r; }
01056 };
01057 
01058 template<>
01059 struct as_helper<short int,integer> {
01060   static inline short int cv (const integer& i) {
01061     VERIFY (mpz_fits_sshort_p (*i), "integer too large");
01062     return (short int) mpz_get_si (*i); }
01063 };
01064 
01065 template<>
01066 struct as_helper<unsigned short int,integer> {
01067   static inline unsigned short int cv (const integer& i) {
01068     VERIFY (mpz_fits_ushort_p (*i), "integer too large");
01069     return (unsigned short) mpz_get_ui (*i); }
01070 };
01071 
01072 template<>
01073 struct as_helper<int,integer> {
01074   static inline int cv (const integer& i) {
01075     VERIFY (mpz_fits_sint_p (*i), "integer too large");
01076     return (int) mpz_get_si (*i); }
01077 };
01078 
01079 template<>
01080 struct as_helper<unsigned int,integer> {
01081   static inline unsigned int cv (const integer& i) {
01082     VERIFY (mpz_fits_uint_p (*i), "integer too large");
01083     return (unsigned int) mpz_get_ui (*i); }
01084 };
01085 
01086 template<>
01087 struct as_helper<long int,integer> {
01088   static inline long int cv (const integer& i) {
01089     VERIFY (mpz_fits_slong_p (*i), "integer too large");
01090     return mpz_get_si (*i); }
01091 };
01092 
01093 template<>
01094 struct as_helper<unsigned long int,integer> {
01095   static inline unsigned long int cv (const integer& i) {
01096     VERIFY (mpz_fits_ulong_p (*i), "integer too large");
01097     return mpz_get_ui (*i); }
01098 };
01099 
01100 #if defined(BASIX_HAVE_LONG_LONG_INT)
01101 template<>
01102 struct as_helper<unsigned long long int,integer> {
01103   static inline unsigned long long int cv (const integer& i) {
01104     const nat s= 8*sizeof(unsigned long int);
01105     return mpz_get_ui (*i)
01106       + MMX_SAFE_LEFT_SHIFT_INT (unsigned long int,
01107                                  as<unsigned long int> (i >> s), s); }
01108 };
01109 
01110 template<>
01111 struct as_helper<long long int,integer> {
01112   static inline long long int cv (const integer& i) {
01113     if (i > 0) return as<unsigned long long int> (i);
01114     return - as<unsigned long long int> (-i); }
01115 };
01116 #endif
01117 
01118 template<>
01119 struct is_signed_helper<integer> {
01120   static const bool value = true; };
01121 
01122 template<>
01123 struct as_helper<double,integer> {
01124   static inline double cv (const integer& i) { return as_double (i); }
01125 };
01126 
01127 template<typename F> inline integer
01128 promote (const F& x, const integer&) { return as<integer> (x); }
01129 
01130 /******************************************************************************
01131 * Other integer routines
01132 ******************************************************************************/
01133 
01134 inline integer factorial (nat i) {
01135   integer r; mpz_fac_ui (*r, i); return r; }
01136 
01137 inline integer binomial (nat i, nat j) {
01138   integer r; mpz_bin_uiui (*r, i, j); return r; }
01139 
01140 inline integer factorial (const integer& i) {
01141   ASSERT (i >= 0, "positive argument expected");
01142   return factorial ((nat) as_int (i)); }
01143 
01144 inline integer binomial (const integer& i, const integer& j) {
01145   ASSERT (i >= 0 && j >= 0, "positive argument expected");
01146   return binomial ((nat) as_int (i), (nat) as_int (j)); }
01147 
01148 inline bool is_probable_prime (const integer& i) {
01149   int n= 5, b;
01150   while ((b= mpz_probab_prime_p (*i, n)) == 1 && n < 10) n++;
01151   return b != 0;
01152 }
01153 
01154 inline integer probable_previous_prime (const integer& i) {
01155   integer j (i-1);
01156   while (! is_probable_prime (j)) j -= 1;
01157   return j;
01158 }
01159 
01160 inline integer probable_next_prime (const integer& i) {
01161   integer j (i+1);
01162   while (! is_probable_prime (j)) j += 1;
01163   return j;
01164 }
01165 
01166 template<typename C> C
01167 binpow (const C& i, const integer& n) {
01168   if (n <= 1) return n == 0 ? promote (1, i) : i;
01169   C j= binpow (i, n >> 1);
01170   if ((n & 1) == 0) return square (j);
01171   else return square (j) * i;
01172 }
01173 
01174 inline nat dyadic_valuation (const integer& i) {
01175   if (i == integer (0)) return (nat) -1;
01176   return mpz_scan1 (* i, 0);
01177 }
01178 
01179 #define HELPER(type) \
01180 inline nat dyadic_valuation (const type& i) { \
01181   if (i == 0) return (nat) -1; \
01182   for(nat v= 0; v < (8 * sizeof (i)); ++v) \
01183     if ((i >> v) & 1) return v; \
01184   return (nat) -1; \
01185 }
01186 
01187 HELPER(signed char)
01188 HELPER(unsigned char)
01189 HELPER(signed short)
01190 HELPER(unsigned short)
01191 HELPER(signed int)
01192 HELPER(unsigned int)
01193 HELPER(signed long)
01194 HELPER(unsigned long)
01195 HELPER(signed long long)
01196 HELPER(unsigned long long)
01197 #undef HELPER
01198 
01199 /******************************************************************************
01200 * Extras for glue
01201 ******************************************************************************/
01202 
01203 #define make_literal_integer make_literal<integer>
01204 #define integer_construct(i) as<generic> (integer (i))
01205   // FIXME: to be removed
01206 
01207 } // namespace mmx
01208 #endif // __MMX_INTEGER_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines