00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX__FKT_TRANSFORM__HPP
00014 #define __MMX__FKT_TRANSFORM__HPP
00015 #include <algebramix/polynomial_naive.hpp>
00016
00017 namespace mmx {
00018 #define TMPL template<class C>
00019
00020 template<typename V>
00021 struct fkt_package {
00022 typedef implementation<polynomial_multiply,V> Pol;
00023 typedef typename Pol::Vec Vec;
00024
00025 TMPL static void
00026 direct_fkt_step (C* dest, nat n) {
00027
00028 nat h= n >> 1;
00029 Vec::half_copy (dest + n, dest + 1, h);
00030 Vec::half_copy (dest + 1, dest + 2, h - 1);
00031 Pol::add (dest + h, dest, dest + n, h);
00032 }
00033
00034 TMPL static void
00035 direct_fkt (C* dest, nat n2, nat n3) {
00036
00037 if (n2 == 2) {
00038 dest[2]= dest[1];
00039 dest[1] += dest[0];
00040 }
00041 else if (n2 == 4) {
00042 C p= dest[0] + dest[1];
00043 C q= dest[2] + dest[3];
00044 dest[6]= dest[2];
00045 dest[2]= dest[1];
00046 dest[8]= dest[3];
00047 dest[1]= p;
00048 dest[3]= dest[0] + dest[6];
00049 dest[4]= p+q;
00050 dest[5]= dest[2] + dest[8];
00051 dest[7]= q;
00052 }
00053 else while (n2 != n3) {
00054 direct_fkt_step (dest, n2);
00055 n2= n2 + (n2 >> 1);
00056 }
00057 }
00058
00059 TMPL static void
00060 inverse_fkt_step (C* dest, nat n, nat l) {
00061
00062
00063 nat t= n/3, k= t/l, ll= (l << 1) + 1;
00064 Pol::sub (dest + t, dest, t);
00065 Pol::sub (dest + t, dest + (t << 1), t);
00066 nat buf_size= aligned_size<C,V> (n);
00067 C* buf= mmx_new<C> (buf_size);
00068 Pol::copy (buf, dest, n);
00069 C* src= buf;
00070 if (l == 1) {
00071 Vec::triple_copy (dest, buf, t);
00072 Vec::triple_copy (dest + 1, buf + t, t);
00073 Vec::triple_copy (dest + 2, buf + (t << 1), t);
00074 }
00075 else while (k != 0) {
00076 Vec::double_copy (dest, src, l);
00077 Vec::double_copy (dest + 1, src + t, l);
00078 Vec::double_add (dest + 2, src + (t << 1), l-1);
00079 dest[l<<1]= src[(t<<1) + (l-1)];
00080 dest += ll; src += l; k--;
00081 }
00082 mmx_delete<C> (buf, buf_size);
00083 }
00084
00085 TMPL static void
00086 inverse_fkt (C* dest, nat n3, nat n2) {
00087
00088 if (n2 == 2)
00089 dest[1] -= (dest[0] + dest[2]);
00090 else if (n2 == 4) {
00091 dest[3] -= (dest[0] + dest[6]);
00092 dest[4] -= (dest[1] + dest[7]);
00093 dest[5] -= (dest[2] + dest[8]);
00094 C aux= dest[1]; dest[1]= dest[3]; dest[3]= aux;
00095 aux= dest[2]; dest[2]= dest[6]; dest[6]= aux;
00096 aux= dest[5]; dest[5]= dest[7]; dest[7]= aux;
00097 dest[3] -= (dest[0] + dest[6]);
00098 dest[4] -= (dest[1] + dest[7]);
00099 dest[5] -= (dest[2] + dest[8]);
00100 aux= dest[1];
00101 dest[1]= dest[3];
00102 dest[3]= dest[4];
00103 dest[4]= dest[2] + dest[7];
00104 dest[2]= aux + dest[6];
00105 dest[6]= dest[8];
00106 }
00107 else {
00108 nat n= n3, l= 1;
00109 while (n != l) {
00110 inverse_fkt_step (dest, n, l);
00111 nat k= n / ((l << 1) + l);
00112 l= (l << 1) + 1;
00113 n= k * l;
00114 }
00115 }
00116 }
00117
00118 };
00119
00120 #undef TMPL
00121 }
00122 #endif //__MMX__FKT_TRANSFORM__HPP