00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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 }
00123 #endif // __MMX_KRONECKER_POLYNOMIAL_HPP