00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 #include <numerix/integer.hpp>
00014 namespace mmx {
00015 
00016 
00017 
00018 
00019 
00020 #if !defined(__GNU_MP__)
00021 
00022 void
00023 encode_kronecker (integer& dest, const integer* src, nat n, xnat bits) {
00024   if (n == 0) dest= 0;
00025   else if (n == 1) dest= src[0];
00026   else {
00027     nat h= n>>1;
00028     integer aux;
00029     encode_kronecker (aux , src+h, n-h, bits);
00030     encode_kronecker (dest, src  , h  , bits);
00031     dest += (aux << (h*bits));
00032   }
00033 }
00034 
00035 void
00036 decode_kronecker (integer* dest, nat n, xnat bits, const integer& src) {
00037   if (n == 0);
00038   else if (n == 1) dest[0]= src;
00039   else if (src > 0) {
00040     nat h= n>>1;
00041     integer aux= src >> (h*bits);
00042     if (src[h*bits-1]) aux += 1;
00043     decode_kronecker (dest+h, n-h, bits, aux);
00044     aux= src - (aux << (h*bits));
00045     decode_kronecker (dest, h, bits, aux);
00046   }
00047   else {
00048     integer bis= -src;
00049     nat h= n>>1;
00050     integer aux= bis >> (h*bits);
00051     if (bis[h*bits-1]) aux += 1;
00052     decode_kronecker (dest+h, n-h, bits, -aux);
00053     aux= bis - (aux << (h*bits));
00054     decode_kronecker (dest, h, bits, -aux);
00055   }
00056 }
00057 
00058 #else
00059 
00060 
00061 
00062 
00063 
00064 void mpz_encode_kronecker
00065        (mpz_t dest, const mpz_t* src, unsigned long n, unsigned long bits);
00066 void mpz_decode_kronecker
00067        (mpz_t* dest, unsigned long n, unsigned long bits, const mpz_t src_bis);
00068 
00069 static inline mpz_t*
00070 mmx_new_mpz (nat n) {
00071   return (mpz_t*) mmx_malloc (n * sizeof (mpz_t));
00072 }
00073 
00074 static inline void
00075 mmx_delete_mpz (mpz_t* Ptr, nat n) {
00076   mmx_free ((void*) Ptr, n * sizeof (mpz_t));
00077 }
00078 
00079 void
00080 encode_kronecker (integer& dest, const integer* src, nat n, xnat bits) {
00081   nat i;
00082   mpz_t* Src= mmx_new_mpz (n);
00083   for (i=0; i<n; i++) {
00084     const mpz_t& aux= *(src[i]);
00085     Src[i]->_mp_alloc= aux->_mp_alloc;
00086     Src[i]->_mp_size = aux->_mp_size;
00087     Src[i]->_mp_d    = aux->_mp_d;
00088   }
00089   mpz_encode_kronecker (*dest, Src, n, bits);
00090   mmx_delete_mpz (Src, n);
00091 }
00092 
00093 void
00094 decode_kronecker (integer* dest, nat n, xnat bits, const integer& src) {
00095   nat i;
00096   mpz_t* Dest= mmx_new_mpz (n);
00097   for (i=0; i<n; i++) mpz_init (Dest[i]);
00098   mpz_decode_kronecker (Dest, n, bits, *src);
00099   for (i=0; i<n; i++) {
00100     mpz_t& aux= *(dest[i]);
00101     aux->_mp_alloc= Dest[i]->_mp_alloc;
00102     aux->_mp_size = Dest[i]->_mp_size;
00103     aux->_mp_d    = Dest[i]->_mp_d;
00104   }
00105   mmx_delete_mpz (Dest, n);
00106 }
00107 #endif // __GNU_MP__
00108 
00109 
00110 
00111 
00112 
00113 xnat max_bit_size (const integer* src, nat n) {
00114   xnat m= 0;
00115   for (nat i=0; i<n; i++)
00116     m= max (m, bit_size (src[i]));
00117   return m;
00118 }
00119 
00120 void
00121 mul_kronecker (integer* dest,
00122                const integer* src1, nat n1,
00123                const integer* src2, nat n2)
00124 {
00125   
00126 
00127 
00128 
00129 
00130 
00131 
00132   if (n1 == 0 && n2 == 0) return;
00133   for (nat i= 0; i < n1 + n2 - 1; i++) dest[i]= 0;
00134   while (n1 > 0 && src1[n1-1] == 0) n1--;
00135   while (n2 > 0 && src2[n2-1] == 0) n2--;
00136   if (n1 == 0 || n2 == 0) return;
00137   
00138   xnat bits1= max_bit_size (src1, n1);
00139   xnat bits2= max_bit_size (src2, n2);
00140   xnat bits= bits1 + bits2 + bit_size (integer (min (n1, n2))) + 1;
00141   integer aux1, aux2;
00142   
00143   
00144   encode_kronecker (aux1, src1, n1, bits);
00145   encode_kronecker (aux2, src2, n2, bits);
00146   
00147   
00148   
00149   integer aux= aux1*aux2;
00150   
00151   
00152   
00153   decode_kronecker (dest, n1+n2-1, bits, aux);
00154   
00155 
00156   
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 }
00167 
00168 void
00169 square_kronecker (integer* dest, const integer* src, nat n) {
00170   if (n == 0) return;
00171   for (nat i= 0; i < 2 * n - 1; i++) dest[i]= 0;
00172   while (n > 0 && src[n-1] == 0) n--;
00173   if (n == 0) return;
00174   if (n == 1) { dest[0]= square (src[0]); return; }
00175 
00176   xnat bits1= max_bit_size (src, n);
00177   xnat bits = (bits1 << 1) + bit_size (integer (n)) + 1;
00178 
00179   integer aux1;
00180   encode_kronecker (aux1, src, n, bits);
00181   integer aux= square (aux1);
00182   decode_kronecker (dest, n+n-1, bits, aux);
00183 }
00184 
00185 }