algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/src/kronecker_integer.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines