30#ifndef GDALSSE_PRIV_H_INCLUDED
31#define GDALSSE_PRIV_H_INCLUDED
39#if (defined(__x86_64) || defined(_M_X64)) && !defined(USE_SSE2_EMULATION)
49#include "gdal_priv_templates.hpp"
51static inline __m128i GDALCopyInt16ToXMM(
const void *ptr)
53#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
56 return _mm_cvtsi32_si128(s);
58 return _mm_cvtsi32_si128(*
static_cast<const unsigned short *
>(ptr));
62static inline __m128i GDALCopyInt32ToXMM(
const void *ptr)
64#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
67 return _mm_cvtsi32_si128(i);
69 return _mm_cvtsi32_si128(*
static_cast<const GInt32 *
>(ptr));
73static inline __m128i GDALCopyInt64ToXMM(
const void *ptr)
75#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
78 return _mm_cvtsi64_si128(i);
80 return _mm_cvtsi64_si128(*
static_cast<const GInt64 *
>(ptr));
84static inline void GDALCopyXMMToInt16(
const __m128i xmm,
void *pDest)
86#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
87 GInt16 i =
static_cast<GInt16>(_mm_extract_epi16(xmm, 0));
90 *
static_cast<GInt16 *
>(pDest) =
91 static_cast<GInt16>(_mm_extract_epi16(xmm, 0));
101#pragma GCC diagnostic push
102#pragma GCC diagnostic ignored "-Weffc++"
105 XMMReg2Double() =
default;
107#pragma GCC diagnostic pop
110 XMMReg2Double(
double val) : xmm(_mm_load_sd(&val))
113 XMMReg2Double(
const XMMReg2Double &other) : xmm(other.xmm)
117 static inline XMMReg2Double Zero()
124 static inline XMMReg2Double Load1ValHighAndLow(
const double *ptr)
127 reg.nsLoad1ValHighAndLow(ptr);
131 static inline XMMReg2Double Load2Val(
const double *ptr)
138 static inline XMMReg2Double Load2Val(
const float *ptr)
145 static inline XMMReg2Double Load2ValAligned(
const double *ptr)
148 reg.nsLoad2ValAligned(ptr);
152 static inline XMMReg2Double Load2Val(
const unsigned char *ptr)
159 static inline XMMReg2Double Load2Val(
const short *ptr)
166 static inline XMMReg2Double Load2Val(
const unsigned short *ptr)
173 static inline XMMReg2Double Equals(
const XMMReg2Double &expr1,
174 const XMMReg2Double &expr2)
177 reg.xmm = _mm_cmpeq_pd(expr1.xmm, expr2.xmm);
181 static inline XMMReg2Double NotEquals(
const XMMReg2Double &expr1,
182 const XMMReg2Double &expr2)
185 reg.xmm = _mm_cmpneq_pd(expr1.xmm, expr2.xmm);
189 static inline XMMReg2Double Greater(
const XMMReg2Double &expr1,
190 const XMMReg2Double &expr2)
193 reg.xmm = _mm_cmpgt_pd(expr1.xmm, expr2.xmm);
197 static inline XMMReg2Double And(
const XMMReg2Double &expr1,
198 const XMMReg2Double &expr2)
201 reg.xmm = _mm_and_pd(expr1.xmm, expr2.xmm);
205 static inline XMMReg2Double Ternary(
const XMMReg2Double &cond,
206 const XMMReg2Double &true_expr,
207 const XMMReg2Double &false_expr)
210 reg.xmm = _mm_or_pd(_mm_and_pd(cond.xmm, true_expr.xmm),
211 _mm_andnot_pd(cond.xmm, false_expr.xmm));
215 static inline XMMReg2Double Min(
const XMMReg2Double &expr1,
216 const XMMReg2Double &expr2)
219 reg.xmm = _mm_min_pd(expr1.xmm, expr2.xmm);
223 inline void nsLoad1ValHighAndLow(
const double *ptr)
225 xmm = _mm_load1_pd(ptr);
228 inline void nsLoad2Val(
const double *ptr)
230 xmm = _mm_loadu_pd(ptr);
233 inline void nsLoad2ValAligned(
const double *ptr)
235 xmm = _mm_load_pd(ptr);
238 inline void nsLoad2Val(
const float *ptr)
240 xmm = _mm_cvtps_pd(_mm_castsi128_ps(GDALCopyInt64ToXMM(ptr)));
243 inline void nsLoad2Val(
const unsigned char *ptr)
245 __m128i xmm_i = GDALCopyInt16ToXMM(ptr);
247 xmm_i = _mm_cvtepu8_epi32(xmm_i);
249 xmm_i = _mm_unpacklo_epi8(xmm_i, _mm_setzero_si128());
250 xmm_i = _mm_unpacklo_epi16(xmm_i, _mm_setzero_si128());
252 xmm = _mm_cvtepi32_pd(xmm_i);
255 inline void nsLoad2Val(
const short *ptr)
257 __m128i xmm_i = GDALCopyInt32ToXMM(ptr);
259 xmm_i = _mm_cvtepi16_epi32(xmm_i);
261 xmm_i = _mm_unpacklo_epi16(
263 xmm_i = _mm_srai_epi32(
266 xmm = _mm_cvtepi32_pd(xmm_i);
269 inline void nsLoad2Val(
const unsigned short *ptr)
271 __m128i xmm_i = GDALCopyInt32ToXMM(ptr);
273 xmm_i = _mm_cvtepu16_epi32(xmm_i);
275 xmm_i = _mm_unpacklo_epi16(
277 _mm_setzero_si128());
279 xmm = _mm_cvtepi32_pd(xmm_i);
282 static inline void Load4Val(
const unsigned char *ptr, XMMReg2Double &low,
285 __m128i xmm_i = GDALCopyInt32ToXMM(ptr);
287 xmm_i = _mm_cvtepu8_epi32(xmm_i);
289 xmm_i = _mm_unpacklo_epi8(xmm_i, _mm_setzero_si128());
290 xmm_i = _mm_unpacklo_epi16(xmm_i, _mm_setzero_si128());
292 low.xmm = _mm_cvtepi32_pd(xmm_i);
294 _mm_cvtepi32_pd(_mm_shuffle_epi32(xmm_i, _MM_SHUFFLE(3, 2, 3, 2)));
297 static inline void Load4Val(
const short *ptr, XMMReg2Double &low,
301 high.nsLoad2Val(ptr + 2);
304 static inline void Load4Val(
const unsigned short *ptr, XMMReg2Double &low,
308 high.nsLoad2Val(ptr + 2);
311 static inline void Load4Val(
const double *ptr, XMMReg2Double &low,
315 high.nsLoad2Val(ptr + 2);
318 static inline void Load4Val(
const float *ptr, XMMReg2Double &low,
321 __m128 temp1 = _mm_loadu_ps(ptr);
322 __m128 temp2 = _mm_shuffle_ps(temp1, temp1, _MM_SHUFFLE(3, 2, 3, 2));
323 low.xmm = _mm_cvtps_pd(temp1);
324 high.xmm = _mm_cvtps_pd(temp2);
327 inline void Zeroize()
329 xmm = _mm_setzero_pd();
332 inline XMMReg2Double &operator=(
const XMMReg2Double &other)
338 inline XMMReg2Double &operator+=(
const XMMReg2Double &other)
340 xmm = _mm_add_pd(xmm, other.xmm);
344 inline XMMReg2Double &operator*=(
const XMMReg2Double &other)
346 xmm = _mm_mul_pd(xmm, other.xmm);
350 inline XMMReg2Double operator+(
const XMMReg2Double &other)
const
353 ret.xmm = _mm_add_pd(xmm, other.xmm);
357 inline XMMReg2Double operator-(
const XMMReg2Double &other)
const
360 ret.xmm = _mm_sub_pd(xmm, other.xmm);
364 inline XMMReg2Double operator*(
const XMMReg2Double &other)
const
367 ret.xmm = _mm_mul_pd(xmm, other.xmm);
371 inline XMMReg2Double operator/(
const XMMReg2Double &other)
const
374 ret.xmm = _mm_div_pd(xmm, other.xmm);
378 inline double GetHorizSum()
const
381 xmm2 = _mm_shuffle_pd(
384 return _mm_cvtsd_f64(_mm_add_sd(xmm, xmm2));
387 inline void Store2Val(
double *ptr)
const
389 _mm_storeu_pd(ptr, xmm);
392 inline void Store2ValAligned(
double *ptr)
const
394 _mm_store_pd(ptr, xmm);
397 inline void Store2Val(
float *ptr)
const
399 __m128i xmm_i = _mm_castps_si128(_mm_cvtpd_ps(xmm));
400 GDALCopyXMMToInt64(xmm_i,
reinterpret_cast<GInt64 *
>(ptr));
403 inline void Store2Val(
unsigned char *ptr)
const
405 __m128i tmp = _mm_cvttpd_epi32(_mm_add_pd(
408 tmp = _mm_packs_epi32(tmp, tmp);
409 tmp = _mm_packus_epi16(tmp, tmp);
410 GDALCopyXMMToInt16(tmp,
reinterpret_cast<GInt16 *
>(ptr));
413 inline void Store2Val(
unsigned short *ptr)
const
415 __m128i tmp = _mm_cvttpd_epi32(_mm_add_pd(
419 tmp = _mm_shufflelo_epi16(tmp, 0 | (2 << 2));
420 GDALCopyXMMToInt32(tmp,
reinterpret_cast<GInt32 *
>(ptr));
423 inline void StoreMask(
unsigned char *ptr)
const
425 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(ptr),
426 _mm_castpd_si128(xmm));
429 inline operator double()
const
431 return _mm_cvtsd_f64(xmm);
437#ifndef NO_WARN_USE_SSE2_EMULATION
438#warning "Software emulation of SSE2 !"
450 XMMReg2Double(
double val)
455 XMMReg2Double(
const XMMReg2Double &other) : low(other.low), high(other.high)
459 static inline XMMReg2Double Zero()
466 static inline XMMReg2Double Load1ValHighAndLow(
const double *ptr)
469 reg.nsLoad1ValHighAndLow(ptr);
473 static inline XMMReg2Double Equals(
const XMMReg2Double &expr1,
474 const XMMReg2Double &expr2)
478 if (expr1.low == expr2.low)
479 memset(&(reg.low), 0xFF,
sizeof(
double));
483 if (expr1.high == expr2.high)
484 memset(&(reg.high), 0xFF,
sizeof(
double));
491 static inline XMMReg2Double NotEquals(
const XMMReg2Double &expr1,
492 const XMMReg2Double &expr2)
496 if (expr1.low != expr2.low)
497 memset(&(reg.low), 0xFF,
sizeof(
double));
501 if (expr1.high != expr2.high)
502 memset(&(reg.high), 0xFF,
sizeof(
double));
509 static inline XMMReg2Double Greater(
const XMMReg2Double &expr1,
510 const XMMReg2Double &expr2)
514 if (expr1.low > expr2.low)
515 memset(&(reg.low), 0xFF,
sizeof(
double));
519 if (expr1.high > expr2.high)
520 memset(&(reg.high), 0xFF,
sizeof(
double));
527 static inline XMMReg2Double And(
const XMMReg2Double &expr1,
528 const XMMReg2Double &expr2)
531 int low1[2], high1[2];
532 int low2[2], high2[2];
533 memcpy(low1, &expr1.low,
sizeof(
double));
534 memcpy(high1, &expr1.high,
sizeof(
double));
535 memcpy(low2, &expr2.low,
sizeof(
double));
536 memcpy(high2, &expr2.high,
sizeof(
double));
539 high1[0] &= high2[0];
540 high1[1] &= high2[1];
541 memcpy(®.low, low1,
sizeof(
double));
542 memcpy(®.high, high1,
sizeof(
double));
546 static inline XMMReg2Double Ternary(
const XMMReg2Double &cond,
547 const XMMReg2Double &true_expr,
548 const XMMReg2Double &false_expr)
552 reg.low = true_expr.low;
554 reg.low = false_expr.low;
556 reg.high = true_expr.high;
558 reg.high = false_expr.high;
562 static inline XMMReg2Double Min(
const XMMReg2Double &expr1,
563 const XMMReg2Double &expr2)
566 reg.low = (expr1.low < expr2.low) ? expr1.low : expr2.low;
567 reg.high = (expr1.high < expr2.high) ? expr1.high : expr2.high;
571 static inline XMMReg2Double Load2Val(
const double *ptr)
578 static inline XMMReg2Double Load2ValAligned(
const double *ptr)
581 reg.nsLoad2ValAligned(ptr);
585 static inline XMMReg2Double Load2Val(
const float *ptr)
592 static inline XMMReg2Double Load2Val(
const unsigned char *ptr)
599 static inline XMMReg2Double Load2Val(
const short *ptr)
606 static inline XMMReg2Double Load2Val(
const unsigned short *ptr)
613 inline void nsLoad1ValHighAndLow(
const double *ptr)
619 inline void nsLoad2Val(
const double *ptr)
625 inline void nsLoad2ValAligned(
const double *ptr)
631 inline void nsLoad2Val(
const float *ptr)
637 inline void nsLoad2Val(
const unsigned char *ptr)
643 inline void nsLoad2Val(
const short *ptr)
649 inline void nsLoad2Val(
const unsigned short *ptr)
655 static inline void Load4Val(
const unsigned char *ptr, XMMReg2Double &low,
664 static inline void Load4Val(
const short *ptr, XMMReg2Double &low,
668 high.nsLoad2Val(ptr + 2);
671 static inline void Load4Val(
const unsigned short *ptr, XMMReg2Double &low,
675 high.nsLoad2Val(ptr + 2);
678 static inline void Load4Val(
const double *ptr, XMMReg2Double &low,
682 high.nsLoad2Val(ptr + 2);
685 static inline void Load4Val(
const float *ptr, XMMReg2Double &low,
689 high.nsLoad2Val(ptr + 2);
692 inline void Zeroize()
698 inline XMMReg2Double &operator=(
const XMMReg2Double &other)
705 inline XMMReg2Double &operator+=(
const XMMReg2Double &other)
712 inline XMMReg2Double &operator*=(
const XMMReg2Double &other)
719 inline XMMReg2Double operator+(
const XMMReg2Double &other)
const
722 ret.low = low + other.low;
723 ret.high = high + other.high;
727 inline XMMReg2Double operator-(
const XMMReg2Double &other)
const
730 ret.low = low - other.low;
731 ret.high = high - other.high;
735 inline XMMReg2Double operator*(
const XMMReg2Double &other)
const
738 ret.low = low * other.low;
739 ret.high = high * other.high;
743 inline XMMReg2Double operator/(
const XMMReg2Double &other)
const
746 ret.low = low / other.low;
747 ret.high = high / other.high;
751 inline double GetHorizSum()
const
756 inline void Store2Val(
double *ptr)
const
762 inline void Store2ValAligned(
double *ptr)
const
768 inline void Store2Val(
float *ptr)
const
770 ptr[0] =
static_cast<float>(low);
771 ptr[1] =
static_cast<float>(high);
774 void Store2Val(
unsigned char *ptr)
const
776 ptr[0] = (
unsigned char)(low + 0.5);
777 ptr[1] = (
unsigned char)(high + 0.5);
780 void Store2Val(
unsigned short *ptr)
const
783 ptr[1] = (
GUInt16)(high + 0.5);
786 inline void StoreMask(
unsigned char *ptr)
const
788 memcpy(ptr, &low, 8);
789 memcpy(ptr + 8, &high, 8);
792 inline operator double()
const
800#if defined(__AVX__) && !defined(USE_SSE2_EMULATION)
802#include <immintrin.h>
809 XMMReg4Double() : ymm(_mm256_setzero_pd())
812 XMMReg4Double(
const XMMReg4Double &other) : ymm(other.ymm)
816 static inline XMMReg4Double Zero()
823 inline void Zeroize()
825 ymm = _mm256_setzero_pd();
828 static inline XMMReg4Double Load1ValHighAndLow(
const double *ptr)
831 reg.nsLoad1ValHighAndLow(ptr);
835 inline void nsLoad1ValHighAndLow(
const double *ptr)
837 ymm = _mm256_set1_pd(*ptr);
840 static inline XMMReg4Double Load4Val(
const unsigned char *ptr)
847 inline void nsLoad4Val(
const unsigned char *ptr)
849 __m128i xmm_i = GDALCopyInt32ToXMM(ptr);
850 xmm_i = _mm_cvtepu8_epi32(xmm_i);
851 ymm = _mm256_cvtepi32_pd(xmm_i);
854 static inline XMMReg4Double Load4Val(
const short *ptr)
861 inline void nsLoad4Val(
const short *ptr)
863 __m128i xmm_i = GDALCopyInt64ToXMM(ptr);
864 xmm_i = _mm_cvtepi16_epi32(xmm_i);
865 ymm = _mm256_cvtepi32_pd(xmm_i);
868 static inline XMMReg4Double Load4Val(
const unsigned short *ptr)
875 inline void nsLoad4Val(
const unsigned short *ptr)
877 __m128i xmm_i = GDALCopyInt64ToXMM(ptr);
878 xmm_i = _mm_cvtepu16_epi32(xmm_i);
879 ymm = _mm256_cvtepi32_pd(
884 static inline XMMReg4Double Load4Val(
const double *ptr)
891 inline void nsLoad4Val(
const double *ptr)
893 ymm = _mm256_loadu_pd(ptr);
896 static inline XMMReg4Double Load4ValAligned(
const double *ptr)
899 reg.nsLoad4ValAligned(ptr);
903 inline void nsLoad4ValAligned(
const double *ptr)
905 ymm = _mm256_load_pd(ptr);
908 static inline XMMReg4Double Load4Val(
const float *ptr)
915 inline void nsLoad4Val(
const float *ptr)
917 ymm = _mm256_cvtps_pd(_mm_loadu_ps(ptr));
920 static inline XMMReg4Double Equals(
const XMMReg4Double &expr1,
921 const XMMReg4Double &expr2)
924 reg.ymm = _mm256_cmp_pd(expr1.ymm, expr2.ymm, _CMP_EQ_OQ);
928 static inline XMMReg4Double NotEquals(
const XMMReg4Double &expr1,
929 const XMMReg4Double &expr2)
932 reg.ymm = _mm256_cmp_pd(expr1.ymm, expr2.ymm, _CMP_NEQ_OQ);
936 static inline XMMReg4Double Greater(
const XMMReg4Double &expr1,
937 const XMMReg4Double &expr2)
940 reg.ymm = _mm256_cmp_pd(expr1.ymm, expr2.ymm, _CMP_GT_OQ);
944 static inline XMMReg4Double And(
const XMMReg4Double &expr1,
945 const XMMReg4Double &expr2)
948 reg.ymm = _mm256_and_pd(expr1.ymm, expr2.ymm);
952 static inline XMMReg4Double Ternary(
const XMMReg4Double &cond,
953 const XMMReg4Double &true_expr,
954 const XMMReg4Double &false_expr)
957 reg.ymm = _mm256_or_pd(_mm256_and_pd(cond.ymm, true_expr.ymm),
958 _mm256_andnot_pd(cond.ymm, false_expr.ymm));
962 static inline XMMReg4Double Min(
const XMMReg4Double &expr1,
963 const XMMReg4Double &expr2)
966 reg.ymm = _mm256_min_pd(expr1.ymm, expr2.ymm);
970 inline XMMReg4Double &operator=(
const XMMReg4Double &other)
976 inline XMMReg4Double &operator+=(
const XMMReg4Double &other)
978 ymm = _mm256_add_pd(ymm, other.ymm);
982 inline XMMReg4Double &operator*=(
const XMMReg4Double &other)
984 ymm = _mm256_mul_pd(ymm, other.ymm);
988 inline XMMReg4Double operator+(
const XMMReg4Double &other)
const
991 ret.ymm = _mm256_add_pd(ymm, other.ymm);
995 inline XMMReg4Double operator-(
const XMMReg4Double &other)
const
998 ret.ymm = _mm256_sub_pd(ymm, other.ymm);
1002 inline XMMReg4Double operator*(
const XMMReg4Double &other)
const
1005 ret.ymm = _mm256_mul_pd(ymm, other.ymm);
1009 inline XMMReg4Double operator/(
const XMMReg4Double &other)
const
1012 ret.ymm = _mm256_div_pd(ymm, other.ymm);
1016 void AddToLow(
const XMMReg2Double &other)
1018 __m256d ymm2 = _mm256_setzero_pd();
1019 ymm2 = _mm256_insertf128_pd(ymm2, other.xmm, 0);
1020 ymm = _mm256_add_pd(ymm, ymm2);
1023 inline double GetHorizSum()
const
1025 __m256d ymm_tmp1, ymm_tmp2;
1026 ymm_tmp2 = _mm256_hadd_pd(ymm, ymm);
1027 ymm_tmp1 = _mm256_permute2f128_pd(ymm_tmp2, ymm_tmp2, 1);
1028 ymm_tmp1 = _mm256_add_pd(ymm_tmp1, ymm_tmp2);
1029 return _mm_cvtsd_f64(_mm256_castpd256_pd128(ymm_tmp1));
1032 inline void Store4Val(
unsigned char *ptr)
const
1035 _mm256_cvttpd_epi32(_mm256_add_pd(ymm, _mm256_set1_pd(0.5)));
1039 _mm_shuffle_epi8(xmm_i, _mm_cvtsi32_si128(0 | (4 << 8) | (8 << 16) |
1041 GDALCopyXMMToInt32(xmm_i,
reinterpret_cast<GInt32 *
>(ptr));
1044 inline void Store4Val(
unsigned short *ptr)
const
1047 _mm256_cvttpd_epi32(_mm256_add_pd(ymm, _mm256_set1_pd(0.5)));
1048 xmm_i = _mm_packus_epi32(xmm_i, xmm_i);
1049 GDALCopyXMMToInt64(xmm_i,
reinterpret_cast<GInt64 *
>(ptr));
1052 inline void Store4Val(
float *ptr)
const
1054 _mm_storeu_ps(ptr, _mm256_cvtpd_ps(ymm));
1057 inline void Store4Val(
double *ptr)
const
1059 _mm256_storeu_pd(ptr, ymm);
1062 inline void StoreMask(
unsigned char *ptr)
const
1064 _mm256_storeu_si256(
reinterpret_cast<__m256i *
>(ptr),
1065 _mm256_castpd_si256(ymm));
1074 XMMReg2Double low, high;
1076#if defined(__GNUC__)
1077#pragma GCC diagnostic push
1078#pragma GCC diagnostic ignored "-Weffc++"
1081 XMMReg4Double() =
default;
1082#if defined(__GNUC__)
1083#pragma GCC diagnostic pop
1086 XMMReg4Double(
const XMMReg4Double &other) : low(other.low), high(other.high)
1090 static inline XMMReg4Double Zero()
1098 static inline XMMReg4Double Load1ValHighAndLow(
const double *ptr)
1101 reg.low.nsLoad1ValHighAndLow(ptr);
1106 static inline XMMReg4Double Load4Val(
const unsigned char *ptr)
1109 XMMReg2Double::Load4Val(ptr, reg.low, reg.high);
1113 static inline XMMReg4Double Load4Val(
const short *ptr)
1116 reg.low.nsLoad2Val(ptr);
1117 reg.high.nsLoad2Val(ptr + 2);
1121 static inline XMMReg4Double Load4Val(
const unsigned short *ptr)
1124 reg.low.nsLoad2Val(ptr);
1125 reg.high.nsLoad2Val(ptr + 2);
1129 static inline XMMReg4Double Load4Val(
const double *ptr)
1132 reg.low.nsLoad2Val(ptr);
1133 reg.high.nsLoad2Val(ptr + 2);
1137 static inline XMMReg4Double Load4ValAligned(
const double *ptr)
1140 reg.low.nsLoad2ValAligned(ptr);
1141 reg.high.nsLoad2ValAligned(ptr + 2);
1145 static inline XMMReg4Double Load4Val(
const float *ptr)
1148 XMMReg2Double::Load4Val(ptr, reg.low, reg.high);
1152 static inline XMMReg4Double Equals(
const XMMReg4Double &expr1,
1153 const XMMReg4Double &expr2)
1156 reg.low = XMMReg2Double::Equals(expr1.low, expr2.low);
1157 reg.high = XMMReg2Double::Equals(expr1.high, expr2.high);
1161 static inline XMMReg4Double NotEquals(
const XMMReg4Double &expr1,
1162 const XMMReg4Double &expr2)
1165 reg.low = XMMReg2Double::NotEquals(expr1.low, expr2.low);
1166 reg.high = XMMReg2Double::NotEquals(expr1.high, expr2.high);
1170 static inline XMMReg4Double Greater(
const XMMReg4Double &expr1,
1171 const XMMReg4Double &expr2)
1174 reg.low = XMMReg2Double::Greater(expr1.low, expr2.low);
1175 reg.high = XMMReg2Double::Greater(expr1.high, expr2.high);
1179 static inline XMMReg4Double And(
const XMMReg4Double &expr1,
1180 const XMMReg4Double &expr2)
1183 reg.low = XMMReg2Double::And(expr1.low, expr2.low);
1184 reg.high = XMMReg2Double::And(expr1.high, expr2.high);
1188 static inline XMMReg4Double Ternary(
const XMMReg4Double &cond,
1189 const XMMReg4Double &true_expr,
1190 const XMMReg4Double &false_expr)
1194 XMMReg2Double::Ternary(cond.low, true_expr.low, false_expr.low);
1196 XMMReg2Double::Ternary(cond.high, true_expr.high, false_expr.high);
1200 static inline XMMReg4Double Min(
const XMMReg4Double &expr1,
1201 const XMMReg4Double &expr2)
1204 reg.low = XMMReg2Double::Min(expr1.low, expr2.low);
1205 reg.high = XMMReg2Double::Min(expr1.high, expr2.high);
1209 inline XMMReg4Double &operator=(
const XMMReg4Double &other)
1216 inline XMMReg4Double &operator+=(
const XMMReg4Double &other)
1223 inline XMMReg4Double &operator*=(
const XMMReg4Double &other)
1230 inline XMMReg4Double operator+(
const XMMReg4Double &other)
const
1233 ret.low = low + other.low;
1234 ret.high = high + other.high;
1238 inline XMMReg4Double operator-(
const XMMReg4Double &other)
const
1241 ret.low = low - other.low;
1242 ret.high = high - other.high;
1246 inline XMMReg4Double operator*(
const XMMReg4Double &other)
const
1249 ret.low = low * other.low;
1250 ret.high = high * other.high;
1254 inline XMMReg4Double operator/(
const XMMReg4Double &other)
const
1257 ret.low = low / other.low;
1258 ret.high = high / other.high;
1262 void AddToLow(
const XMMReg2Double &other)
1267 inline double GetHorizSum()
const
1269 return (low + high).GetHorizSum();
1272 inline void Store4Val(
unsigned char *ptr)
const
1274#ifdef USE_SSE2_EMULATION
1276 high.Store2Val(ptr + 2);
1278 __m128i tmpLow = _mm_cvttpd_epi32(_mm_add_pd(
1281 __m128i tmpHigh = _mm_cvttpd_epi32(_mm_add_pd(
1284 auto tmp = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(tmpLow),
1285 _mm_castsi128_ps(tmpHigh),
1286 _MM_SHUFFLE(1, 0, 1, 0)));
1287 tmp = _mm_packs_epi32(tmp, tmp);
1288 tmp = _mm_packus_epi16(tmp, tmp);
1289 GDALCopyXMMToInt32(tmp,
reinterpret_cast<GInt32 *
>(ptr));
1293 inline void Store4Val(
unsigned short *ptr)
const
1297 high.Store2Val(ptr + 2);
1299 __m128i xmm0 = _mm_cvtpd_epi32(low.xmm);
1300 __m128i xmm1 = _mm_cvtpd_epi32(high.xmm);
1301 xmm0 = _mm_or_si128(xmm0, _mm_slli_si128(xmm1, 8));
1303 xmm0 = _mm_packus_epi32(xmm0, xmm0);
1305 xmm0 = _mm_add_epi32(xmm0, _mm_set1_epi32(-32768));
1306 xmm0 = _mm_packs_epi32(xmm0, xmm0);
1307 xmm0 = _mm_sub_epi16(xmm0, _mm_set1_epi16(-32768));
1309 GDALCopyXMMToInt64(xmm0, (
GInt64 *)ptr);
1313 inline void Store4Val(
float *ptr)
const
1316 high.Store2Val(ptr + 2);
1319 inline void Store4Val(
double *ptr)
const
1322 high.Store2Val(ptr + 2);
1325 inline void StoreMask(
unsigned char *ptr)
const
1328 high.StoreMask(ptr + 16);
Core portability definitions for CPL.
short GInt16
Int16 type.
Definition cpl_port.h:201
GIntBig GInt64
Signed 64 bit integer type.
Definition cpl_port.h:254
unsigned short GUInt16
Unsigned int16 type.
Definition cpl_port.h:203
int GInt32
Int32 type.
Definition cpl_port.h:195