algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/fkt_transform.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : fkt_transform.hpp
00004 * DESCRIPTION: fast Karatsuba transform
00005 * COPYRIGHT  : (C) 2004  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 #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   // dest of length n on entry and 3n/2 on exit
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   // dest of length n2 = 2^p on entry and n3 = 3^p on exit
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   // dest of length n = 3 k l on entry for some integer k
00062   // dest of length (2 l + 1) k on exit
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   // dest of length n3 = 3^p on entry and 2 n2 - 1 on exit with n2 = 2 ^ p
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 } // namespace mmx
00122 #endif //__MMX__FKT_TRANSFORM__HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines