algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : base_naive.hpp 00004 * DESCRIPTION: Implementation and interface for naive 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_NAIVE__HPP 00014 #define __MMX__BASE_NAIVE__HPP 00015 #include <basix/vector.hpp> 00016 #include <numerix/modular.hpp> 00017 00018 namespace mmx { 00019 00020 /****************************************************************************** 00021 * Size bound in base 00022 ******************************************************************************/ 00023 00024 template<typename C, typename I=C> 00025 struct size_bound_in_base_helper { 00026 static inline nat 00027 size (const C& s, const I& p) { 00028 ASSERT (N (p) > 1, "invalid base"); 00029 return is_signed_helper<C>::value ? 00030 1 + (1 + N (s)) / (N (p) - 1): 00031 1 + N (s) / (N (p) - 1); } 00032 }; 00033 00034 /****************************************************************************** 00035 * Standard parameters 00036 ******************************************************************************/ 00037 00038 template<typename C,typename I=C> 00039 struct std_base_naive { 00040 typedef C base; 00041 typedef I modulus_base; 00042 typedef typename Modulus_variant(I) modulus_base_variant; 00043 }; 00044 00045 /****************************************************************************** 00046 * Naive variant for Base 00047 ******************************************************************************/ 00048 00049 #define Base_naive_variant(C) base_naive_variant_helper<C>::BV 00050 00051 struct base_naive {}; 00052 00053 template<typename C> 00054 struct base_naive_variant_helper { 00055 typedef base_naive BV; 00056 }; 00057 00058 /****************************************************************************** 00059 * Direct and inverse transforms 00060 ******************************************************************************/ 00061 00062 struct base_transform {}; 00063 00064 template<typename V> 00065 struct implementation<base_transform,V,base_naive> { 00066 00067 template<typename C, typename M, typename I> static inline nat 00068 direct (I* c, nat n, const C& a, const M& p) { 00069 C x (a); nat i= 0; 00070 while (x != 0 && i < n) c[i++]= as<I> (rem (x, * p, x)); 00071 return i; } 00072 00073 template<typename C, typename M, typename I> static inline void 00074 inverse (C& a, const I* c, nat n, const M& p) { 00075 a= 0; while (n > 0) a = * p * a + c[--n]; } 00076 00077 }; 00078 00079 /****************************************************************************** 00080 * Signed variant for signed types 00081 ******************************************************************************/ 00082 00083 template<typename V> struct base_signed {}; 00084 00085 template<typename F, typename V, typename W> 00086 struct implementation<F,V,base_signed<W> >: 00087 public implementation<F,V,W> {}; 00088 00089 template<typename V,typename W> 00090 struct implementation<base_transform,V,base_signed<W> > : 00091 implementation<base_transform,V,W > { 00092 00093 template<typename C, typename M, typename I> static inline nat 00094 direct (I* c, nat n, const C& a, const M& p) { 00095 C x (a); C r, h (* p >> 1); nat i= 0; 00096 while (x != 0 && i < n) { 00097 if (x > 0) { 00098 r= rem (x, * p, x); 00099 if (r > h) { 00100 c[i++]= as<I> (r - * p); 00101 x += 1; 00102 } 00103 else 00104 c[i++]= as<I> (r); 00105 } 00106 else { 00107 r= rem (-x, * p, x); neg (x); 00108 if (r > h) { 00109 c[i++]= as<I> (* p - r); 00110 x -= 1; 00111 } 00112 else 00113 c[i++]= as<I> (- r); 00114 } 00115 } 00116 return i; } 00117 }; 00118 00119 /****************************************************************************** 00120 * The naive base transformer class 00121 ******************************************************************************/ 00122 00123 template<typename C, typename S=std_base_naive<C>, 00124 typename V=typename Base_naive_variant(C) > 00125 struct base_naive_transformer : public S { 00126 00127 typedef typename S::modulus_base I; 00128 typedef modulus<I, typename S::modulus_base_variant> M; 00129 typedef implementation<base_transform,V> Base; 00130 00131 M p; // modulus of the base 00132 00133 template<typename K> 00134 inline base_naive_transformer (const K& _p) : p(_p) { 00135 ASSERT (p != 0, "invalid base"); } 00136 00137 inline nat direct_transform (I* c, nat n, const C& a) const { 00138 return Base::direct (c, n, a, p); } 00139 00140 inline void inverse_transform (C& a, const I* c, nat n) { 00141 Base::inverse (a, c, n, p); } 00142 }; 00143 00144 /****************************************************************************** 00145 * Higher interface level -- common to all transformers 00146 ******************************************************************************/ 00147 00148 #define C typename Baser::base 00149 #define I typename Baser::modulus_base 00150 #define M modulus<typename Baser::modulus_base,\ 00151 typename Baser::modulus_base_variant> 00152 00153 template<typename Baser> inline nat 00154 size_bound (const C& a, Baser& baser) { 00155 // return a bound size for the expansion of a 00156 return size_bound_in_base_helper<C,I>::size (a, * baser.p); 00157 } 00158 00159 template<typename Baser> inline nat 00160 direct_base (I* dest, nat n, const C& s, Baser& baser) { 00161 // return the size filled in dest 00162 return baser.direct_transform (dest, n, s); 00163 } 00164 00165 template<typename Baser, typename W> inline void 00166 direct_base (vector<I,W>& dest, const C& s, Baser& baser) { 00167 nat n= size_bound (s, baser); 00168 nat l= aligned_size<I,W> (n); 00169 I* tmp= mmx_formatted_new<I> (l, CF(dest)); 00170 n= baser.direct_transform (tmp, n, s); 00171 dest= vector<I,W> (tmp, n, l, CF(dest)); 00172 } 00173 00174 template<typename Baser> inline vector<I> 00175 direct_base (const C& s, Baser& baser) { 00176 vector<I> dest; 00177 direct_base (dest, s, baser); 00178 return dest; 00179 } 00180 00181 template<typename Baser> inline void 00182 inverse_base (C& d, const I* src, nat n, Baser& baser) { 00183 baser.inverse_transform (d, src, n); 00184 } 00185 00186 template<typename Baser, typename W> inline void 00187 inverse_base (C& d, const vector<I,W>& src, Baser& baser) { 00188 baser.inverse_transform (d, seg (src), N(src)); 00189 } 00190 00191 template<typename Baser, typename W> inline C 00192 inverse_base (const vector<I,W>& src, Baser& baser) { 00193 C d; inverse_base (d, seg (src), N(src), baser); 00194 return d; 00195 } 00196 00197 #undef C 00198 #undef I 00199 #undef M 00200 } // namespace mmx 00201 #endif //__MMX__BASE_NAIVE__HPP