algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : modular_simd.hpp 00004 * DESCRIPTION: SIMD support for modulars 00005 * COPYRIGHT : (C) 2007 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__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 * Helpers 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 * modulars over int8_t 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 } // namespace mmx 00227 00228 #endif // NUMERIX_ENABLE_SIMD 00229 #endif // __MMX__MODULAR_SIMD__HPP