#ifndef SIMD_MATH_H #define SIMD_MATH_H #include "Fastor/meta/meta.h" #include "Fastor/simd_vector/extintrin.h" #include "Fastor/simd_vector/SIMDVector.h" #include // SHUT GCC6 -Wignored-attributes WARNINGS #ifdef __GNUC__ #if __GNUC__==6 #pragma GCC diagnostic ignored "-Wignored-attributes" #endif #endif namespace Fastor { // minimum //----------------------------------------------------------------------------------------------------------// template FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::min(((T*)&a)[i],((T*)&b)[i]); } return out; } template FASTOR_INLINE SIMDVector min(const SIMDVector &a, T b) { return min(a,SIMDVector(b)); } template FASTOR_INLINE SIMDVector min(T a, const SIMDVector &b) { return min(SIMDVector(a),b); } #ifdef FASTOR_SSE2_IMPL #ifdef FASTOR_SSE4_1_IMPL template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm_min_epi32(a.value,b.value); } #endif #if defined(FASTOR_AVX512F_IMPL) && defined(FASTOR_AVX512VL_IMPL) template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm_min_epi64(a.value,b.value); } #endif template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm_min_ps(a.value,b.value); } template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm_min_pd(a.value,b.value); } #endif #ifdef FASTOR_AVX_IMPL #ifdef FASTOR_AVX2_IMPL template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm256_min_epi32(a.value,b.value); } #endif #if defined(FASTOR_AVX512F_IMPL) && defined(FASTOR_AVX512VL_IMPL) template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm256_min_epi64(a.value,b.value); } #endif template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm256_min_ps(a.value,b.value); } template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm256_min_pd(a.value,b.value); } #endif #ifdef FASTOR_AVX512F_IMPL template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm512_min_epi32(a.value,b.value); } template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm512_min_epi64(a.value,b.value); } template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm512_min_ps(a.value,b.value); } template<> FASTOR_INLINE SIMDVector min(const SIMDVector &a, const SIMDVector &b) { return _mm512_min_pd(a.value,b.value); } #endif //----------------------------------------------------------------------------------------------------------// // maximum //----------------------------------------------------------------------------------------------------------// template FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::max(((T*)&a)[i],((T*)&b)[i]); } return out; } template FASTOR_INLINE SIMDVector max(const SIMDVector &a, T b) { return max(a,SIMDVector(b)); } template FASTOR_INLINE SIMDVector max(T a, const SIMDVector &b) { return max(SIMDVector(a),b); } #ifdef FASTOR_SSE2_IMPL #ifdef FASTOR_SSE4_1_IMPL template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm_max_epi32(a.value,b.value); } #endif #if defined(FASTOR_AVX512F_IMPL) && defined(FASTOR_AVX512VL_IMPL) template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm_max_epi64(a.value,b.value); } #endif template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm_max_ps(a.value,b.value); } template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm_max_pd(a.value,b.value); } #endif #ifdef FASTOR_AVX_IMPL #ifdef FASTOR_AVX2_IMPL template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm256_max_epi32(a.value,b.value); } #endif #if defined(FASTOR_AVX512F_IMPL) && defined(FASTOR_AVX512VL_IMPL) template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm256_max_epi64(a.value,b.value); } #endif template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm256_max_ps(a.value,b.value); } template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm256_max_pd(a.value,b.value); } #endif #ifdef FASTOR_AVX512F_IMPL template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm512_max_epi32(a.value,b.value); } template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm512_max_epi64(a.value,b.value); } template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm512_max_ps(a.value,b.value); } template<> FASTOR_INLINE SIMDVector max(const SIMDVector &a, const SIMDVector &b) { return _mm512_max_pd(a.value,b.value); } #endif //----------------------------------------------------------------------------------------------------------// // ceil //----------------------------------------------------------------------------------------------------------// template FASTOR_INLINE SIMDVector ceil(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::ceil(((T*)&a)[i]);} return out; } #ifdef FASTOR_SSE4_1_IMPL template<> FASTOR_INLINE SIMDVector ceil(const SIMDVector &a) { return _mm_ceil_ps(a.value); } template<> FASTOR_INLINE SIMDVector ceil(const SIMDVector &a) { return _mm_ceil_pd(a.value); } #endif #ifdef FASTOR_AVX_IMPL template<> FASTOR_INLINE SIMDVector ceil(const SIMDVector &a) { return _mm256_ceil_ps(a.value); } template<> FASTOR_INLINE SIMDVector ceil(const SIMDVector &a) { return _mm256_ceil_pd(a.value); } #endif // Part of SVML // #ifdef FASTOR_AVX512F_IMPL // template<> // FASTOR_INLINE SIMDVector ceil(const SIMDVector &a) { // return _mm512_ceil_ps(a.value); // } // template<> // FASTOR_INLINE SIMDVector ceil(const SIMDVector &a) { // return _mm512_ceil_pd(a.value); // } // #endif //----------------------------------------------------------------------------------------------------------// // round //----------------------------------------------------------------------------------------------------------// template FASTOR_INLINE SIMDVector round(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::round(((T*)&a)[i]);} return out; } #ifdef FASTOR_SSE4_1_IMPL template<> FASTOR_INLINE SIMDVector round(const SIMDVector &a) { return _mm_round_ps(a.value, ( _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC ) ); } template<> FASTOR_INLINE SIMDVector round(const SIMDVector &a) { return _mm_round_pd(a.value, ( _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC ) ); } #endif #ifdef FASTOR_AVX_IMPL template<> FASTOR_INLINE SIMDVector round(const SIMDVector &a) { return _mm256_round_ps(a.value, ( _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC ) ); } template<> FASTOR_INLINE SIMDVector round(const SIMDVector &a) { return _mm256_round_pd(a.value, ( _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC ) ); } #endif //----------------------------------------------------------------------------------------------------------// // floor //----------------------------------------------------------------------------------------------------------// template FASTOR_INLINE SIMDVector floor(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::floor(((T*)&a)[i]);} return out; } #ifdef FASTOR_SSE4_1_IMPL template<> FASTOR_INLINE SIMDVector floor(const SIMDVector &a) { return _mm_floor_ps(a.value); } template<> FASTOR_INLINE SIMDVector floor(const SIMDVector &a) { return _mm_floor_pd(a.value); } #endif #ifdef FASTOR_AVX_IMPL template<> FASTOR_INLINE SIMDVector floor(const SIMDVector &a) { return _mm256_floor_ps(a.value); } template<> FASTOR_INLINE SIMDVector floor(const SIMDVector &a) { return _mm256_floor_pd(a.value); } #endif //----------------------------------------------------------------------------------------------------------// // remaining math functions from STL //----------------------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------------------// template FASTOR_INLINE SIMDVector exp(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::exp(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector exp2(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::exp2(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector expm1(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::expm1(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector log(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::log(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector log10(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::log10(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector log2(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::log2(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector log1p(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::log1p(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector pow(const SIMDVector &a, const SIMDVector &b) { SIMDVector out; for (FASTOR_INDEX i = 0; i < SIMDVector::Size; i++) { ((T*)&out)[i] = std::pow(((T*)&a)[i], ((T*)&b)[i]);} return out; } template FASTOR_INLINE SIMDVector pow(const SIMDVector &a, T b) { return pow(a, SIMDVector(b)); } template FASTOR_INLINE SIMDVector pow(T a, const SIMDVector &b) { return pow(SIMDVector(a),b); } template FASTOR_INLINE SIMDVector cbrt(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::cbrt(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector sin(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::sin(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector cos(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::cos(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector tan(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::tan(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector asin(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::asin(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector acos(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::acos(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector atan(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::atan(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector atan2(const SIMDVector &a, const SIMDVector &b) { SIMDVector out; for (FASTOR_INDEX i = 0; i < SIMDVector::Size; i++) { ((T*)&out)[i] = std::atan2(((T*)&a)[i], ((T*)&b)[i]);} return out; } template FASTOR_INLINE SIMDVector atan2(const SIMDVector &a, T b) { return atan2(a, SIMDVector(b)); } template FASTOR_INLINE SIMDVector atan2(T a, const SIMDVector &b) { return atan2(SIMDVector(a),b); } template FASTOR_INLINE SIMDVector sinh(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::sinh(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector cosh(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::cosh(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector tanh(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::tanh(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector asinh(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::asinh(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector acosh(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::acosh(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector atanh(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::atanh(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector erf(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::erf(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector tgamma(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::tgamma(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector lgamma(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::lgamma(((T*)&a)[i]);} return out; } template FASTOR_INLINE SIMDVector hypot(const SIMDVector &a, const SIMDVector &b) { SIMDVector out; for (FASTOR_INDEX i = 0; i < SIMDVector::Size; i++) { ((T*)&out)[i] = std::hypot(((T*)&a)[i], ((T*)&b)[i]);} return out; } template FASTOR_INLINE SIMDVector hypot(const SIMDVector &a, T b) { return hypot(a, SIMDVector(b)); } template FASTOR_INLINE SIMDVector hypot(T a, const SIMDVector &b) { return hypot(SIMDVector(a),b); } template FASTOR_INLINE SIMDVector trunc(const SIMDVector &a) { SIMDVector out; for (FASTOR_INDEX i=0; i::Size; i++) { ((T*)&out)[i] = std::trunc(((T*)&a)[i]);} return out; } //----------------------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------------------// // Boolean arithmetic // ! or not //----------------------------------------------------------------------------------------------------------// template FASTOR_INLINE SIMDVector::Size>> operator!(const SIMDVector &a) { SIMDVector::Size>> out; for (FASTOR_INDEX i=0; i::Size; i++) { ((bool*)&out)[i] = !(((T*)&a)[i]); } return out; } //----------------------------------------------------------------------------------------------------------// // isinf/nan/finite //----------------------------------------------------------------------------------------------------------// template FASTOR_INLINE SIMDVector::Size>> isinf(const SIMDVector &a) { SIMDVector::Size>> out; for (FASTOR_INDEX i=0; i::Size; i++) { ((bool*)&out)[i] = std::isinf(((T*)&a)[i]); } return out; } template FASTOR_INLINE SIMDVector::Size>> isnan(const SIMDVector &a) { SIMDVector::Size>> out; for (FASTOR_INDEX i=0; i::Size; i++) { ((bool*)&out)[i] = std::isnan(((T*)&a)[i]); } return out; } template FASTOR_INLINE SIMDVector::Size>> isfinite(const SIMDVector &a) { SIMDVector::Size>> out; for (FASTOR_INDEX i=0; i::Size; i++) { ((bool*)&out)[i] = std::isfinite(((T*)&a)[i]); } return out; } //----------------------------------------------------------------------------------------------------------// } // end of namespace Fastor // Include all backends #include "Fastor/simd_math/sleef_backend.h" #endif // SIMD_MATH_H