00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00031
00032
00033
00034
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 #ifdef __SSE4_1__
00083 STMPL
00084 struct sse_has_helper<mul_op, int32_t> {static const bool value= true;};
00085 #endif
00086
00087 template<typename C>
00088 struct sse_has_helper<lmul_op, C> {
00089 static const bool value= sse_has_helper<mul_op,C>::value; };
00090
00091 template<typename C>
00092 struct sse_has_helper<rmul_op, C> {
00093 static const bool value= sse_has_helper<mul_op,C>::value; };
00094
00095 STMPL
00096 struct sse_has_helper<div_op, double> {static const bool value= true;};
00097
00098 template<typename C>
00099 struct sse_has_helper<ldiv_op, C> {
00100 static const bool value= sse_has_helper<div_op,C>::value; };
00101
00102 template<typename C>
00103 struct sse_has_helper<rdiv_op, C> {
00104 static const bool value= sse_has_helper<div_op,C>::value; };
00105
00106 template<typename C>
00107 struct sse_has_helper<mul_add_op, C> {
00108 static const bool value= sse_has_helper<add_op,C>::value &&
00109 sse_has_helper<mul_op,C>::value; };
00110
00111 STMPL
00112 struct sse_has_helper<min_op, double> {static const bool value= true;};
00113 STMPL
00114 struct sse_has_helper<min_op, uint8_t> {static const bool value= true;};
00115 #ifdef __SSE4_1__
00116 STMPL
00117 struct sse_has_helper<min_op, int8_t> {static const bool value= true;};
00118 STMPL
00119 struct sse_has_helper<min_op, uint16_t> {static const bool value= true;};
00120 #endif
00121 STMPL
00122 struct sse_has_helper<min_op, int16_t> {static const bool value= true;};
00123 #ifdef __SSE4_1__
00124 STMPL
00125 struct sse_has_helper<min_op, uint32_t> {static const bool value= true;};
00126 STMPL
00127 struct sse_has_helper<min_op, int32_t> {static const bool value= true;};
00128 #endif
00129
00130 STMPL
00131 struct sse_has_helper<max_op, double> {static const bool value= true;};
00132 STMPL
00133 struct sse_has_helper<max_op, uint8_t> {static const bool value= true;};
00134 #ifdef __SSE4_1__
00135 STMPL
00136 struct sse_has_helper<max_op, int8_t> {static const bool value= true;};
00137 STMPL
00138 struct sse_has_helper<max_op, uint16_t> {static const bool value= true;};
00139 #endif
00140 STMPL
00141 struct sse_has_helper<max_op, int16_t> {static const bool value= true;};
00142 #ifdef __SSE4_1__
00143 STMPL
00144 struct sse_has_helper<max_op, uint32_t> {static const bool value= true;};
00145 STMPL
00146 struct sse_has_helper<max_op, int32_t> {static const bool value= true;};
00147 #endif
00148
00149
00150
00151
00152
00153
00154 template<bool b, typename V, typename W, typename Op, typename C>
00155 struct vec_unary_simd_helper {
00156 typedef implementation<vector_abstractions,V> Vec;
00157 static inline void op (C* dest, const C* s, nat n) {
00158 Vec::template vec_unary<Op, C, C> (dest, s, n); }
00159 };
00160
00161 template<typename V, typename W, typename Op, typename C>
00162 struct vec_unary_simd_helper <true,V,W,Op,C> {
00163 static inline void op (C* dest, const C* s, nat n) {
00164 typedef typename Simd_type (C) simd_C;
00165 typedef implementation<vector_abstractions,W> SVec;
00166 static const nat m= Simd_size (C);
00167 SVec::template vec_unary<Op, simd_C, simd_C>
00168 ((simd_C*) dest, (simd_C*) s, n / m); }
00169 };
00170
00171 template<typename V, typename W, typename Op, typename C>
00172 struct vec_unary_aligned_helper <V,W,Op,C,C> :
00173 vec_unary_simd_helper <sse_has_helper<Op, C>::value,V,W,Op,C> {};
00174
00175
00176 template<bool b, typename V, typename W, typename Op, typename C>
00177 struct vec_binary_simd_helper {
00178 static inline void op (C* dest, const C* s1, const C* s2, nat n) {
00179 typedef implementation<vector_abstractions,V> Vec;
00180 Vec::template vec_binary<Op, C, C, C> (dest, s1, s2, n); }
00181 };
00182
00183 template<typename V, typename W, typename Op, typename C>
00184 struct vec_binary_simd_helper <true,V,W,Op,C> {
00185 static inline void op (C* dest, const C* s1, const C* s2, nat n) {
00186 typedef typename Simd_type (C) simd_C;
00187 typedef implementation<vector_abstractions,W> SVec;
00188 static const nat m= Simd_size (C);
00189 SVec::template vec_binary<Op, simd_C, simd_C, simd_C>
00190 ((simd_C*) dest, (simd_C*) s1, (simd_C*) s2, n / m); }
00191 };
00192
00193 template<typename V, typename W,typename Op, typename C>
00194 struct vec_binary_aligned_helper <V,W,Op,C,C,C> :
00195 vec_binary_simd_helper <sse_has_helper<Op, C>::value,V,W,Op,C> {};
00196
00197
00198 template<bool b, typename V, typename W, typename Op, typename C>
00199 struct vec_binary_scalar_simd_helper {
00200 static inline void op (C* dest, const C* s, const C& x, nat n) {
00201 typedef implementation<vector_abstractions,V> Vec;
00202 Vec::template vec_binary_scalar<Op, C, C, C > (dest, s, x, n); }
00203 };
00204
00205 template<typename V, typename W, typename Op, typename C>
00206 struct vec_binary_scalar_simd_helper <true,V,W,Op,C> {
00207 static inline void op (C* dest, const C* s, const C& x, nat n) {
00208 typedef typename Simd_type (C) simd_C;
00209 typedef implementation<vector_abstractions,W> SVec;
00210 static const nat m= Simd_size (C);
00211 simd_C vx= simd_set_duplicate (x);
00212 SVec::template vec_binary_scalar<Op, simd_C, simd_C, simd_C >
00213 ((simd_C*) dest, (simd_C*) s, vx, n / m); }
00214 };
00215
00216 template<typename V, typename W, typename Op, typename C>
00217 struct vec_binary_scalar_aligned_helper <V,W,Op,C,C,C> :
00218 vec_binary_scalar_simd_helper <sse_has_helper<Op, C>::value,V,W,Op,C> {};
00219
00220 #if 0
00221
00222 template<typename V, typename W, typename C>
00223 struct vec_binary_big_aligned_helper<V,W,mul_add_op,C,C> {
00224 static inline C op (const C* s1, const C* s2, nat n) {
00225 typedef typename Simd_type (C) simd_C;
00226 typedef implementation<vector_abstractions,V> Vec;
00227 typedef implementation<vector_abstractions,W> SVec;
00228 static const nat m= Simd_size (C);
00229 if (sse_has_helper<mul_add_op, C>::value && m > 1) {
00230 simd_C vr= SVec::template vec_binary_big<mul_add_op, simd_C, simd_C>
00231 ((simd_C*) s1, (simd_C*) s2, n / m);
00232 return simd_big_add<C> (vr);
00233 }
00234 else
00235 return Vec::template vec_binary_big<mul_add_op, C, C> (s1, s2, n); }
00236 };
00237 #endif
00238 #endif // __SSE2__
00239 #endif // ALGEBRAMIX_ENABLE_SIMD
00240 }
00241
00242 #endif // __MMX__VECTOR_SSE__HPP