algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/modular_simd.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines