algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : vector_modular.hpp 00004 * DESCRIPTION: header for low level vectorial computations over modular 00005 * COPYRIGHT : (C) 2008 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__VECTOR_MODULAR__HPP 00014 #define __MMX__VECTOR_MODULAR__HPP 00015 #include <numerix/modular.hpp> 00016 #include <algebramix/vector_unrolled.hpp> 00017 00018 namespace mmx { 00019 00020 /****************************************************************************** 00021 * Optimized unrolling for modular operations 00022 ******************************************************************************/ 00023 00024 // neg_op 00025 template<typename R, typename M, nat n> 00026 struct vec_neg_mod_helper { 00027 static const nat n1= (n>>1), n2= n-n1; 00028 static inline void op (R* dest, const R* s, const M& m) { 00029 vec_neg_mod_helper <R, M, n1>::op (dest , s , m); 00030 vec_neg_mod_helper <R, M, n2>::op (dest+n1, s+n1, m); } 00031 }; 00032 00033 template<typename R, typename M> 00034 struct vec_neg_mod_helper<R, M, 1> { 00035 static inline void op (R* dest, const R* s, const M& m) { 00036 dest[0] = s[0]; 00037 neg_mod (dest->rep, m); } 00038 }; 00039 00040 template<typename C, typename V, typename W, nat n> 00041 struct vec_unary_helper<neg_op, 00042 modular<modulus<C, V>, W>, 00043 modular<modulus<C, V>, W>, 00044 n> { 00045 typedef modulus<C, V> M; 00046 typedef modular<M, W> R; 00047 static void op (R* dest, const R* s) { 00048 vec_neg_mod_helper<R, M, n>:: op (dest, s, R::get_modulus ()); } 00049 }; 00050 00051 // add_op 00052 template<typename R, typename M, nat n> 00053 struct vec_add_mod_helper { 00054 static const nat n1= (n>>1), n2= n-n1; 00055 static inline void op (R* dest, const R* s1, const R* s2, const M& m) { 00056 vec_add_mod_helper <R, M, n1>::op (dest , s1 , s2 , m); 00057 vec_add_mod_helper <R, M, n2>::op (dest+n1, s1+n1, s2+n1, m); } 00058 }; 00059 00060 template<typename R, typename M> 00061 struct vec_add_mod_helper<R, M, 1> { 00062 static inline void op (R* dest, const R* s1, const R* s2, const M& m) { 00063 dest[0] = s1[0]; 00064 add_mod (dest->rep, s2->rep, m); } 00065 }; 00066 00067 template<typename C, typename V, typename W, nat n> 00068 struct vec_binary_helper<add_op, 00069 modular<modulus<C, V>, W>, 00070 modular<modulus<C, V>, W>, 00071 modular<modulus<C, V>, W>, 00072 n> { 00073 typedef modulus<C, V> M; 00074 typedef modular<M, W> R; 00075 static void op (R* dest, const R* s1, const R* s2) { 00076 vec_add_mod_helper<R, M, n>:: op (dest, s1, s2, R::get_modulus ()); } 00077 }; 00078 00079 // sub_op 00080 template<typename R, typename M, nat n> 00081 struct vec_sub_mod_helper { 00082 static const nat n1= (n>>1), n2= n-n1; 00083 static inline void op (R* dest, const R* s1, const R* s2, const M& m) { 00084 vec_sub_mod_helper <R, M, n1>::op (dest , s1 , s2 , m); 00085 vec_sub_mod_helper <R, M, n2>::op (dest+n1, s1+n1, s2+n1, m); } 00086 }; 00087 00088 template<typename R, typename M> 00089 struct vec_sub_mod_helper<R, M, 1> { 00090 static inline void op (R* dest, const R* s1, const R* s2, const M& m) { 00091 dest[0] = s1[0]; 00092 sub_mod (dest->rep, s2->rep, m); } 00093 }; 00094 00095 template<typename C, typename V, typename W, nat n> 00096 struct vec_binary_helper<sub_op, 00097 modular<modulus<C, V>, W>, 00098 modular<modulus<C, V>, W>, 00099 modular<modulus<C, V>, W>, 00100 n> { 00101 typedef modulus<C, V> M; 00102 typedef modular<M, W> R; 00103 static void op (R* dest, const R* s1, const R* s2) { 00104 vec_sub_mod_helper<R, M, n>:: op (dest, s1, s2, R::get_modulus ()); } 00105 }; 00106 00107 // mul_op 00108 template<typename R, typename M, nat n> 00109 struct vec_mul_mod_helper { 00110 static const nat n1= (n>>1), n2= n-n1; 00111 static inline void op (R* dest, const R* s1, const R* s2, const M& m) { 00112 vec_mul_mod_helper <R, M, n1>::op (dest , s1 , s2 , m); 00113 vec_mul_mod_helper <R, M, n2>::op (dest+n1, s1+n1, s2+n1, m); } 00114 }; 00115 00116 template<typename R, typename M> 00117 struct vec_mul_mod_helper<R, M, 1> { 00118 static inline void op (R* dest, const R* s1, const R* s2, const M& m) { 00119 dest[0] = s1[0]; 00120 mul_mod (dest->rep, s2->rep, m); } 00121 }; 00122 00123 template<typename C, typename V, typename W, nat n> 00124 struct vec_binary_helper<mul_op, 00125 modular<modulus<C, V>, W>, 00126 modular<modulus<C, V>, W>, 00127 modular<modulus<C, V>, W>, 00128 n> { 00129 typedef modulus<C, V> M; 00130 typedef modular<M, W> R; 00131 static void op (R* dest, const R* s1, const R* s2) { 00132 vec_mul_mod_helper<R, M, n>:: op (dest, s1, s2, R::get_modulus ()); } 00133 }; 00134 00135 // div_op 00136 template<typename R, typename M, nat n> 00137 struct vec_div_mod_helper { 00138 static const nat n1= (n>>1), n2= n-n1; 00139 static inline void op (R* dest, const R* s1, const R* s2, const M& m) { 00140 vec_div_mod_helper <R, M, n1>::op (dest , s1 , s2 , m); 00141 vec_div_mod_helper <R, M, n2>::op (dest+n1, s1+n1, s2+n1, m); } 00142 }; 00143 00144 template<typename R, typename M> 00145 struct vec_div_mod_helper<R, M, 1> { 00146 static inline void op (R* dest, const R* s1, const R* s2, const M& m) { 00147 dest[0] = s1[0]; 00148 div_mod (dest->rep, s2->rep, m); } 00149 }; 00150 00151 template<typename C, typename V, typename W, nat n> 00152 struct vec_binary_helper<div_op, 00153 modular<modulus<C, V>, W>, 00154 modular<modulus<C, V>, W>, 00155 modular<modulus<C, V>, W>, 00156 n> { 00157 typedef modulus<C, V> M; 00158 typedef modular<M, W> R; 00159 static void op (R* dest, const R* s1, const R* s2) { 00160 vec_div_mod_helper<R, M, n>:: op (dest, s1, s2, R::get_modulus ()); } 00161 }; 00162 00163 /****************************************************************************** 00164 * Use modular vector operations by default 00165 ******************************************************************************/ 00166 00167 template<typename V, typename W> 00168 struct vector_variant_helper<modular<modulus<char,V>, W> > { 00169 typedef vector_unrolled<16,vector_unrolled<32> > VV; 00170 }; 00171 00172 template<typename V, typename W> 00173 struct vector_variant_helper<modular<modulus<signed char,V>, W> > { 00174 typedef vector_unrolled<16,vector_unrolled<32> > VV; 00175 }; 00176 00177 template<typename V, typename W> 00178 struct vector_variant_helper<modular<modulus<unsigned char,V>, W> > { 00179 typedef vector_unrolled<16,vector_unrolled<32> > VV; 00180 }; 00181 00182 template<typename V, typename W> 00183 struct vector_variant_helper<modular<modulus<short int,V>, W> > { 00184 typedef vector_unrolled<8,vector_unrolled<32> > VV; 00185 }; 00186 00187 template<typename V, typename W> 00188 struct vector_variant_helper<modular<modulus<short unsigned int,V>, W> > { 00189 typedef vector_unrolled<8,vector_unrolled<32> > VV; 00190 }; 00191 00192 template<typename V, typename W> 00193 struct vector_variant_helper<modular<modulus<int,V>, W> > { 00194 typedef vector_unrolled<4,vector_unrolled<16> > VV; 00195 }; 00196 00197 template<typename V, typename W> 00198 struct vector_variant_helper<modular<modulus<unsigned int,V>, W> > { 00199 typedef vector_unrolled<4,vector_unrolled<16> > VV; 00200 }; 00201 00202 template<typename V, typename W> 00203 struct vector_variant_helper<modular<modulus<long int,V>, W> > { 00204 typedef vector_unrolled<4,vector_unrolled<16> > VV; 00205 }; 00206 00207 template<typename V, typename W> 00208 struct vector_variant_helper<modular<modulus<long unsigned int,V>, W> > { 00209 typedef vector_unrolled<4,vector_unrolled<16> > VV; 00210 }; 00211 00212 template<typename V, typename W> 00213 struct vector_variant_helper<modular<modulus<long long int,V>, W> > { 00214 typedef vector_unrolled<2,vector_unrolled<8> > VV; 00215 }; 00216 00217 template<typename V, typename W> 00218 struct vector_variant_helper<modular<modulus<long long unsigned int,V>, W> > { 00219 typedef vector_unrolled<2,vector_unrolled<8> > VV; 00220 }; 00221 00222 } // namespace mmx 00223 #endif //__MMX__VECTOR_MODULAR__HPP