00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
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
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
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
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
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;
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
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
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
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 }
00201 #endif //__MMX__BASE_NAIVE__HPP