algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : kronecker_integer.cpp 00004 * DESCRIPTION: Breaking big integers into parts and recomposing them 00005 * COPYRIGHT : (C) 2007 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 #include <numerix/integer.hpp> 00014 namespace mmx { 00015 00016 /****************************************************************************** 00017 * Naive encoding and decoding of integer polynomials using Kronecker's method 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 * Specific implementation for GMP 00061 ******************************************************************************/ 00062 00063 // from polynomial_gmp.cpp 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 * Multiply two integer polynomials stored in segments using Kronecker's method 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 mmout << "n1= " << n1 << ", " << "n2= " << n2 << "\n"; 00127 for (nat i=0; i<n1; i++) 00128 mmout << " s" << i << "\t" << src1[i] << "\n"; 00129 for (nat i=0; i<n2; i++) 00130 mmout << " t" << i << "\t" << src2[i] << "\n"; 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 //mmout << "Encoding\n"; 00143 //nat start= mmx_time (); 00144 encode_kronecker (aux1, src1, n1, bits); 00145 encode_kronecker (aux2, src2, n2, bits); 00146 //mmout << "Done in " << mmx_time () - start << "ms\n"; 00147 //mmout << "Multiplying\n"; 00148 //start= mmx_time (); 00149 integer aux= aux1*aux2; 00150 //mmout << "Done in " << mmx_time () - start << "ms\n"; 00151 //mmout << "Decoding\n"; 00152 //start= mmx_time (); 00153 decode_kronecker (dest, n1+n2-1, bits, aux); 00154 //mmout << "Done in " << mmx_time () - start << "ms\n"; 00155 00156 /* 00157 integer* dest1= mmx_new<integer> (n1+n2-1); 00158 decode_kronecker_naive (dest1, n1+n2-1, bits, aux); 00159 decode_kronecker (dest, n1+n2-1, bits, aux); 00160 for (nat i=0; i<n1+n2-1; i++) { 00161 mmout << "naive\t" << i << "\t" << dest1[i] << "\n"; 00162 mmout << "fast\t" << i << "\t" << dest[i] << "\n"; 00163 } 00164 mmx_delete<integer> (dest1, n1+n2-1); 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 } // namespace mmx