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 }