algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/base_dicho.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : base_dicho.hpp
00004 * DESCRIPTION: Implementation and interface for dichotomic change of bases
00005 * COPYRIGHT  : (C) 2009  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__BASE_DICHO__HPP
00014 #define __MMX__BASE_DICHO__HPP
00015 #include <algebramix/base_naive.hpp>
00016 
00017 namespace mmx {
00018 
00019 /******************************************************************************
00020 * Standard parameters
00021 ******************************************************************************/
00022 
00023 template<typename C>
00024 struct std_base_dicho {
00025   typedef C                           base;
00026   typedef C                           modulus_base;
00027   typedef typename Modulus_variant(C) modulus_base_variant;
00028 };
00029 
00030 /******************************************************************************
00031 * Dichotomic variant for Base
00032 ******************************************************************************/
00033 
00034 #define Base_dicho_variant(C) base_dicho_variant_helper<C>::BV
00035 
00036 template<typename V>
00037 struct base_dicho : public V {};
00038 
00039 template<typename F, typename V, typename W>
00040 struct implementation<F,V,base_dicho<W> >:
00041   public implementation<F,V,W> {};
00042 
00043 template<typename C>
00044 struct base_dicho_variant_helper {
00045   typedef base_dicho<typename base_naive_variant_helper<C>::BV> BV;
00046 };
00047 
00048 /******************************************************************************
00049 * Direct and inverse transforms
00050 ******************************************************************************/
00051 
00052 template<typename V, typename W>
00053 struct implementation<base_transform,V,base_dicho<W> > {
00054 
00055   template<typename C, typename M, typename I> static inline nat
00056   direct (I* c, nat n, const C& a, const M* pow_p) {
00057     if (n == 0 || a == 0) return 0;
00058     if (n == 1) {
00059       c[0]= rem (a, * pow_p[0]);
00060       return 1; }
00061     C q, r;
00062     nat h= (n+1) >> 1, l= log_2 (h); nat m= ((nat) 1) << l;
00063     r= rem (a, * pow_p[l], q);
00064     nat o= direct (c, m, r, pow_p);
00065     if (q == 0) return o;
00066     for (; o < m; o++) c[o]= 0;
00067     return m + direct (c + m, n - m, q, pow_p); }
00068 
00069   template<typename C, typename M, typename I> static inline void
00070   inverse (C& a, const I* c, nat n, const M* pow_p) {
00071     if (n == 0) return;
00072     if (n == 1) { a= c[0]; return; }
00073     if (n == 2) { a= c[0] + C(* pow_p[0]) * c[1]; return; }
00074     nat h= (n+1) >> 1; nat l= log_2 (h); nat m= ((nat) 1) << l; C b;
00075     inverse (a, c    , m    , pow_p);
00076     inverse (b, c + m, n - m, pow_p);
00077     a += * pow_p[l] * b; }
00078 
00079 };
00080 
00081 /******************************************************************************
00082 * Signed variant for signed types
00083 ******************************************************************************/
00084 
00085 template<typename V,typename W>
00086 struct implementation<base_transform,V,base_signed<base_dicho<W> > > :
00087     implementation<base_transform,V,base_dicho<W> > {
00088 private:
00089   template<typename C, typename M, typename I> static inline nat
00090   direct (I* c, nat n, const C& a, const M* pow_p, I& carry) {
00091     if (n == 0 || a == 0) { carry= 0; return 0; }
00092     C q, r;
00093     if (n == 1) {
00094       r= rem (abs (a), * pow_p[0], q);
00095       if (r > * pow_p[0] >> 1) { r -= * pow_p[0]; q += 1; }
00096       if (a < 0) { neg (r); neg (q); }
00097       c[0]= as<I> (r); carry= q;
00098       return c[0] == 0 ? 0 : 1;
00099     }
00100     nat h= (n+1) >> 1, l= log_2 (h); nat m= ((nat) 1) << l;
00101     r= rem (abs (a), * pow_p[l], q);
00102     if (a < 0) { neg (r); neg (q); }
00103     nat o= direct (c, m, r, pow_p, carry); q += carry;
00104     if (q == 0) return o;
00105     for (; o < m; o++) c[o]= 0;
00106     return m + direct (c + m, n - m, q, pow_p, carry);
00107   }
00108 public:
00109   template<typename C, typename M, typename I> static inline nat
00110   direct (I* c, nat n, const C& a, const M* pow_p) {
00111     I carry (0); nat o= direct (c, n, a, pow_p, carry); (void) carry;
00112     return o; }
00113 
00114 };
00115 
00116 /******************************************************************************
00117 * The naive base transformer class
00118 ******************************************************************************/
00119 
00120 template<typename C, typename S=std_base_dicho<C>,
00121          typename V=typename Base_dicho_variant(C) >
00122 struct base_dicho_transformer : public S {
00123 
00124   typedef typename S::modulus_base I;
00125   typedef modulus<I, typename S::modulus_base_variant> M;
00126   typedef implementation<base_transform,V> Base;
00127 
00128   vector<M> pow_p;
00129   M p;
00130 
00131 private:
00132   void extend (nat n) {
00133     while (((nat) 1) << N(pow_p) <= ((n + 1) >> 1))
00134       pow_p << M (square (* pow_p[N(pow_p) - 1])); }
00135 public:
00136 
00137   template<typename K> 
00138   inline base_dicho_transformer (const K& _p) : p(_p) {
00139     ASSERT (_p != 0, "invalid base");
00140     pow_p << p; }
00141 
00142   inline nat direct_transform (I* c, nat n, const C& a) {
00143     extend (n);
00144     return Base::direct (c, n, a, seg (pow_p)); }
00145 
00146   inline void inverse_transform (C& a, const I* c, nat n) {
00147     extend (n);
00148     Base::inverse (a, c, n, seg (pow_p)); }
00149 };
00150 
00151 } // namespace mmx
00152 #endif //__MMX__BASE_DICHO__HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines