00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX__MODULAR_SIMD__HPP
00014 #define __MMX__MODULAR_SIMD__HPP
00015 #include <basix/int.hpp>
00016 #include <numerix/simd.hpp>
00017 #include <numerix/sse.hpp>
00018 #include <numerix/modular.hpp>
00019 #ifdef NUMERIX_ENABLE_SIMD
00020 #include <algebramix/vector_fixed.hpp>
00021
00022 namespace mmx {
00023
00024
00025
00026
00027
00028 template<typename M>
00029 struct simd_modulus_helper;
00030
00031 template<typename M, typename W>
00032 struct simd_modulus_helper<modular<M,W> > {
00033 typedef typename M::base C;
00034 typedef typename simd_helper<C>::type simd_C;
00035 static inline C get_modulus () {
00036 return *modular<M,W>::get_modulus (); }
00037 static inline simd_C modulus_duplicate () {
00038 static const simd_C vp = simd_set_duplicate (get_modulus ());
00039 return vp; }
00040 };
00041
00042 template<typename C, typename V, typename X, X p>
00043 struct simd_modulus_helper <modular<modulus<C,V>, modular_fixed<X,p> > > {
00044 typedef modulus<C,V> M;
00045 typedef modular_fixed<X,p> W;
00046 typedef typename simd_helper<C>::type simd_C;
00047 static inline C get_modulus () {
00048 static const C np = *modular<M,W>::get_modulus ();
00049 return np; }
00050 static inline simd_C modulus_duplicate () {
00051 static const simd_C vp = simd_set_duplicate (get_modulus ());
00052 return vp; }
00053 };
00054
00055
00056
00057
00058
00059 #ifdef __SSSE3__
00060
00061 template<typename R, nat n>
00062 struct vec_neg_mod_simd_helper {};
00063
00064 template<typename R, nat n>
00065 struct vec_add_mod_simd_helper {};
00066
00067 template<typename R, nat n>
00068 struct vec_sub_mod_simd_helper {};
00069
00070 template<typename V, typename W>
00071 struct vec_neg_mod_simd_helper<modular<modulus<int8_t, V>, W>,
00072 Simd_size (int8_t)> {
00073 typedef int8_t C;
00074 typedef typename simd_helper<C>::type simd_C;
00075 typedef modulus<C, V> M;
00076 typedef modular<M, W> R;
00077
00078 static inline void op (R* dest, const R* s,
00079 const simd_C& vp, const simd_C& vz) {
00080 simd_C vs, vd;
00081 vs = simd_load_aligned ((C*) s);
00082 vd = - vs;
00083 vs = vd + vp;
00084 vd = _mm_min_epu8 ((__m128i) vd, (__m128i) vs);
00085 simd_save_aligned ((C*) dest, vd);
00086 }
00087 };
00088
00089 template<typename V, typename W, nat n>
00090 struct vec_neg_mod_simd_helper<modular<modulus<int8_t, V>, W>, n> {
00091 static const nat n1= (n>>1), n2= n-n1;
00092 typedef int8_t C;
00093 typedef typename simd_helper<C>::type simd_C;
00094 typedef modulus<C, V> M;
00095 typedef modular<M, W> R;
00096
00097 static inline void op (R* dest, const R* s,
00098 const simd_C& vp, const simd_C& vz) {
00099 vec_neg_mod_simd_helper <R, n1>::op (dest , s , vp, vz);
00100 vec_neg_mod_simd_helper <R, n2>::op (dest+n1, s+n1, vp, vz);
00101 }
00102 };
00103
00104 template<typename V, typename W, nat n>
00105 struct vec_unary_helper<neg_op,
00106 modular<modulus<int8_t, V>, W>,
00107 modular<modulus<int8_t, V>, W>,
00108 n> {
00109 typedef int8_t C;
00110 typedef typename simd_helper<C>::type simd_C;
00111 typedef modulus<C, V> M;
00112 typedef modular<M, W> R;
00113
00114 static inline void op (R* dest, const R* s) {
00115 const simd_C vz = simd_set_duplicate ((C) 0);
00116 const simd_C vp = simd_modulus_helper<R>::modulus_duplicate ();
00117 vec_neg_mod_simd_helper<R, n>:: op (dest, s, vp, vz);
00118 }
00119 };
00120
00121 template<typename V, typename W>
00122 struct vec_add_mod_simd_helper<modular<modulus<int8_t, V>, W>,
00123 Simd_size (int8_t)> {
00124 typedef int8_t C;
00125 typedef typename simd_helper<C>::type simd_C;
00126 typedef modulus<C, V> M;
00127 typedef modular<M, W> R;
00128
00129 static inline void op (R* dest, const R* s1, const R* s2,
00130 const simd_C& vp, const simd_C& vz) {
00131 simd_C v1, v2, vd;
00132 v1 = simd_load_aligned ((C*) s1);
00133 v2 = simd_load_aligned ((C*) s2);
00134 vd = v1 + v2;
00135 vd = _mm_min_epu8 ((__m128i) vd, (__m128i) (vd - vp));
00136 simd_save_aligned ((C*) dest, vd);
00137 }
00138 };
00139
00140 template<typename V, typename W, nat n>
00141 struct vec_add_mod_simd_helper<modular<modulus<int8_t, V>, W>, n> {
00142 static const nat n1= (n>>1), n2= n-n1;
00143 typedef int8_t C;
00144 typedef typename simd_helper<C>::type simd_C;
00145 typedef modulus<C, V> M;
00146 typedef modular<M, W> R;
00147
00148 static inline void op (R* dest, const R* s1, const R* s2,
00149 const simd_C& vp, const simd_C& vz) {
00150 vec_add_mod_simd_helper <R, n1>::op (dest , s1 , s2, vp, vz);
00151 vec_add_mod_simd_helper <R, n2>::op (dest+n1, s1+n1, s2+n1, vp, vz);
00152 }
00153 };
00154
00155 template<typename V, typename W, nat n>
00156 struct vec_binary_helper<add_op,
00157 modular<modulus<int8_t, V>, W>,
00158 modular<modulus<int8_t, V>, W>,
00159 modular<modulus<int8_t, V>, W>,
00160 n> {
00161 typedef int8_t C;
00162 typedef typename simd_helper<C>::type simd_C;
00163 typedef modulus<C, V> M;
00164 typedef modular<M, W> R;
00165
00166 static inline void op (R* dest, const R* s1, const R* s2) {
00167 const simd_C vz = simd_set_duplicate ((C) 0);
00168 const simd_C vp = simd_modulus_helper<R>::modulus_duplicate ();
00169 vec_add_mod_simd_helper<R, n>:: op (dest, s1, s2, vp, vz);
00170 }
00171 };
00172
00173 template<typename V, typename W>
00174 struct vec_sub_mod_simd_helper<modular<modulus<int8_t, V>, W>,
00175 Simd_size (int8_t)> {
00176 typedef int8_t C;
00177 typedef typename simd_helper<C>::type simd_C;
00178 typedef modulus<C, V> M;
00179 typedef modular<M, W> R;
00180
00181 static inline void op (R* dest, const R* s1, const R* s2,
00182 const simd_C& vp) {
00183 simd_C v1, v2, vd;
00184 v1 = simd_load_aligned ((C*) s1);
00185 v2 = simd_load_aligned ((C*) s2);
00186 vd = v1 - v2;
00187 vd = _mm_min_epu8 ((__m128i) vd, (__m128i) (vd + vp));
00188 simd_save_aligned ((C*) dest, vd);
00189 }
00190 };
00191
00192 template<typename V, typename W, nat n>
00193 struct vec_sub_mod_simd_helper<modular<modulus<int8_t, V>, W>, n> {
00194 static const nat n1= (n>>1), n2= n-n1;
00195 typedef int8_t C;
00196 typedef typename simd_helper<C>::type simd_C;
00197 typedef modulus<C, V> M;
00198 typedef modular<M, W> R;
00199
00200 static inline void op (R* dest, const R* s1, const R* s2,
00201 const simd_C& vp) {
00202 vec_sub_mod_simd_helper <R, n1>::op (dest , s1 , s2, vp);
00203 vec_sub_mod_simd_helper <R, n2>::op (dest+n1, s1+n1, s2+n1, vp);
00204 }
00205 };
00206
00207 template<typename V, typename W, nat n>
00208 struct vec_binary_helper<sub_op,
00209 modular<modulus<int8_t, V>, W>,
00210 modular<modulus<int8_t, V>, W>,
00211 modular<modulus<int8_t, V>, W>,
00212 n> {
00213 typedef int8_t C;
00214 typedef typename simd_helper<C>::type simd_C;
00215 typedef modulus<C, V> M;
00216 typedef modular<M, W> R;
00217
00218 static inline void op (R* dest, const R* s1, const R* s2) {
00219 const simd_C vp = simd_modulus_helper<R>::modulus_duplicate ();
00220 vec_sub_mod_simd_helper<R, n>:: op (dest, s1, s2, vp);
00221 }
00222 };
00223
00224 #endif // __SSSE3__
00225
00226 }
00227
00228 #endif // NUMERIX_ENABLE_SIMD
00229 #endif // __MMX__MODULAR_SIMD__HPP