algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/kronecker_polynomial.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : kronecker_polynomial.hpp
00004 * DESCRIPTION: Multiplication of integer polynomials
00005 * COPYRIGHT  : (C) 2009  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 #ifndef __MMX_KRONECKER_POLYNOMIAL_HPP
00014 #define __MMX_KRONECKER_POLYNOMIAL_HPP
00015 #include <algebramix/polynomial.hpp>
00016 
00017 namespace mmx {
00018 #define TMPL template<typename C, typename V>
00019 #define Polynomial polynomial<C,V>
00020 
00021 /******************************************************************************
00022 * Low level Kronecker multiplication for bivariate polynomials
00023 ******************************************************************************/
00024 
00025 TMPL nat
00026 max_polynomial_size (const Polynomial* src, nat n) {
00027   nat m= 0;
00028   for (nat i= 0; i < n; i++) m= max (N(src[i]), m);
00029   return m;
00030 }
00031 
00032 TMPL void
00033 encode_kronecker (Polynomial& dest, const Polynomial* src, nat n, nat m) {
00034   if (n == 0) return;
00035   nat p= n * m;
00036   nat l= aligned_size<C,V> (p);
00037   C* x= mmx_new<C> (l); C* y= x;
00038   for (nat i= 0; i < n; i++, x += m, src++)
00039     for (nat j= 0; j < m; j++)
00040       x[j]= (*src)[j];
00041   dest= Polynomial (y, p, l, CF(src[0]));
00042 }
00043 
00044 TMPL void
00045 decode_kronecker (Polynomial* dest, const Polynomial& src, nat n, nat m) {
00046   typedef implementation<polynomial_linear,V> Pol;
00047   if (n == 0) return;
00048   nat l= aligned_size<C,V> (m), i, j; C* x;
00049   const C* y= seg (src);
00050   for (i= 0, j= 0; i + 1 < n && j + m < N(src); i++, j += m, y += m) {
00051     x= mmx_new<C> (l);
00052     Pol::copy (x, y, m);
00053     dest[i]= Polynomial (x, m, l, CF(src));
00054   }
00055   if (i < n && N(src) > i * m) {
00056     m= N(src) - i * m;
00057     l= aligned_size<C,V> (m);
00058     x= mmx_new<C> (l);
00059     Pol::copy (x, y, m);
00060     dest[i]= Polynomial (x, m, l, CF(src));
00061     i++;
00062   }
00063   for (; i < n; i++) dest[i]= Polynomial (C(0));
00064 }
00065 
00066 TMPL inline void
00067 mul_kronecker (Polynomial* dest,
00068                const Polynomial* s1, nat n1,
00069                const Polynomial* s2, nat n2) {
00070   typedef implementation<polynomial_linear,V> Pol;
00071   if (n1 == 0 || n2 == 0) return;
00072   if (n1 == 1) { Pol::mul_sc (dest, s2, s1[0], n2); return; }
00073   if (n2 == 1) { Pol::mul_sc (dest, s1, s2[0], n1); return; }
00074   nat m1= max_polynomial_size (s1, n1);
00075   nat m2= max_polynomial_size (s2, n2);
00076   nat m = m1 + m2 - 1;
00077   Polynomial x1, x2, y;
00078   encode_kronecker (x1, s1, n1, m);
00079   encode_kronecker (x2, s2, n2, m);
00080   y= x1 * x2;
00081   decode_kronecker (dest, y, n1 + n2 - 1, m); }
00082 
00083 TMPL inline void
00084 square_kronecker (Polynomial* dest, const Polynomial* s, nat n) {
00085   typedef implementation<polynomial_linear,V> Pol;
00086   if (n == 0) return;
00087   if (n == 1) { dest[0]= square_op::op (s[0]); return; }
00088   nat m = (max_polynomial_size (s, n) << 1) - 1;
00089   Polynomial x;
00090   encode_kronecker (x, s, n, m);
00091   x= square_op::op (x);
00092   decode_kronecker (dest, x, (n << 1) - 1, m); }
00093 
00094 TMPL inline void
00095 div_kronecker (Polynomial* dest,
00096                const Polynomial* s1, nat n1,
00097                const Polynomial* s2, nat n2) {
00098   typedef implementation<polynomial_linear,V> Pol;
00099   ASSERT (n2 != 0, "division by zero");
00100   if (n1 == 0) return;
00101   nat m1= max_polynomial_size (s1, n1);
00102   nat m2= max_polynomial_size (s2, n2);
00103   nat n= n1 - n2 + 1;
00104   Polynomial x1, x2, y;
00105   encode_kronecker (x1, s1, n1, m1);
00106   encode_kronecker (x2, s2, n2, m1);
00107   y= x1 / x2;
00108   nat l= default_aligned_size<C> (n1);
00109   Polynomial* tmp= mmx_new<Polynomial> (l);
00110   decode_kronecker (tmp, y, n1, m1);
00111   while (n1 > 0 && is_exact_zero (tmp[n1-1])) n1--;
00112   nat m= max_polynomial_size (tmp, n1);
00113   if (n1 <= n && m1 != m + m2 - 1) {
00114     mmx_delete<Polynomial> (tmp, l);
00115     ERROR ("unexact division");
00116   }
00117   Pol::copy (dest, tmp, n);
00118   mmx_delete<Polynomial> (tmp, l); }
00119 
00120 #undef Polynomial
00121 #undef TMPL
00122 } // namespace mmx
00123 #endif // __MMX_KRONECKER_POLYNOMIAL_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines