algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/src/kronecker_gmp.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : kronecker_gmp.cpp
00004 * DESCRIPTION: Breaking big integers into parts and recomposing them
00005 * COPYRIGHT  : (C) 2007  Joris van der Hoeven and 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 #include <numerix/integer.hpp>
00014 namespace mmx {
00015 #if defined(__GNU_MP__)
00016 
00017 #define ASSERT_RANGE(cond) assert(cond)
00018 //#define ASSERT_RANGE(cond) VERIFY(cond,"limb out of range")
00019 
00020 static inline void
00021 mpn_set (mp_limb_t* dest, const mp_limb_t* src, mp_size_t size) {
00022   mp_size_t i;
00023   for (i=0; i<size; i++) dest[i]= src[i];
00024 }
00025 
00026 template<typename I> static inline void
00027 mpn_get2 (I& dest, const mp_limb_t* src, unsigned long n,
00028           unsigned long beg, unsigned long end) {
00029   // write bits of src from index beg to end-1 into dest
00030   typedef typename unsigned_of_helper<I>::type U;
00031   dest= 0; 
00032   if (end <= beg) return;
00033   const xnat shift_l= bit_size (BITS_PER_LIMB) - 1;
00034   const mp_limb_t ceil_l= (- (mp_limb_t) 1) << shift_l;
00035   const mp_limb_t mod_l= (- (mp_limb_t) 1) - ceil_l;
00036   end= min (beg + 8 * sizeof (I), min (end, BITS_PER_LIMB * n));
00037   unsigned long pos= beg;
00038   while (pos < end) {
00039     unsigned long i= pos >> shift_l, o= pos & mod_l;
00040     dest |= ((I) (src[i] >> o)) << (pos - beg);
00041     pos += BITS_PER_LIMB - o;
00042   }
00043   dest &= (((U) -1) >> (8 * sizeof (I) - (end - beg)));
00044 }
00045 
00046 static inline void
00047 mpn_get2 (mp_limb_t* dest, const mp_limb_t* src, unsigned long n,
00048           unsigned long beg, unsigned long end) {
00049   // write the bits from beg to end-1 of src into dest
00050   unsigned long i= 0;
00051   while (beg < end) {
00052     mpn_get2 (dest[i], src, n, beg, min (end, beg + BITS_PER_LIMB));
00053     i++; beg += BITS_PER_LIMB;
00054   }
00055 }
00056 
00057 /******************************************************************************
00058 * Encoding a polynomial of integers using Kronecker's method
00059 ******************************************************************************/
00060 
00061 static inline void
00062 mpn_lshift_bis (mp_limb_t* dest, mp_size_t dest_size,
00063                 const mp_limb_t* src , mp_size_t src_size,
00064                 unsigned int count)
00065 {
00066   assert (dest_size >= src_size && dest_size > 0);
00067   if (dest_size == src_size) {
00068     if (count == 0) mpn_set (dest, src, src_size);
00069     else (void) mpn_lshift (dest, src, src_size, count);
00070   }
00071   else {
00072     mp_size_t i;
00073     if (src_size == 0) dest[src_size]= 0;
00074     else {
00075       if (count == 0) {
00076         mpn_set (dest, src, src_size);
00077         dest[src_size]= 0;
00078       }
00079       else dest[src_size]= mpn_lshift (dest, src, src_size, count);
00080     }
00081     for (i=src_size+1; i<dest_size; i++) dest[i]= 0;
00082   }
00083 }
00084 
00085 void
00086 mpz_encode_kronecker (mpz_t dest,
00087                       const mpz_t* src, unsigned long n, unsigned long bits)
00088 {
00089   // src is an array of length n of integers which fit into bits-1 bits.
00090   // We set dest := src[0]+ src[1] 2^{bits} + ... + src[n-1] 2^{(n-1) bits}.
00091 
00092   unsigned long i;
00093   mp_size_t dest_size;
00094   mp_size_t cleaned;
00095   mpz_t aux;
00096   int dest_sgn;
00097 
00098   while (n>0 && mpz_sgn (src[n-1]) == 0) n--;
00099   mpz_set_si (dest, 0);
00100   if (n == 0) return;
00101   dest_sgn= mpz_sgn (src[n-1]);
00102 
00103   mpz_realloc2 (dest, n * bits);
00104   dest_size  = dest->_mp_alloc;
00105   cleaned= dest_size;
00106   //mmout << "dest_size= " << dest_size << "\n";
00107 
00108   mpz_init2 (aux, bits + BITS_PER_LIMB);
00109   for (i=n-1; i != ((unsigned long) -1); i--) {
00110     mp_size_t    j;
00111     mp_size_t    bit     = i * bits;
00112     unsigned int shift   = bit & (BITS_PER_LIMB-1);
00113     mp_size_t    offset  = bit / BITS_PER_LIMB;
00114     mp_size_t    extra   = cleaned - offset;
00115     mp_size_t    aux_size= aux->_mp_alloc;
00116     mp_size_t    src_ssz = src[i]->_mp_size;
00117     mp_size_t    src_size= (src_ssz>0? src_ssz: -src_ssz);
00118     int          src_sgn = (src_ssz>=0? 1: -1);
00119     if (aux_size + offset > dest_size) aux_size--;
00120     /*
00121     mmout << "Step " << i << "\n";
00122     mmout << "  bit     = " << bit << "\n";
00123     mmout << "  shift   = " << shift << "\n";
00124     mmout << "  offset  = " << offset << "\n";
00125     mmout << "  extra   = " << extra << "\n";
00126     mmout << "  aux_size= " << aux_size << "\n";
00127     mmout << "  src_size= " << src_size << "\n";
00128     mmout << "  dest_sgn= " << dest_sgn << "\n";
00129     mmout << "  src_sgn = " << src_sgn << "\n";
00130     */
00131 
00132     // ASSERT_RANGE (aux->_mp_alloc >= aux_size); // Useless, GL.
00133     mpn_lshift_bis (aux->_mp_d, aux_size, src[i]->_mp_d, src_size, shift);
00134     if (src_sgn == dest_sgn) {
00135       for (j=0; j<extra; j++)
00136         dest->_mp_d[j+offset]= aux->_mp_d[j];
00137       if (aux_size > extra) {
00138         ASSERT_RANGE (dest->_mp_alloc >= cleaned + aux_size - extra);
00139         mpn_add_n (dest->_mp_d + cleaned, dest->_mp_d + cleaned,
00140                    aux->_mp_d + extra, aux_size - extra);
00141       }
00142     }
00143     else {
00144       ASSERT_RANGE (dest->_mp_alloc >= offset + extra);
00145       for (j=0; j<extra; j++)
00146         dest->_mp_d[j+offset]= 0;
00147       ASSERT_RANGE (dest->_mp_alloc >= dest_size);
00148       mpn_sub (dest->_mp_d + offset,
00149                dest->_mp_d + offset, dest_size - offset,
00150                aux->_mp_d, aux_size);
00151     }
00152     cleaned= offset;
00153   }
00154   mpz_clear (aux);
00155 
00156   while (dest->_mp_d[dest_size-1] == 0) dest_size--;
00157   dest->_mp_size= (dest_sgn>0? dest_size: -dest_size);
00158 }
00159 
00160 template<typename I> static inline void
00161 mpz_encode_kronecker_uint (mpz_t dest,
00162                            const I* src, unsigned long n, unsigned long bits)
00163 {
00164   // src is an array of length n of unsigned hardware integers which fit
00165   // into e bits. We set dest := src[0]+ src[1] 2^{bits} + ... +
00166   // src[n-1] 2^{(n-1) bits}.
00167   while (n > 0 && src[n-1] == 0) n--;
00168   mpz_set_si (dest, 0);
00169   if (n == 0) return;
00170   static const xnat k= 8 * sizeof (I);
00171   const xnat shift_k= bit_size (k) - 1;
00172   const unsigned long ceil_k= (- (unsigned long) 1) << shift_k;
00173   const unsigned long mod_k= (- (unsigned long) 1) - ceil_k;
00174   mpz_realloc2 (dest, (n * bits + k - 1) & ceil_k);
00175   for (unsigned long i= 0; i < (unsigned long) dest->_mp_alloc; i++)
00176     dest->_mp_d[i]= 0;
00177   unsigned long pos= 0, j, o;
00178   I* aux= (I*) (void*) dest->_mp_d;
00179   for (unsigned long i= 0; i < n; i++, pos += bits) {
00180     j= pos >> shift_k, o= pos & mod_k; 
00181                 aux[j    ] |= src[i] << o;
00182     if (o != 0) aux[j + 1] |= src[i] >> (k - o);
00183   }
00184   dest->_mp_size= dest->_mp_alloc;
00185   while (dest->_mp_size > 0 && dest->_mp_d[dest->_mp_size - 1] == 0)
00186     dest->_mp_size--;
00187 }
00188 
00189 #define IMPLEMENTATION_HELPER(I)                                        \
00190   void mpz_encode_kronecker (mpz_t dest,                                \
00191                              const I* src, unsigned long n,             \
00192                              unsigned long bits) {                      \
00193     mpz_encode_kronecker_uint (dest, src, n, bits); }
00194 
00195 IMPLEMENTATION_HELPER(unsigned char)
00196 IMPLEMENTATION_HELPER(unsigned short)
00197 IMPLEMENTATION_HELPER(unsigned int)
00198 IMPLEMENTATION_HELPER(unsigned long int)
00199 IMPLEMENTATION_HELPER(unsigned long long int)
00200 #undef IMPLEMENTATION_HELPER
00201 
00202 /******************************************************************************
00203 * Decoding a polynomial of integers using Kronecker's method
00204 ******************************************************************************/
00205 
00206 static inline void
00207 mpn_rshift_bis (mp_limb_t* dest, mp_size_t dest_size,
00208                 const mp_limb_t* src , mp_size_t src_size,
00209                 unsigned int count)
00210 {
00211   assert (dest_size > 0);
00212   if (src_size >= dest_size) {
00213     if (count == 0) mpn_set (dest, src, dest_size);
00214     else (void) mpn_rshift (dest, src, dest_size, count);
00215   }
00216   else {
00217     mp_size_t i;
00218     if (src_size != 0) {
00219       if (count == 0) mpn_set (dest, src, src_size);
00220       else mpn_rshift (dest, src, src_size, count);
00221     }
00222     for (i=src_size; i<dest_size; i++) dest[i]= 0;
00223   }
00224 }
00225 
00226 void
00227 mpz_decode_kronecker (mpz_t* dest, unsigned long n, unsigned long bits,
00228                       const mpz_t src_bis)
00229 {
00230   // let src be an integer of the form a_0 + ... + a_{n-1} 2^{(n-1) bits},
00231   // where the a_i are positive or negative integers of at most bits-1 bits.
00232   // On exit, we have dest[i] := a_i for each i.
00233 
00234   unsigned long i, src_bit_size;
00235   mp_size_t src_size, aux_size;
00236   int src_sgn;
00237   mpz_t src, aux, tmp;
00238   mp_limb_t mask= (((mp_limb_t) 1) << (bits & (BITS_PER_LIMB-1))) - 1;
00239   if (mask == 0) mask= (mp_limb_t) -1;
00240   mpz_init2 (src, (mpz_size (src_bis) + 1) * BITS_PER_LIMB);
00241   mpz_set (src, src_bis);
00242   ASSERT_RANGE (((long int) src->_mp_alloc) > ((long int) mpz_size (src)));
00243   src->_mp_d[mpz_size (src)]= 0;
00244 
00245   /* handle trailing zeros */
00246   if (n == 0) return;
00247   src_bit_size= mpz_sizeinbase (src, 2);
00248   if (src_bit_size < (n-1) * bits) {
00249     unsigned long new_n= (src_bit_size / bits) + 1;
00250     for (i= new_n; i<n; i++) mpz_set_si (dest[i], 0);
00251     n= new_n;
00252   }
00253   ASSERT_RANGE (src_bit_size < n*bits);
00254   ASSERT_RANGE (src_bit_size >= (n-1) * bits);
00255 
00256   src_size= mpz_size (src) + 1;
00257   src_sgn= mpz_sgn (src);
00258   mpz_init2 (aux, bits + BITS_PER_LIMB);
00259   aux_size= aux->_mp_alloc;
00260   mpz_init2 (tmp, bits + BITS_PER_LIMB);
00261   mpz_set_si (tmp, 1);
00262   mpz_mul_2exp (tmp, tmp, bits);
00263 
00264   /*
00265   mmout << "mask\t= " << mask << "\n";
00266   mmout << "n\t= " << n << "\n";
00267   mmout << "src_sz\t= " << src_size << "\n";
00268   mmout << "src_sgn\t= " << src_sgn << "\n";
00269   mmout << "aux_sz\t= " << aux_size << "\n";
00270   */
00271 
00272   for (i=0; i<n; i++) {
00273     int          dest_sgn = 1;
00274     mp_size_t    bit      = i * bits;
00275     unsigned int shift    = bit & (BITS_PER_LIMB-1);
00276     mp_size_t    offset   = bit / BITS_PER_LIMB;
00277 
00278     /*
00279     mmout << "Stage " << i << "\n";
00280     mmout << "  bit\t= " << bit << "\n";
00281     mmout << "  total\t= " << src_bit_size << "\n";
00282     mmout << "  shift\t= " << shift << "\n";
00283     mmout << "  off\t= " << offset << "\n";
00284     */
00285 
00286     /* put the raw next coefficient in aux */
00287     ASSERT_RANGE (aux->_mp_alloc >= aux_size);
00288     mpn_rshift_bis (aux->_mp_d, aux_size,
00289                     src->_mp_d+offset, src_size-offset, shift);
00290     ASSERT_RANGE (aux->_mp_alloc >= aux_size);
00291     aux->_mp_d[aux_size-2] &= mask;
00292     aux->_mp_size= aux_size - 1;
00293     while (aux->_mp_size > 0 && aux->_mp_d[aux->_mp_size-1] == 0)
00294       aux->_mp_size--;
00295 
00296     /* check whether the next coefficient has a negative sign */
00297     if (i != n-1) {
00298       unsigned int k= (bits-1) & (BITS_PER_LIMB-1);
00299       mp_size_t    l= (bits-1) / BITS_PER_LIMB;
00300       dest_sgn= ((aux->_mp_d[l] & ((mp_limb_t) 1<<k)) == 0? 1: -1);
00301       if (dest_sgn < 0) {
00302         /* in-place update of src in case of a negative sign */
00303         mp_size_t    next_bit   = (i+1) * bits;
00304         unsigned int next_shift = next_bit & (BITS_PER_LIMB-1);
00305         mp_size_t    next_offset= next_bit / BITS_PER_LIMB;
00306         mp_limb_t    plus       = ((mp_limb_t) 1) << next_shift;
00307         ASSERT_RANGE (src->_mp_alloc >= src_size);
00308         if (mpn_add (src->_mp_d + next_offset,
00309                      src->_mp_d + next_offset, src_size - next_offset,
00310                      &plus, 1) != 0)
00311           ASSERT (false, "unexpected carry (mpz_decode_kronecker)");
00312       }
00313       //mmout << "  sgn\t= " << dest_sgn << "\n";
00314     }
00315 
00316     /* put the sign-corrected next coefficient in dest[i] */
00317     if (dest_sgn >= 0) mpz_set (dest[i], aux);
00318     else mpz_sub (dest[i], tmp, aux);
00319     if (dest_sgn != src_sgn) dest[i]->_mp_size= -dest[i]->_mp_size;
00320   }
00321 
00322   mpz_clear (src);
00323   mpz_clear (aux);
00324   mpz_clear (tmp);
00325 }
00326 
00327 template<typename I> static inline void
00328 mpz_decode_kronecker_uint (I* dest, unsigned long n, unsigned long bits,
00329                            const mpz_t src,
00330                            unsigned int e= 8 * sizeof (I)) {
00331   ASSERT (2*e <= bits, "overflow");
00332   const xnat k= 8 * sizeof (I);
00333   const xnat shift_k= bit_size (k) - 1;
00334   const unsigned long ceil_k= (- (unsigned long) 1) << shift_k;
00335   const unsigned long mod_k= (- (unsigned long) 1) - ceil_k;
00336   unsigned long i= 0, j, o, sz= BITS_PER_LIMB * src->_mp_size, pos= 0;
00337   const I* aux= (I*) (void*) src->_mp_d;
00338   for (; pos + (k << 1) < sz && i < n; i++, pos += bits) {
00339     j= pos >> shift_k, o= pos & mod_k;
00340     if (o == 0) 
00341       dest[i]= aux[j] >> o;
00342     else
00343       dest[i]= (aux[j] >> o) | (aux[j+1] << (k - o));
00344   }
00345   for (; pos < sz && i < n; i++, pos += bits)
00346     mpn_get2 (dest[i], src->_mp_d, src->_mp_size, pos, pos+bits);
00347   for (; i < n; i++) dest[i]= 0;
00348 }
00349 #define IMPLEMENTATION_HELPER(I)                                        \
00350   void mpz_decode_kronecker (I* dest, unsigned long n,                  \
00351                              unsigned long bits, const mpz_t src) {     \
00352     mpz_decode_kronecker_uint (dest, n, bits, src); }
00353 
00354 IMPLEMENTATION_HELPER(unsigned char)
00355 IMPLEMENTATION_HELPER(unsigned short)
00356 IMPLEMENTATION_HELPER(unsigned int)
00357 IMPLEMENTATION_HELPER(unsigned long int)
00358 IMPLEMENTATION_HELPER(unsigned long long int)
00359 #undef IMPLEMENTATION_HELPER
00360 
00361 /******************************************************************************
00362 * Decoding a polynomial of integers using Kronecker's method
00363 ******************************************************************************/
00364 
00365 template<typename L,typename I> static inline void
00366 _mpz_decode_kronecker_mod_uint (I* dest,
00367                                 unsigned long n, unsigned long bits,
00368                                 const mpz_t src, const I& p) {
00369   // Kronecker decoding modulo p in case when L is a hardware integer
00370   // type with at least 'bits' bits.
00371   const xnat k= 8 * sizeof (L);
00372   ASSERT (k >= bits, "overflow");
00373   const xnat shift_k= bit_size (k) - 1;
00374   const L mask= ((L) -1) >> (k - bits);
00375   const unsigned long ceil_k= (- (unsigned long) 1) << shift_k;
00376   const unsigned long mod_k= (- (unsigned long) 1) - ceil_k;
00377   unsigned long i= 0, j, o, sz= BITS_PER_LIMB * src->_mp_size, pos= 0;
00378   const L* aux= (L*) (void*) src->_mp_d;
00379   for (; pos + (k << 1) < sz && i < n; i++, pos += bits) {
00380     j= pos >> shift_k, o= pos & mod_k;
00381     if (o == 0) 
00382       dest[i]= ((aux[j] >> o) & mask) % p;
00383     else
00384       dest[i]= (((aux[j] >> o) | (aux[j+1] << (k - o))) & mask) % p;
00385   }
00386   for (; pos < sz && i < n; i++, pos += bits) {
00387     L tmp; mpn_get2 (tmp, src->_mp_d, src->_mp_size, pos, pos+bits);
00388     dest[i]= tmp % p;
00389   }
00390   for (; i < n; i++) dest[i]= 0;
00391 }
00392 
00393 template<typename I> static inline void
00394 _mpz_decode_kronecker_mod_integer (I* dest, unsigned long n,
00395                                    unsigned long bits, const mpz_t src,
00396                                    const I& p)
00397 {
00398   // let src be an integer of the form a_0 + ... + a_{n-1} 2^{(n-1) bits},
00399   // where the a_i are positive or negative integers of at most bits-1 bits.
00400   // On exit, we have dest[i] := a_i mod p for each i.
00401   ASSERT (bit_size (p) <= BITS_PER_LIMB, "overflow");
00402   const mp_size_t e= (bits + BITS_PER_LIMB - 1) / BITS_PER_LIMB;
00403   unsigned long sz= src->_mp_size * BITS_PER_LIMB, i= 0;
00404   mp_limb_t* aux= mmx_new<mp_limb_t> (2*e);
00405   mp_limb_t* q= aux + e;
00406   for (unsigned long pos= 0; pos < sz && i < n; i++, pos += bits) {
00407     mpn_get2 (aux, src->_mp_d, src->_mp_size, pos, pos + bits);
00408     dest[i]= mpn_divrem_1 (q, 0, aux, e, (mp_limb_t) p);
00409   }
00410   for (; i < n; i++) dest[i]= 0;
00411   mmx_delete<mp_limb_t> (aux, 2*e);
00412 }
00413 
00414 template<typename I> static inline void
00415 _mpz_decode_kronecker_mod_integer (I* dest, unsigned long n,
00416                                    unsigned long bits, const mpz_t src,
00417                                    const mpz_t p)
00418 {
00419   // let src be an integer of the form a_0 + ... + a_{n-1} 2^{(n-1) bits},
00420   // where the a_i are positive or negative integers of at most bits-1 bits.
00421   // On exit, we have dest[i] := a_i mod p for each i.
00422   const mp_size_t e= (bits + BITS_PER_LIMB - 1) / BITS_PER_LIMB;
00423   unsigned long sz= src->_mp_size * BITS_PER_LIMB, i= 0;
00424   mp_limb_t* aux= mmx_new<mp_limb_t> (2*e + p->_mp_size);
00425   mp_limb_t* q= aux + e, * r= q + e;
00426   for (unsigned long pos= 0; pos < sz && i < n; i++, pos += bits) {
00427     mpn_get2 (aux, src->_mp_d, src->_mp_size, pos, pos + bits);
00428     mpn_tdiv_qr (q, r, 0, aux, e, p->_mp_d, p->_mp_size);
00429     dest[i]= r[0];
00430     for (xnat j= 1; j < (xnat) p->_mp_size; j++)
00431       dest[i] |= ((I) r[j]) << (j * BITS_PER_LIMB);
00432   }
00433   for (; i < n; i++) dest[i]= 0;
00434   mmx_delete<mp_limb_t> (aux, 2*e + p->_mp_size);
00435 }
00436 
00437 template<typename I> static inline void
00438 mpz_decode_kronecker_mod_int (I* dest, unsigned long n, unsigned long bits,
00439                               const mpz_t src, const I& p) {
00440   if (p == 0) {
00441     typedef typename unsigned_of_helper<I>::type U;
00442     mpz_decode_kronecker ((U*) (void*) dest, n, bits, src);
00443     return;
00444   }
00445   if (bits <= 8 * sizeof (unsigned char)) {
00446     typedef unsigned char L;
00447     _mpz_decode_kronecker_mod_uint<L> (dest, n, bits, src, p);
00448   }
00449   else if (bits <= 8 * sizeof (unsigned short int)) {
00450     typedef unsigned short int L;
00451     _mpz_decode_kronecker_mod_uint<L> (dest, n, bits, src, p);
00452   }
00453   else if (bits <= 8 * sizeof (unsigned int)) {
00454     typedef unsigned int L;
00455     _mpz_decode_kronecker_mod_uint<L> (dest, n, bits, src, p);
00456   }
00457   else if (bits <= 8 * sizeof (unsigned long int)) {
00458     typedef unsigned long int L;
00459     _mpz_decode_kronecker_mod_uint<L> (dest, n, bits, src, p);
00460   }
00461   else if (bits <= 8 * sizeof (unsigned long long int)) {
00462     typedef unsigned long long int L;
00463     _mpz_decode_kronecker_mod_uint<L> (dest, n, bits, src, p);
00464   }
00465   else
00466     if (bit_size (p) <= BITS_PER_LIMB)
00467       _mpz_decode_kronecker_mod_integer (dest, n, bits, src, p);
00468     else {
00469       integer _p (p);
00470       _mpz_decode_kronecker_mod_integer (dest, n, bits, src, * _p); } }
00471 
00472 #define DECLARE_HELPER(I)                                               \
00473   void mpz_decode_kronecker_mod (I* dest, unsigned long n,              \
00474                                  unsigned long bits, const mpz_t src,   \
00475                                  const I& p) {                          \
00476     mpz_decode_kronecker_mod_int (dest, n, bits, src, p); }
00477 DECLARE_HELPER(signed char)
00478 DECLARE_HELPER(unsigned char)
00479 DECLARE_HELPER(short int)
00480 DECLARE_HELPER(unsigned short)
00481 DECLARE_HELPER(int)
00482 DECLARE_HELPER(unsigned int)
00483 DECLARE_HELPER(long int)
00484 DECLARE_HELPER(unsigned long int)
00485 DECLARE_HELPER(long long int)
00486 DECLARE_HELPER(unsigned long long int)
00487 #undef DECLARE_HELPER
00488 
00489 #endif // __GNU_MP__
00490 } // namespace mmx
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines