LCOV - code coverage report
Current view: top level - Src/SSE3 - InaVecSSE3Float.hpp (source / functions) Hit Total Coverage
Test: Coverage inastemp Lines: 189 189 100.0 %
Date: 2022-03-17 09:48:28 Functions: 170 170 100.0 %

          Line data    Source code
       1             : ///////////////////////////////////////////////////////////////////////////
       2             : // Inastemp - Berenger Bramas MPCDF - 2016
       3             : // Under MIT Licence, please you must read the LICENCE file.
       4             : ///////////////////////////////////////////////////////////////////////////
       5             : #ifndef INAVECSSE3FLOAT_HPP
       6             : #define INAVECSSE3FLOAT_HPP
       7             : 
       8             : #include "InastempGlobal.h"
       9             : #include "Common/InaIfElse.hpp"
      10             : #include "Common/InaUtils.hpp"
      11             : 
      12             : #ifndef INASTEMP_USE_SSE3
      13             : #error InaVecSSE3<float> is included but SSE3 is not enable in the configuration
      14             : #endif
      15             : 
      16             : #include "Common/InaFastExp.hpp"
      17             : 
      18             : #include <emmintrin.h>
      19             : #include <pmmintrin.h>
      20             : #include <cmath>
      21             : #include <initializer_list>
      22             : 
      23             : #ifdef __FMA__
      24             : #include <immintrin.h>
      25             : #endif
      26             : 
      27             : // Forward declarations
      28             : template <class RealType>
      29             : class InaVecMaskSSE3;
      30             : 
      31             : template <class RealType>
      32             : class InaVecSSE3;
      33             : 
      34             : 
      35             : // Mask type
      36             : template <>
      37             : class InaVecMaskSSE3<float> {
      38             :     __m128i mask;
      39             : public:
      40             :     // Classic constructors
      41             :     inline InaVecMaskSSE3(){}
      42             : 
      43             :     inline InaVecMaskSSE3(const InaVecMaskSSE3&) = default;
      44             :     inline InaVecMaskSSE3& operator=(const InaVecMaskSSE3&) = default;
      45             : 
      46             :     // Native data type compatibility
      47             :     inline /*not explicit*/ InaVecMaskSSE3(const __m128i inMask)
      48             :         : mask(inMask){}
      49             : 
      50             :     inline InaVecMaskSSE3& operator=(const __m128i inMask){
      51             :         mask = inMask;
      52             :         return (*this);
      53             :     }
      54             : 
      55             :     inline explicit operator __m128i() const{
      56             :         return mask;
      57             :     }
      58             : 
      59             :     inline __m128i getMask() const{
      60             :         return mask;
      61             :     }
      62             : 
      63             :     // Bool data type compatibility
      64          80 :     inline explicit InaVecMaskSSE3(const bool inBool){
      65          80 :         mask = (inBool? _mm_set1_epi32(static_cast<int>(0xFFFFFFFF)) : _mm_setzero_si128());
      66             :     }
      67             : 
      68             :     inline InaVecMaskSSE3& operator=(const bool inBool){
      69             :         mask = (inBool? _mm_set1_epi32(static_cast<int>(0xFFFFFFFF)) : _mm_setzero_si128());
      70             :         return (*this);
      71             :     }
      72             : 
      73             :     // Binary methods
      74             :     inline InaVecMaskSSE3 Not() const{
      75             :         return NotAnd(mask, _mm_set1_epi32(static_cast<int>(0xFFFFFFFF)));
      76             :     }
      77             : 
      78             :     inline bool isAllTrue() const{
      79             :         // true if all FF
      80          60 :         return _mm_movemask_epi8(_mm_cmpeq_epi32(mask,_mm_set1_epi32(static_cast<int>(0xFFFFFFFF)))) == 0xFFFF;
      81             :     }
      82             : 
      83             :     inline bool isAllFalse() const{
      84             :         // true if all zero
      85          60 :         return _mm_movemask_epi8(_mm_cmpeq_epi32(mask,_mm_setzero_si128())) == 0xFFFF;
      86             :     }
      87             : 
      88             :     // Double args methods
      89             :     inline static InaVecMaskSSE3 And(const InaVecMaskSSE3& inMask1, const InaVecMaskSSE3& inMask2){
      90             :         return InaVecMaskSSE3(_mm_and_si128(inMask1.mask, inMask2.mask));
      91             :     }
      92             : 
      93             :     inline static InaVecMaskSSE3 NotAnd(const InaVecMaskSSE3& inMask1, const InaVecMaskSSE3& inMask2){
      94             :         return InaVecMaskSSE3(_mm_andnot_si128(inMask1.mask, inMask2.mask));
      95             :     }
      96             : 
      97             :     inline static InaVecMaskSSE3 Or(const InaVecMaskSSE3& inMask1, const InaVecMaskSSE3& inMask2){
      98         168 :         return InaVecMaskSSE3(_mm_or_si128(inMask1.mask, inMask2.mask));
      99             :     }
     100             : 
     101             :     inline static InaVecMaskSSE3 Xor(const InaVecMaskSSE3& inMask1, const InaVecMaskSSE3& inMask2){
     102             :         return InaVecMaskSSE3(_mm_xor_si128(inMask1.mask, inMask2.mask));
     103             :     }
     104             : 
     105             :     inline static bool IsEqual(const InaVecMaskSSE3& inMask1, const InaVecMaskSSE3& inMask2){
     106          48 :         return _mm_movemask_epi8(_mm_cmpeq_epi32(inMask1.mask,inMask2.mask)) == 0xFFFF;
     107             :     }
     108             : 
     109             :     inline static bool IsNotEqual(const InaVecMaskSSE3& inMask1, const InaVecMaskSSE3& inMask2){
     110          24 :         return _mm_movemask_epi8(_mm_cmpeq_epi32(inMask1.mask,inMask2.mask)) != 0xFFFF;
     111             :     }
     112             : };
     113             : 
     114             : // Mask must have operators
     115             : inline InaVecMaskSSE3<float> operator&(const InaVecMaskSSE3<float>& inMask1, const InaVecMaskSSE3<float>& inMask2){
     116             :     return InaVecMaskSSE3<float>::And(inMask1, inMask2);
     117             : }
     118             : 
     119             : inline InaVecMaskSSE3<float> operator|(const InaVecMaskSSE3<float>& inMask1, const InaVecMaskSSE3<float>& inMask2){
     120             :     return InaVecMaskSSE3<float>::Or(inMask1, inMask2);
     121             : }
     122             : 
     123             : inline InaVecMaskSSE3<float> operator^(const InaVecMaskSSE3<float>& inMask1, const InaVecMaskSSE3<float>& inMask2){
     124             :     return InaVecMaskSSE3<float>::Xor(inMask1, inMask2);
     125             : }
     126             : 
     127             : inline bool operator==(const InaVecMaskSSE3<float>& inMask1, const InaVecMaskSSE3<float>& inMask2){
     128          16 :     return InaVecMaskSSE3<float>::IsEqual(inMask1, inMask2);
     129             : }
     130             : 
     131             : inline bool operator!=(const InaVecMaskSSE3<float>& inMask1, const InaVecMaskSSE3<float>& inMask2){
     132           8 :     return InaVecMaskSSE3<float>::IsNotEqual(inMask1, inMask2);
     133             : }
     134             : 
     135             : // Vec type
     136             : template <>
     137             : class InaVecSSE3<float> {
     138             : protected:
     139             :     __m128 vec;
     140             : 
     141             : public:
     142             :     using VecRawType           = __m128;
     143             :     using MaskType             = InaVecMaskSSE3<float>;
     144             :     using RealType             = float;
     145             :     [[deprecated("Please use the method instead")]]
     146             :     static const int VecLength = 4;
     147             :     static const int Alignement= 16;
     148             :     static const bool IsOfFixedSize = true;
     149             : 
     150             :     static constexpr int GetVecLength(){
     151             :         return 4;
     152             :     }
     153             : 
     154             :     static constexpr bool IsRealFma(){
     155             : #ifdef __FMA__
     156             :         return true;
     157             : #else
     158             :         return false;
     159             : #endif
     160             :     }
     161             : 
     162         204 :     inline InaVecSSE3(){}
     163             :     inline InaVecSSE3(const InaVecSSE3&) = default;
     164             :     inline InaVecSSE3& operator = (const InaVecSSE3&) = default;
     165             : 
     166             :     // Constructor from raw type
     167             :     /*not explicit*/ InaVecSSE3(const __m128 inVec)
     168          74 :         : vec(inVec){
     169             :     }
     170             : 
     171             :     inline InaVecSSE3& operator=(const __m128 inVec){
     172             :         vec = inVec;
     173             :         return *this;
     174             :     }
     175             : 
     176             :     inline void setFromRawType(const __m128 inVec){
     177             :         vec = inVec;
     178             :     }
     179             : 
     180             :     inline explicit operator __m128() const{
     181             :         return vec;
     182             :     }
     183             : 
     184             :     inline __m128 getVec() const{
     185             :         return vec;
     186             :     }
     187             : 
     188             :     // Constructor from scalar
     189             :     /*not explicit*/ InaVecSSE3(const float val)
     190        8712 :         : vec(_mm_set1_ps(val)){
     191             :     }
     192             : 
     193             :     inline InaVecSSE3& operator=(const float val){
     194             :         vec = _mm_set1_ps(val);
     195             :         return *this;
     196             :     }
     197             : 
     198             :     inline void setFromScalar(const float val){
     199             :         vec = _mm_set1_ps(val);
     200             :     }
     201             : 
     202             :     // Constructor from vec
     203             :     inline InaVecSSE3(const std::initializer_list<float> lst)
     204          48 :         : InaVecSSE3(lst.begin()){
     205             :     }
     206             : 
     207             :     inline explicit InaVecSSE3(const float ptr[])
     208        8232 :         : vec(_mm_loadu_ps(ptr)){
     209             :     }
     210             : 
     211             :     inline InaVecSSE3& setFromArray(const float ptr[]){
     212         360 :         vec = _mm_loadu_ps(ptr);
     213             :         return *this;
     214             :     }
     215             : 
     216             :     inline InaVecSSE3& setFromAlignedArray(const float ptr[]){
     217         100 :         vec = _mm_load_ps(ptr);
     218             :         return *this;
     219             :     }
     220             : 
     221             :     inline InaVecSSE3& setFromIndirectArray(const float values[], const int inIndirection[]) {
     222         300 :         vec = _mm_set_ps(
     223          60 :             values[inIndirection[3]],
     224          60 :             values[inIndirection[2]],
     225          60 :             values[inIndirection[1]],
     226          60 :             values[inIndirection[0]]);
     227             :         return *this;
     228             :     }
     229             : 
     230          60 :     inline InaVecSSE3& setFromIndirect2DArray(const float inArray[], const int inIndirection1[],
     231             :                                  const int inLeadingDimension, const int inIndirection2[]){
     232         300 :         vec = _mm_set_ps(
     233          60 :             inArray[inIndirection1[3] * inLeadingDimension + inIndirection2[3]],
     234          60 :             inArray[inIndirection1[2] * inLeadingDimension + inIndirection2[2]],
     235          60 :             inArray[inIndirection1[1] * inLeadingDimension + inIndirection2[1]],
     236          60 :             inArray[inIndirection1[0] * inLeadingDimension + inIndirection2[0]]);
     237          60 :         return *this;
     238             :     }
     239             : 
     240             :     // Move back to array
     241             :     inline void storeInArray(float ptr[]) const {
     242       27704 :         _mm_storeu_ps(ptr, vec);
     243             :     }
     244             : 
     245             :     inline void storeInAlignedArray(float ptr[]) const {
     246       10360 :         _mm_store_ps(ptr, vec);
     247             :     }
     248             : 
     249             :     // Acce to individual values
     250             :     inline float at(const int index) const {
     251             :         alignas(Alignement) float allval[GetVecLength()];
     252       52320 :         _mm_store_ps(allval, vec);
     253       26160 :         return allval[index];
     254             :     }
     255             : 
     256             :     // Horizontal operation
     257             :     inline float horizontalSum() const {
     258             :         // Better than _mm_hadd_ps
     259       11880 :         const __m128 val02_13_20_31 = _mm_add_ps(vec, _mm_movehl_ps(vec, vec));
     260        7930 :         const __m128 res            = _mm_add_ss(val02_13_20_31, _mm_shuffle_ps(val02_13_20_31, val02_13_20_31, 1));
     261        3980 :         return _mm_cvtss_f32(res);
     262             :     }
     263             : 
     264             :     inline float horizontalMul() const {
     265         160 :         const __m128 val02_13_20_31 = _mm_mul_ps(vec, _mm_movehl_ps(vec, vec));
     266         120 :         const __m128 res            = _mm_mul_ss(val02_13_20_31, _mm_shuffle_ps(val02_13_20_31, val02_13_20_31, 1));
     267          60 :         return _mm_cvtss_f32(res);
     268             :     }    
     269             : 
     270             :     inline float minInVec() const {
     271         480 :         const __m128 val02_13_20_31 = _mm_min_ps(vec, _mm_movehl_ps(vec, vec));
     272         320 :         const __m128 res            = _mm_min_ps(val02_13_20_31, _mm_shuffle_ps(val02_13_20_31, val02_13_20_31, 1));
     273         160 :         return _mm_cvtss_f32(res);
     274             :     }
     275             : 
     276             :     inline float maxInVec() const {
     277         480 :         const __m128 val02_13_20_31 = _mm_max_ps(vec, _mm_movehl_ps(vec, vec));
     278         320 :         const __m128 res            = _mm_max_ps(val02_13_20_31, _mm_shuffle_ps(val02_13_20_31, val02_13_20_31, 1));
     279         160 :         return _mm_cvtss_f32(res);
     280             :     }
     281             : 
     282             :     inline InaVecSSE3 sqrt() const {
     283          80 :         return _mm_sqrt_ps(vec);
     284             :     }
     285             : 
     286          34 :     inline InaVecSSE3 exp() const {
     287             : #ifdef __INTEL_COMPILER
     288             :         return _mm_exp_ps(vec);
     289             : #else
     290          34 :         const __m128 COEFF_LOG2E = _mm_set1_ps(float(InaFastExp::CoeffLog2E()));
     291          34 :         const __m128 COEFF_A     = _mm_set1_ps(float(InaFastExp::CoeffA32()));
     292          34 :         const __m128 COEFF_B     = _mm_set1_ps(float(InaFastExp::CoeffB32()));
     293          34 :         const __m128 COEFF_P5_A  = _mm_set1_ps(float(InaFastExp::GetCoefficient6_5()));
     294          34 :         const __m128 COEFF_P5_B  = _mm_set1_ps(float(InaFastExp::GetCoefficient6_4()));
     295          34 :         const __m128 COEFF_P5_C  = _mm_set1_ps(float(InaFastExp::GetCoefficient6_3()));
     296          34 :         const __m128 COEFF_P5_D  = _mm_set1_ps(float(InaFastExp::GetCoefficient6_2()));
     297          34 :         const __m128 COEFF_P5_E  = _mm_set1_ps(float(InaFastExp::GetCoefficient6_1()));
     298          34 :         const __m128 COEFF_P5_F  = _mm_set1_ps(float(InaFastExp::GetCoefficient6_0()));
     299             : 
     300          68 :         __m128 x = _mm_mul_ps( vec , COEFF_LOG2E);
     301             : 
     302          68 :         const __m128 fractional_part = _mm_sub_ps(x, InaVecSSE3(x).floor().vec);
     303             : 
     304         306 :         __m128 factor = _mm_add_ps(_mm_mul_ps(_mm_add_ps( _mm_mul_ps(_mm_add_ps(
     305             :                          _mm_mul_ps(_mm_add_ps( _mm_mul_ps(_mm_add_ps(_mm_mul_ps(
     306             :                          COEFF_P5_A, fractional_part), COEFF_P5_B), fractional_part), COEFF_P5_C),fractional_part),
     307          34 :                          COEFF_P5_D), fractional_part), COEFF_P5_E),fractional_part), COEFF_P5_F);
     308             : 
     309          34 :         x = _mm_sub_ps(x,factor);
     310             : 
     311         102 :         __m128i castedInteger = _mm_cvtps_epi32(_mm_add_ps(_mm_mul_ps(COEFF_A, x), COEFF_B));
     312             : 
     313          34 :         return _mm_castsi128_ps(castedInteger);
     314             : #endif
     315             :     }
     316             : 
     317          40 :     inline InaVecSSE3 expLowAcc() const {
     318          40 :         const __m128 COEFF_LOG2E = _mm_set1_ps(float(InaFastExp::CoeffLog2E()));
     319          40 :         const __m128 COEFF_A     = _mm_set1_ps(float(InaFastExp::CoeffA32()));
     320          40 :         const __m128 COEFF_B     = _mm_set1_ps(float(InaFastExp::CoeffB32()));
     321          40 :         const __m128 COEFF_P5_D  = _mm_set1_ps(float(InaFastExp::GetCoefficient3_2()));
     322          40 :         const __m128 COEFF_P5_E  = _mm_set1_ps(float(InaFastExp::GetCoefficient3_1()));
     323          40 :         const __m128 COEFF_P5_F  = _mm_set1_ps(float(InaFastExp::GetCoefficient3_0()));
     324             : 
     325          80 :         __m128 x = _mm_mul_ps( vec , COEFF_LOG2E);
     326             : 
     327          80 :         const __m128 fractional_part = _mm_sub_ps(x, InaVecSSE3(x).floor().vec);
     328             : 
     329         120 :         __m128 factor = _mm_add_ps(_mm_mul_ps(
     330             :                          _mm_add_ps(_mm_mul_ps(
     331             :                                          COEFF_P5_D, fractional_part),
     332             :                                          COEFF_P5_E), fractional_part),
     333          40 :                                          COEFF_P5_F);
     334             : 
     335          40 :         x = _mm_sub_ps(x,factor);
     336             : 
     337         120 :         __m128i castedInteger = _mm_cvtps_epi32(_mm_add_ps(_mm_mul_ps(COEFF_A, x), COEFF_B));
     338             : 
     339          40 :         return _mm_castsi128_ps(castedInteger);
     340             :     }
     341             : 
     342             :     inline InaVecSSE3 rsqrt() const {
     343          80 :         return _mm_set1_ps(1) / _mm_sqrt_ps(vec); // _mm_rsqrt_ps(val); not enough accurate
     344             :     }
     345             : 
     346             :     inline InaVecSSE3 abs() const {
     347          60 :         const __m128 minus0 = _mm_castsi128_ps(_mm_set1_epi32(static_cast<int>(0x80000000)));
     348         120 :         return _mm_andnot_ps(minus0, vec);
     349             :     }
     350             : 
     351         124 :     inline InaVecSSE3 floor() const {
     352             :         alignas(Alignement) float allval[GetVecLength()];
     353         248 :         _mm_store_ps(allval, vec);
     354         620 :         for (int idx = 0; idx < GetVecLength(); ++idx) {
     355         992 :             allval[idx] = std::floor(allval[idx]);
     356             :         }
     357         124 :         return _mm_loadu_ps(allval);
     358             :     }
     359             : 
     360             :     inline InaVecSSE3 signOf() const {
     361         100 :         const __m128 minus0 = _mm_castsi128_ps(_mm_set1_epi32(static_cast<int>(0x80000000)));
     362         200 :         const __m128 signs  = _mm_and_ps(vec, minus0);
     363         400 :         return _mm_andnot_ps(_mm_cmpeq_ps(_mm_setzero_ps(), vec), _mm_or_ps(signs, _mm_set1_ps(1)));
     364             :     }
     365             : 
     366             :     inline InaVecSSE3 isPositive() const {
     367         200 :         const __m128 greater = _mm_cmple_ps(_mm_setzero_ps(), vec);
     368         100 :         const __m128 ones    = _mm_set1_ps(1);
     369         100 :         return _mm_and_ps(greater, ones);
     370             :     }
     371             : 
     372             :     inline InaVecSSE3 isNegative() const {
     373         200 :         const __m128 less = _mm_cmpge_ps(_mm_setzero_ps(), vec);
     374         100 :         const __m128 ones = _mm_set1_ps(1);
     375         100 :         return _mm_and_ps(less, ones);
     376             :     }
     377             : 
     378             :     inline InaVecSSE3 isPositiveStrict() const {
     379         200 :         const __m128 greater = _mm_cmplt_ps(_mm_setzero_ps(), vec);
     380         100 :         const __m128 ones    = _mm_set1_ps(1);
     381         100 :         return _mm_and_ps(greater, ones);
     382             :     }
     383             : 
     384             :     inline InaVecSSE3 isNegativeStrict() const {
     385         200 :         const __m128 less = _mm_cmpgt_ps(_mm_setzero_ps(), vec);
     386         100 :         const __m128 ones = _mm_set1_ps(1);
     387         100 :         return _mm_and_ps(less, ones);
     388             :     }
     389             : 
     390             :     inline InaVecSSE3 isZero() const {
     391         120 :         const __m128 equalZero = _mm_cmpeq_ps(_mm_setzero_ps(), vec);
     392          60 :         const __m128 ones      = _mm_set1_ps(1);
     393          60 :         return _mm_and_ps(equalZero, ones);
     394             :     }
     395             : 
     396             :     inline InaVecSSE3 isNotZero() const {
     397         120 :         const __m128 equalZero = _mm_cmpeq_ps(_mm_setzero_ps(), vec);
     398          60 :         const __m128 ones      = _mm_set1_ps(1);
     399          60 :         return _mm_andnot_ps(equalZero, ones);
     400             :     }
     401             : 
     402             :     inline InaVecMaskSSE3<float> isPositiveMask() const {
     403         300 :         return _mm_castps_si128(_mm_cmple_ps(_mm_setzero_ps(), vec));
     404             :     }
     405             : 
     406             :     inline InaVecMaskSSE3<float> isNegativeMask() const {
     407         300 :         return _mm_castps_si128(_mm_cmpge_ps(_mm_setzero_ps(), vec));
     408             :     }
     409             : 
     410             :     inline InaVecMaskSSE3<float> isPositiveStrictMask() const {
     411         300 :         return _mm_castps_si128(_mm_cmplt_ps(_mm_setzero_ps(), vec));
     412             :     }
     413             : 
     414             :     inline InaVecMaskSSE3<float> isNegativeStrictMask() const {
     415         300 :         return _mm_castps_si128(_mm_cmpgt_ps(_mm_setzero_ps(), vec));
     416             :     }
     417             : 
     418             :     inline InaVecMaskSSE3<float> isZeroMask() const {
     419         240 :         return _mm_castps_si128(_mm_cmpeq_ps(_mm_setzero_ps(), vec));
     420             :     }
     421             : 
     422             :     inline InaVecMaskSSE3<float> isNotZeroMask() const {
     423         216 :         return _mm_castps_si128(_mm_cmpneq_ps(_mm_setzero_ps(), vec));
     424             :     }
     425             : 
     426             :     // Static basic methods
     427             :     inline static InaVecSSE3 GetZero() {
     428          80 :         return InaVecSSE3(_mm_setzero_ps());
     429             :     }
     430             : 
     431             :     inline static InaVecSSE3 GetOne() {
     432          20 :         return InaVecSSE3(_mm_set1_ps(1));
     433             :     }
     434             : 
     435             :     inline static InaVecSSE3 Min(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     436         120 :         return _mm_min_ps(inVec1.vec, inVec2.vec);
     437             :     }
     438             : 
     439             :     inline static InaVecSSE3 Max(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     440         120 :         return _mm_max_ps(inVec1.vec, inVec2.vec);
     441             :     }
     442             : 
     443             :     inline static InaVecSSE3 IsLowerOrEqual(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     444         160 :         const __m128 testResult = _mm_cmple_ps(inVec1.vec, inVec2.vec);
     445          80 :         const __m128 ones       = _mm_set1_ps(1);
     446          80 :         return _mm_and_ps(testResult, ones);
     447             :     }
     448             : 
     449             :     inline static InaVecSSE3 IsLower(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     450         160 :         const __m128 testResult = _mm_cmplt_ps(inVec1.vec, inVec2.vec);
     451          80 :         const __m128 ones       = _mm_set1_ps(1);
     452          80 :         return _mm_and_ps(testResult, ones);
     453             :     }
     454             : 
     455             :     inline static InaVecSSE3 IsGreaterOrEqual(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     456         160 :         const __m128 testResult = _mm_cmpge_ps(inVec1.vec, inVec2.vec);
     457          80 :         const __m128 ones       = _mm_set1_ps(1);
     458          80 :         return _mm_and_ps(testResult, ones);
     459             :     }
     460             : 
     461             :     inline static InaVecSSE3 IsGreater(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     462         160 :         const __m128 testResult = _mm_cmpgt_ps(inVec1.vec, inVec2.vec);
     463          80 :         const __m128 ones       = _mm_set1_ps(1);
     464          80 :         return _mm_and_ps(testResult, ones);
     465             :     }
     466             : 
     467             :     inline static InaVecSSE3 IsEqual(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     468         160 :         const __m128 testResult = _mm_cmpeq_ps(inVec1.vec, inVec2.vec);
     469          80 :         const __m128 ones       = _mm_set1_ps(1);
     470          80 :         return _mm_and_ps(testResult, ones);
     471             :     }
     472             : 
     473             :     inline static InaVecSSE3 IsNotEqual(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     474         160 :         const __m128 testResult = _mm_cmpneq_ps(inVec1.vec, inVec2.vec);
     475          80 :         const __m128 ones       = _mm_set1_ps(1);
     476          80 :         return _mm_and_ps(testResult, ones);
     477             :     }
     478             : 
     479             :     inline static InaVecMaskSSE3<float> IsLowerOrEqualMask(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     480         300 :         return _mm_castps_si128(_mm_cmple_ps(inVec1.vec, inVec2.vec));
     481             :     }
     482             : 
     483             :     inline static InaVecMaskSSE3<float> IsLowerMask(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     484         252 :         return _mm_castps_si128(_mm_cmplt_ps(inVec1.vec, inVec2.vec));
     485             :     }
     486             : 
     487             :     inline static InaVecMaskSSE3<float> IsGreaterOrEqualMask(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     488         288 :         return _mm_castps_si128(_mm_cmpge_ps(inVec1.vec, inVec2.vec));
     489             :     }
     490             : 
     491             :     inline static InaVecMaskSSE3<float> IsGreaterMask(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     492         240 :         return _mm_castps_si128(_mm_cmpgt_ps(inVec1.vec, inVec2.vec));
     493             :     }
     494             : 
     495             :     inline static InaVecMaskSSE3<float> IsEqualMask(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     496         548 :         return _mm_castps_si128(_mm_cmpeq_ps(inVec1.vec, inVec2.vec));
     497             :     }
     498             : 
     499             :     inline static InaVecMaskSSE3<float> IsNotEqualMask(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     500         372 :         return _mm_castps_si128(_mm_cmpneq_ps(inVec1.vec, inVec2.vec));
     501             :     }
     502             : 
     503             :     inline static InaVecSSE3 BitsAnd(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     504         120 :         return _mm_and_ps(inVec1.vec, inVec2.vec);
     505             :     }
     506             : 
     507             :     inline static InaVecSSE3 BitsNotAnd(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     508         160 :         return _mm_andnot_ps(inVec1.vec, inVec2.vec);
     509             :     }
     510             : 
     511             :     inline static InaVecSSE3 BitsOr(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     512         408 :         return _mm_or_ps(inVec1.vec, inVec2.vec);
     513             :     }
     514             : 
     515             :     inline static InaVecSSE3 BitsXor(const InaVecSSE3& inVec1, const InaVecSSE3& inVec2) {
     516         120 :         return _mm_xor_ps(inVec1.vec, inVec2.vec);
     517             :     }
     518             : 
     519             :     inline static  const char* GetName() {
     520             :         return "InaVecSSE3<float>";
     521             :     }
     522             : 
     523             :     inline static  InaIfElse< InaVecSSE3<float> >::ThenClass If(const InaVecMaskSSE3<float>& inTest) {
     524          30 :         return InaIfElse< InaVecSSE3<float> >::IfClass().If(inTest);
     525             :     }
     526             : 
     527             :     inline static InaVecSSE3 IfElse(const InaVecMaskSSE3<float>& inMask, const InaVecSSE3& inIfTrue, const InaVecSSE3& inIfFalse) {
     528          32 :         return _mm_or_ps(IfTrue(inMask, inIfTrue.vec).vec,
     529          64 :                       IfFalse(inMask, inIfFalse.vec).vec);
     530             :     }
     531             : 
     532             :     inline static InaVecSSE3 IfTrue(const InaVecMaskSSE3<float>& inMask, const InaVecSSE3& inIfTrue) {
     533        4256 :         return _mm_and_ps(_mm_castsi128_ps(inMask.getMask()), inIfTrue.vec);
     534             :     }
     535             : 
     536             :     inline static InaVecSSE3 IfFalse(const InaVecMaskSSE3<float>& inMask, const InaVecSSE3& inIfFalse) {
     537         356 :         return _mm_andnot_ps(_mm_castsi128_ps(inMask.getMask()), inIfFalse.vec);
     538             :     }
     539             : 
     540             :     // Inner operators
     541             :     inline InaVecSSE3<float>& operator+=(const InaVecSSE3<float>& inVec){
     542         104 :         vec = _mm_add_ps(vec,inVec.vec);
     543             :         return *this;
     544             :     }
     545             : 
     546             :     inline InaVecSSE3<float>& operator-=(const InaVecSSE3<float>& inVec){
     547          84 :         vec = _mm_sub_ps(vec,inVec.vec);
     548             :         return *this;
     549             :     }
     550             : 
     551             :     inline InaVecSSE3<float>& operator/=(const InaVecSSE3<float>& inVec){
     552          44 :         vec = _mm_div_ps(vec,inVec.vec);
     553             :         return *this;
     554             :     }
     555             : 
     556             :     inline InaVecSSE3<float>& operator*=(const InaVecSSE3<float>& inVec){
     557         564 :         vec = _mm_mul_ps(vec,inVec.vec);
     558             :         return *this;
     559             :     }
     560             : 
     561             :     inline InaVecSSE3<float> operator-() const {
     562          80 :         const __m128 minus0 = _mm_castsi128_ps(_mm_set1_epi32(static_cast<int>(0x80000000)));
     563         160 :         return _mm_xor_ps(vec, minus0);
     564             :     }
     565             : 
     566             :     inline InaVecSSE3<float> pow(std::size_t power) const{
     567         120 :         return InaUtils::FastPow<InaVecSSE3<float>>(*this, power);
     568             :     }
     569             : 
     570             :     // Multiple sum
     571             :     template <class ... Args>
     572           4 :     inline static void MultiHorizontalSum(float sumRes[], const InaVecSSE3<float>& inVec1,
     573             :                                           const InaVecSSE3<float>& inVec2, const InaVecSSE3<float>& inVec3,
     574             :                                           const InaVecSSE3<float>& inVec4, Args ...args){
     575         152 :         const __m128 val_a01_a23_b01_b23 = _mm_hadd_ps(inVec1.vec, inVec2.vec);
     576         152 :         const __m128 val_c01_c23_d01_d23 = _mm_hadd_ps(inVec3.vec, inVec4.vec);
     577             : 
     578          76 :         const __m128 val_suma_sumb_sumc_sumd = _mm_hadd_ps(val_a01_a23_b01_b23, val_c01_c23_d01_d23);
     579             : 
     580          76 :         __m128 vecBuffer = _mm_loadu_ps(sumRes);
     581          76 :         vecBuffer += val_suma_sumb_sumc_sumd;
     582          76 :         _mm_storeu_ps(sumRes, vecBuffer);
     583             : 
     584         100 :         MultiHorizontalSum(&sumRes[4], args... );
     585           4 :     }
     586             : 
     587             :     template <class ... Args>
     588        1188 :     inline static void MultiHorizontalSum(float sumRes[], const InaVecSSE3<float>& inVec1,
     589             :                                           const InaVecSSE3<float>& inVec2, Args ...args){
     590        3136 :         const __m128 val_a01_a23_b01_b23 = _mm_hadd_ps(inVec1.vec, inVec2.vec);
     591        1568 :         const __m128 val_a23_a01_b23_b01 = _mm_shuffle_ps(val_a01_a23_b01_b23, val_a01_a23_b01_b23, 0xB1);// 10.11.00.01
     592             : 
     593        1568 :         const __m128 val_suma_x_sumb_x = _mm_add_ps(val_a01_a23_b01_b23, val_a23_a01_b23_b01);
     594             : 
     595        1568 :         alignas(Alignement) float buffer[GetVecLength()] = {0};
     596        1568 :         buffer[0] = sumRes[0];
     597        1568 :         buffer[2] = sumRes[1];
     598        1568 :         __m128 vecBuffer = _mm_load_ps(buffer);
     599        1568 :         vecBuffer += val_suma_x_sumb_x;
     600        1568 :         _mm_store_ps(buffer, vecBuffer);
     601        1568 :         sumRes[0] = buffer[0];
     602        1568 :         sumRes[1] = buffer[2];
     603             : 
     604        1758 :         MultiHorizontalSum(&sumRes[2], args... );
     605        1188 :     }
     606             : 
     607             :     inline static void MultiHorizontalSum(float sumRes[], const InaVecSSE3<float>& inVec){
     608         240 :         sumRes[0] += inVec.horizontalSum();
     609             :     }
     610             : 
     611             :     inline static void MultiHorizontalSum(float /*sumRes*/[]){
     612             :     }
     613             : 
     614             :     inline static InaVecSSE3<float> Fma(const InaVecSSE3<float>& inValAdd, const InaVecSSE3<float>& inValMul1, const InaVecSSE3<float>& inValMul2){
     615             : #ifdef __FMA__
     616             :         return _mm_fmadd_ps(inValMul1.vec, inValMul2.vec, inValAdd.vec);
     617             : #else
     618         148 :         return _mm_add_ps(inValAdd.vec, _mm_mul_ps(inValMul1.vec,inValMul2.vec));
     619             : #endif
     620             :     }
     621             : };
     622             : 
     623             : // Bits operators
     624             : inline InaVecSSE3<float> operator&(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     625             :     return InaVecSSE3<float>::BitsAnd(inVec1, inVec2);
     626             : }
     627             : 
     628             : inline InaVecSSE3<float> operator|(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     629             :     return InaVecSSE3<float>::BitsOr(inVec1, inVec2);
     630             : }
     631             : 
     632             : inline InaVecSSE3<float> operator^(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     633             :     return InaVecSSE3<float>::BitsXor(inVec1, inVec2);
     634             : }
     635             : 
     636             : // Dual operators
     637             : inline InaVecSSE3<float> operator+(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     638          92 :     return _mm_add_ps(inVec1.getVec(), inVec2.getVec());
     639             : }
     640             : 
     641             : inline InaVecSSE3<float> operator-(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     642          92 :     return _mm_sub_ps(inVec1.getVec(), inVec2.getVec());
     643             : }
     644             : 
     645             : inline InaVecSSE3<float> operator/(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     646          52 :     return _mm_div_ps(inVec1.getVec(), inVec2.getVec());
     647             : }
     648             : 
     649             : inline InaVecSSE3<float> operator*(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     650         172 :     return _mm_mul_ps(inVec1.getVec(), inVec2.getVec());
     651             : }
     652             : 
     653             : // Tests and comparions
     654             : inline InaVecMaskSSE3<float> operator<(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     655           4 :     return InaVecSSE3<float>::IsLowerMask(inVec1,inVec2);
     656             : }
     657             : 
     658             : inline InaVecMaskSSE3<float> operator<=(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     659          16 :     return InaVecSSE3<float>::IsLowerOrEqualMask(inVec1,inVec2);
     660             : }
     661             : 
     662             : inline InaVecMaskSSE3<float> operator>(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     663             :     return InaVecSSE3<float>::IsGreaterMask(inVec1,inVec2);
     664             : }
     665             : 
     666             : inline InaVecMaskSSE3<float> operator>=(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     667           8 :     return InaVecSSE3<float>::IsGreaterOrEqualMask(inVec1,inVec2);
     668             : }
     669             : 
     670             : inline InaVecMaskSSE3<float> operator==(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     671         100 :     return InaVecSSE3<float>::IsEqualMask(inVec1,inVec2);
     672             : }
     673             : 
     674             : inline InaVecMaskSSE3<float> operator!=(const InaVecSSE3<float>& inVec1, const InaVecSSE3<float>& inVec2){
     675          44 :     return InaVecSSE3<float>::IsNotEqualMask(inVec1,inVec2);
     676             : }
     677             : 
     678             : 
     679             : 
     680             : #endif

Generated by: LCOV version 1.13