00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX__CRT_BLOCKS__HPP
00014 #define __MMX__CRT_BLOCKS__HPP
00015 #include <algebramix/crt_dicho.hpp>
00016
00017 namespace mmx {
00018
00019
00020
00021
00022
00023 #define Crt_blocks_variant(C) crt_blocks_variant_helper<C>::CV
00024
00025 template<typename V>
00026 struct crt_blocks: public V {};
00027
00028 template<typename F, typename V, typename W>
00029 struct implementation<F,V,crt_blocks<W> >:
00030 public implementation<F,V,W> {};
00031
00032 template<typename C>
00033 struct crt_blocks_variant_helper {
00034 typedef crt_blocks<typename crt_naive_variant_helper<C>::CV> CV;
00035 };
00036
00037
00038
00039
00040
00041 template<typename V,typename W>
00042 struct implementation<crt_transform,V,crt_blocks<W> > :
00043 public implementation<crt_project,V> {
00044 typedef implementation<crt_project,V> Crt;
00045
00046 template<typename I, typename C, typename CL, typename CH>
00047 static inline void
00048 direct (I* c, const C& a, CL** low, CH* high,
00049 C* aux, nat m, nat s) {
00050 high -> direct_transform (aux, a);
00051 for (nat i= 0; i < m; i++)
00052 low[i] -> direct_transform (c + i * s, aux[i]); }
00053
00054 template<typename C, typename I, typename CL, typename CH>
00055 static inline void
00056 combine (C& a, const I* c, CL* low, CH* high, C* aux, nat m, nat s) {
00057 for (nat i= 0; i < m; i++)
00058 low[i] -> combine (aux[i], c + i * s);
00059 high -> combine (a, aux); }
00060
00061 template<typename C, typename I, typename CL, typename CH>
00062 static inline void
00063 inverse (C& a, const I* c, CL* low, CH* high, C* aux, nat m, nat s) {
00064 for (nat i= 0; i < m; i++)
00065 low[i] -> inverse_transform (aux[i], c + i * s);
00066 high -> inverse_transform (a, aux); }
00067 };
00068
00069
00070
00071
00072
00073 struct crt_blocks_threshold {};
00074
00075 template<typename C>
00076 struct threshold_helper<C,crt_blocks_threshold> {
00077 typedef fixed_value<nat,32> impl;
00078 };
00079
00080
00081
00082
00083
00084 template<typename WL, typename WH,
00085 nat s=Threshold(typename WH::base,crt_blocks_threshold),
00086 typename V=typename Crt_blocks_variant(typename WH::base) >
00087 struct crt_blocks_transformer {
00088
00089 typedef typename WL::base base;
00090 typedef typename WL::modulus_variant modulus_variant;
00091 typedef typename WL::modulus_base modulus_base;
00092 typedef typename WL::modulus_base_variant modulus_base_variant;
00093
00094 private:
00095 typedef base C;
00096 typedef modulus_base I;
00097 typedef modulus<I, modulus_base_variant> M;
00098 typedef modulus<C, modulus_variant> Modulus;
00099 typedef implementation<crt_transform,V> Crt;
00100
00101 public:
00102
00103 nat n, m;
00104 WL** low;
00105 WH* high;
00106 C* aux;
00107 Modulus P;
00108 C H;
00109 bool setup;
00110
00111 inline void setup_comoduli () {}
00112
00113 inline void
00114 setup_inverse () {
00115 if (setup) return;
00116 high -> setup_inverse ();
00117 for (nat i= 0; i < m; i++)
00118 low[i] -> setup_inverse ();
00119 setup= true; }
00120
00121 inline crt_blocks_transformer (const vector<M>& p, bool lazy= true) {
00122 n= N(p); m= (n + s - 1) / s; setup= !lazy;
00123 if (n == 0) { P= 1; H= 0; return; }
00124 low= mmx_new<WL*> (m);
00125 vector<Modulus> v (Modulus (), m);
00126 for (nat i= 0; i < m; i++) {
00127 low[i]= mmx_new<WL> (1, range (p, i * s, min (n, (i+1) * s)), lazy);
00128 v[i]= low[i] -> product ();
00129 }
00130 high= mmx_new<WH> (1, v, lazy);
00131 P= high -> product ();
00132 H= Crt::half (P);
00133 aux= mmx_new<C> (m); }
00134
00135 inline ~crt_blocks_transformer () {
00136 if (n == 0) return;
00137 for (nat i= 0; i < m; i++) mmx_delete<WL> (low[i], 1);
00138 mmx_delete<WL*> (low, m);
00139 mmx_delete<WH> (high, 1);
00140 mmx_delete<C> (aux, m); }
00141
00142 inline M operator[] (nat i) const {
00143 VERIFY (i < n, "index out of range");
00144 return low[i / s]-> operator [] (i % s); }
00145
00146 inline nat size () const {
00147 return n; }
00148
00149 inline Modulus product () const {
00150 return P; }
00151
00152 inline C comodulus (nat i) const {
00153 VERIFY (i < n, "index out of range");
00154 return high -> comodulus(i / s) * low[i / s] -> comodulus(i % s); }
00155
00156 inline void direct_transform (I* c, const C& a) {
00157 if (n == 0) return;
00158 C b= Crt::encode (a, P);
00159 Crt::direct (c, b, low, high, aux, m, s); }
00160
00161 inline void combine (C& a, const I* c) {
00162 if (n == 0) { a= 0; return; }
00163 setup_comoduli ();
00164 Crt::combine (a, c, low, high, aux, m, s); }
00165
00166 inline void inverse_transform (C& a, const I* c) {
00167 if (n == 0) { a= 0; return; }
00168 setup_inverse ();
00169 Crt::inverse (a, c, low, high, aux, m, s);
00170 a= Crt::decode (a, P, H); }
00171
00172 };
00173
00174 template<typename WL, typename WH, nat s, typename V> inline nat
00175 N (const crt_blocks_transformer<WL,WH,s,V>& crter) {
00176 return crter.size ();
00177 }
00178
00179 }
00180 #endif //__MMX__CRT_BLOCKS__HPP