algebramix_doc 0.3
|
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