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