algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/vector_sse.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : vector_sse.hpp
00004 * DESCRIPTION: SSE instructions support for aligned vectors
00005 * COPYRIGHT  : (C) 2008  Joris van der Hoeven and 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_SSE__HPP
00014 #define __MMX__VECTOR_SSE__HPP
00015 
00016 #include <basix/operators.hpp>
00017 #include <basix/double.hpp>
00018 #include <numerix/sse.hpp>
00019 #include <algebramix/algebramix-config.hpp>
00020 #include <algebramix/vector_aligned.hpp>
00021 
00022 #ifndef NUMERIX_ENABLE_SIMD
00023 #undef ALGEBRAMIX_ENABLE_SIMD
00024 #endif
00025 
00026 namespace mmx {
00027 #ifdef ALGEBRAMIX_ENABLE_SIMD
00028 
00029 /******************************************************************************
00030 * SSE features helpers
00031 ******************************************************************************/
00032 
00033 // According to basix/fast_new.hpp, any allocation of size
00034 // being a multiple of 16 bytes is aligned.
00035 
00036 #ifdef __SSE2__
00037 
00038 template<typename Op, typename C>
00039 struct sse_has_helper { static const bool value= false;};
00040 
00041 template<typename C>
00042 struct sse_has_helper<id_op, C> {static const bool value= true;};
00043 
00044 STMPL
00045 struct sse_has_helper<equal_op, double> {static const bool value= true;};
00046 STMPL
00047 struct sse_has_helper<equal_op, int8_t> {static const bool value= true;};
00048 STMPL
00049 struct sse_has_helper<equal_op, uint8_t> {static const bool value= true;};
00050 STMPL
00051 struct sse_has_helper<equal_op, int16_t> {static const bool value= true;};
00052 STMPL
00053 struct sse_has_helper<equal_op, uint16_t> {static const bool value= true;};
00054 STMPL
00055 struct sse_has_helper<equal_op, int32_t> {static const bool value= true;};
00056 STMPL
00057 struct sse_has_helper<equal_op, uint32_t> {static const bool value= true;};
00058 STMPL
00059 struct sse_has_helper<equal_op, int64_t> {static const bool value= true;};
00060 STMPL
00061 struct sse_has_helper<equal_op, uint64_t> {static const bool value= true;};
00062 
00063 template<typename C>
00064 struct sse_has_helper<neg_op, C> {static const bool value= true;};
00065 
00066 template<typename C>
00067 struct sse_has_helper<add_op, C> {static const bool value= true;};
00068 
00069 template<typename C>
00070 struct sse_has_helper<sub_op, C> {static const bool value= true;};
00071 
00072 STMPL
00073 struct sse_has_helper<mul_op, double> {static const bool value= true;};
00074 STMPL
00075 struct sse_has_helper<mul_op, int8_t> {static const bool value= true;};
00076 STMPL
00077 struct sse_has_helper<mul_op, uint8_t> {static const bool value= true;};
00078 STMPL
00079 struct sse_has_helper<mul_op, int16_t> {static const bool value= true;};
00080 STMPL
00081 struct sse_has_helper<mul_op, uint16_t> {static const bool value= true;};
00082 
00083 template<typename C>
00084 struct sse_has_helper<lmul_op, C> {
00085   static const bool value= sse_has_helper<mul_op,C>::value; };
00086 
00087 template<typename C>
00088 struct sse_has_helper<rmul_op, C> {
00089   static const bool value= sse_has_helper<mul_op,C>::value; };
00090 
00091 STMPL
00092 struct sse_has_helper<div_op, double> {static const bool value= true;};
00093 
00094 template<typename C>
00095 struct sse_has_helper<ldiv_op, C> {
00096   static const bool value= sse_has_helper<div_op,C>::value; };
00097 
00098 template<typename C>
00099 struct sse_has_helper<rdiv_op, C> {
00100   static const bool value= sse_has_helper<div_op,C>::value; };
00101 
00102 template<typename C>
00103 struct sse_has_helper<mul_add_op, C> {
00104   static const bool value= sse_has_helper<add_op,C>::value &&
00105                            sse_has_helper<mul_op,C>::value; };
00106 
00107 STMPL
00108 struct sse_has_helper<min_op, uint8_t> {static const bool value= true;};
00109 STMPL
00110 struct sse_has_helper<min_op, int16_t> {static const bool value= true;};
00111 
00112 STMPL
00113 struct sse_has_helper<max_op, uint8_t> {static const bool value= true;};
00114 STMPL
00115 struct sse_has_helper<max_op, int16_t> {static const bool value= true;};
00116 
00117 /******************************************************************************
00118 * SSE support for aligned vectors
00119 ******************************************************************************/
00120 
00121 // Unary
00122 template<bool b, typename V, typename W, typename Op, typename C>
00123 struct vec_unary_simd_helper {
00124   typedef implementation<vector_abstractions,V> Vec;
00125   static inline void op (C* dest, const C* s, nat n) {
00126     Vec::template vec_unary<Op, C, C> (dest, s, n); }
00127 };
00128 
00129 template<typename V, typename W, typename Op, typename C>
00130 struct vec_unary_simd_helper <true,V,W,Op,C> {
00131   static inline void op (C* dest, const C* s, nat n) {
00132     typedef typename Simd_type (C) simd_C;
00133     typedef implementation<vector_abstractions,W> SVec;
00134     static const nat m= Simd_size (C);
00135     SVec::template vec_unary<Op, simd_C, simd_C>
00136       ((simd_C*) dest, (simd_C*) s, n / m); }
00137 };
00138 
00139 template<typename V, typename W, typename Op, typename C>
00140 struct vec_unary_aligned_helper <V,W,Op,C,C> :
00141     vec_unary_simd_helper <sse_has_helper<Op, C>::value,V,W,Op,C> {};
00142 
00143 // Binary
00144 template<bool b, typename V, typename W, typename Op, typename C>
00145 struct vec_binary_simd_helper {
00146   static inline void op (C* dest, const C* s1, const C* s2, nat n) {
00147     typedef implementation<vector_abstractions,V> Vec;
00148       Vec::template vec_binary<Op, C, C, C> (dest, s1, s2, n); }
00149 };
00150 
00151 template<typename V, typename W, typename Op, typename C>
00152 struct vec_binary_simd_helper <true,V,W,Op,C> {
00153   static inline void op (C* dest, const C* s1, const C* s2, nat n) {
00154     typedef typename Simd_type (C) simd_C;
00155     typedef implementation<vector_abstractions,W> SVec;
00156     static const nat m= Simd_size (C);
00157     SVec::template vec_binary<Op, simd_C, simd_C, simd_C>
00158       ((simd_C*) dest, (simd_C*) s1, (simd_C*) s2, n / m); }
00159 };
00160 
00161 template<typename V, typename W,typename Op, typename C>
00162 struct vec_binary_aligned_helper <V,W,Op,C,C,C> :
00163     vec_binary_simd_helper <sse_has_helper<Op, C>::value,V,W,Op,C> {};
00164 
00165 // Binary scalar
00166 template<bool b, typename V, typename W, typename Op, typename C>
00167 struct vec_binary_scalar_simd_helper {
00168   static inline void op (C* dest, const C* s, const C& x, nat n) {
00169     typedef implementation<vector_abstractions,V> Vec;
00170     Vec::template vec_binary_scalar<Op, C, C, C > (dest, s, x, n); }
00171 };
00172 
00173 template<typename V, typename W, typename Op, typename C>
00174 struct vec_binary_scalar_simd_helper <true,V,W,Op,C> {
00175   static inline void op (C* dest, const C* s, const C& x, nat n) {
00176     typedef typename Simd_type (C) simd_C;
00177     typedef implementation<vector_abstractions,W> SVec;
00178     static const nat m= Simd_size (C);
00179     simd_C vx= simd_set_duplicate (x);
00180     SVec::template vec_binary_scalar<Op, simd_C, simd_C, simd_C >
00181       ((simd_C*) dest, (simd_C*) s, vx, n / m); }
00182 };
00183 
00184 template<typename V, typename W, typename Op, typename C>
00185 struct vec_binary_scalar_aligned_helper <V,W,Op,C,C,C> :
00186     vec_binary_scalar_simd_helper <sse_has_helper<Op, C>::value,V,W,Op,C> {};
00187 
00188 #if 0
00189   // problem with neutral on simd types. FIXME
00190 template<typename V, typename W, typename C>
00191 struct vec_binary_big_aligned_helper<V,W,mul_add_op,C,C> {
00192   static inline C op (const C* s1, const C* s2, nat n) {
00193     typedef typename Simd_type (C) simd_C;
00194     typedef implementation<vector_abstractions,V> Vec;
00195     typedef implementation<vector_abstractions,W> SVec;
00196     static const nat m= Simd_size (C);
00197     if (sse_has_helper<mul_add_op, C>::value && m > 1) {
00198       simd_C vr= SVec::template vec_binary_big<mul_add_op, simd_C, simd_C>
00199         ((simd_C*) s1, (simd_C*) s2, n / m);
00200       return simd_big_add<C> (vr);
00201     }
00202     else
00203       return Vec::template vec_binary_big<mul_add_op, C, C> (s1, s2, n); }
00204 };
00205 #endif
00206 #endif // __SSE2__
00207 #endif // ALGEBRAMIX_ENABLE_SIMD
00208 } // namespace mmx
00209 
00210 #endif // __MMX__VECTOR_SSE__HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines