algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/base_naive.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines