22 namespace ext::intel::experimental::esimd {
37 template <
typename T0,
typename T1,
int SZ,
typename U,
38 class Sat = __ESIMD_NS::saturation_off_tag>
39 __ESIMD_API std::enable_if_t<std::is_integral<T0>::value &&
40 std::is_integral<T1>::value &&
41 std::is_integral<U>::value,
42 __ESIMD_NS::simd<T0, SZ>>
43 shl(__ESIMD_NS::simd<T1, SZ> src0, U src1, Sat sat = {}) {
45 __ESIMD_DNS::computation_type_t<decltype(src0), int32_t>;
46 ComputationTy Src0 = src0;
47 ComputationTy Src1 = src1;
49 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_on_tag>) {
50 if constexpr (std::is_unsigned<T0>::value) {
51 if constexpr (std::is_unsigned<
52 typename ComputationTy::element_type>::value)
53 return __esimd_uushl_sat<T0, typename ComputationTy::element_type, SZ>(
54 Src0.data(), Src1.data());
56 return __esimd_usshl_sat<T0, typename ComputationTy::element_type, SZ>(
57 Src0.data(), Src1.data());
59 if constexpr (std::is_signed<typename ComputationTy::element_type>::value)
60 return __esimd_sushl_sat<T0, typename ComputationTy::element_type, SZ>(
61 Src0.data(), Src1.data());
63 return __esimd_ssshl_sat<T0, typename ComputationTy::element_type, SZ>(
64 Src0.data(), Src1.data());
67 if constexpr (std::is_unsigned<T0>::value) {
68 if constexpr (std::is_unsigned<
69 typename ComputationTy::element_type>::value)
70 return __esimd_uushl<T0, typename ComputationTy::element_type, SZ>(
71 Src0.data(), Src1.data());
73 return __esimd_usshl<T0, typename ComputationTy::element_type, SZ>(
74 Src0.data(), Src1.data());
76 if constexpr (std::is_signed<typename ComputationTy::element_type>::value)
77 return __esimd_sushl<T0, typename ComputationTy::element_type, SZ>(
78 Src0.data(), Src1.data());
80 return __esimd_ssshl<T0, typename ComputationTy::element_type, SZ>(
81 Src0.data(), Src1.data());
95 template <
typename T0,
typename T1,
typename T2,
96 class Sat = __ESIMD_NS::saturation_off_tag>
97 __ESIMD_API std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<T0>::value &&
98 __ESIMD_DNS::is_esimd_scalar<T1>::value &&
99 __ESIMD_DNS::is_esimd_scalar<T2>::value &&
100 std::is_integral<T0>::value &&
101 std::is_integral<T1>::value &&
102 std::is_integral<T2>::value,
103 std::remove_const_t<T0>>
104 shl(T1 src0, T2 src1, Sat sat = {}) {
105 __ESIMD_NS::simd<T1, 1> Src0 = src0;
106 __ESIMD_NS::simd<T0, 1> Result =
107 esimd::shl<T0, T1, 1, T2, Sat>(Src0, src1, sat);
121 template <
typename T0,
typename T1,
int SZ,
typename U,
122 class Sat = __ESIMD_NS::saturation_off_tag>
123 __ESIMD_API std::enable_if_t<std::is_integral<T0>::value &&
124 std::is_integral<T1>::value &&
125 std::is_integral<U>::value,
126 __ESIMD_NS::simd<T0, SZ>>
127 lsr(__ESIMD_NS::simd<T1, SZ> src0, U src1, Sat sat = {}) {
128 using IntermedTy = __ESIMD_DNS::computation_type_t<T1, T1>;
129 typedef typename std::make_unsigned<IntermedTy>::type ComputationTy;
130 __ESIMD_NS::simd<ComputationTy, SZ> Src0 = src0;
131 __ESIMD_NS::simd<ComputationTy, SZ> Src1 = src1;
133 __ESIMD_NS::simd<ComputationTy, SZ> Result = Src0.data() >> Src1.data();
135 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
138 return __ESIMD_NS::saturate<T0>(Result);
151 template <
typename T0,
typename T1,
typename T2,
152 class Sat = __ESIMD_NS::saturation_off_tag>
153 __ESIMD_API std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<T0>::value &&
154 __ESIMD_DNS::is_esimd_scalar<T1>::value &&
155 __ESIMD_DNS::is_esimd_scalar<T2>::value &&
156 std::is_integral<T0>::value &&
157 std::is_integral<T1>::value &&
158 std::is_integral<T2>::value,
159 std::remove_const_t<T0>>
160 lsr(T1 src0, T2 src1, Sat sat = {}) {
161 __ESIMD_NS::simd<T1, 1> Src0 = src0;
162 __ESIMD_NS::simd<T0, 1> Result =
163 esimd::lsr<T0, T1, 1, T2, Sat>(Src0, src1, sat);
178 template <
typename T0,
typename T1,
int SZ,
typename U,
179 class Sat = __ESIMD_NS::saturation_off_tag>
180 __ESIMD_API std::enable_if_t<std::is_integral<T0>::value &&
181 std::is_integral<T1>::value &&
182 std::is_integral<U>::value,
183 __ESIMD_NS::simd<T0, SZ>>
184 asr(__ESIMD_NS::simd<T1, SZ> src0, U src1, Sat sat = {}) {
185 using IntermedTy = __ESIMD_DNS::computation_type_t<T1, T1>;
186 typedef typename std::make_signed<IntermedTy>::type ComputationTy;
187 __ESIMD_NS::simd<ComputationTy, SZ> Src0 = src0;
189 __ESIMD_NS::simd<ComputationTy, SZ> Result = Src0 >> src1;
191 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
194 return __ESIMD_NS::saturate<T0>(Result);
207 template <
typename T0,
typename T1,
typename T2,
208 class Sat = __ESIMD_NS::saturation_off_tag>
209 __ESIMD_API std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<T0>::value &&
210 __ESIMD_DNS::is_esimd_scalar<T1>::value &&
211 __ESIMD_DNS::is_esimd_scalar<T2>::value &&
212 std::is_integral<T0>::value &&
213 std::is_integral<T1>::value &&
214 std::is_integral<T2>::value,
215 std::remove_const_t<T0>>
216 asr(T1 src0, T2 src1, Sat sat = {}) {
217 __ESIMD_NS::simd<T1, 1> Src0 = src0;
218 __ESIMD_NS::simd<T0, 1> Result =
219 esimd::asr<T0, T1, 1, T2, Sat>(Src0, src1, sat);
233 template <
typename T0,
typename T1,
int SZ,
typename U,
234 class Sat = __ESIMD_NS::saturation_off_tag>
235 __ESIMD_API std::enable_if_t<std::is_integral<T0>::value &&
236 std::is_integral<T1>::value &&
237 std::is_integral<U>::value,
238 __ESIMD_NS::simd<T0, SZ>>
239 shr(__ESIMD_NS::simd<T1, SZ> src0, U src1, Sat sat = {}) {
240 if constexpr (std::is_unsigned<T1>::value) {
241 return esimd::lsr<T0, T1, SZ, U, Sat>(src0, src1, sat);
243 return esimd::asr<T0, T1, SZ, U, Sat>(src0, src1, sat);
256 template <
typename T0,
typename T1,
typename T2,
257 class Sat = __ESIMD_NS::saturation_off_tag>
258 __ESIMD_API std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<T0>::value &&
259 __ESIMD_DNS::is_esimd_scalar<T1>::value &&
260 __ESIMD_DNS::is_esimd_scalar<T2>::value &&
261 std::is_integral<T0>::value &&
262 std::is_integral<T1>::value &&
263 std::is_integral<T2>::value,
264 std::remove_const_t<T0>>
265 shr(T1 src0, T2 src1, Sat sat = {}) {
266 __ESIMD_NS::simd<T1, 1> Src0 = src0;
267 __ESIMD_NS::simd<T0, 1> Result =
268 esimd::shr<T0, T1, 1, T2, Sat>(Src0, src1, sat);
280 template <
typename T0,
typename T1,
int SZ>
281 __ESIMD_API std::enable_if_t<
282 __ESIMD_NS::detail::is_type<T0, int16_t, uint16_t, int32_t, uint32_t,
284 __ESIMD_NS::detail::is_type<T1, int16_t, uint16_t, int32_t, uint32_t,
286 __ESIMD_NS::simd<T0, SZ>>
287 rol(__ESIMD_NS::simd<T1, SZ> src0, __ESIMD_NS::simd<T1, SZ> src1) {
288 return __esimd_rol<T0, T1, SZ>(src0.data(), src1.data());
299 template <
typename T0,
typename T1,
int SZ,
typename U>
300 __ESIMD_API std::enable_if_t<
301 __ESIMD_NS::detail::is_type<T0, int16_t, uint16_t, int32_t, uint32_t,
303 __ESIMD_NS::detail::is_type<T1, int16_t, uint16_t, int32_t, uint32_t,
305 __ESIMD_NS::detail::is_type<U, int16_t, uint16_t, int32_t, uint32_t,
307 __ESIMD_NS::simd<T0, SZ>>
308 rol(__ESIMD_NS::simd<T1, SZ> src0, U src1) {
309 __ESIMD_NS::simd<T1, SZ> Src1 = src1;
310 return esimd::rol<T0>(src0, Src1);
320 template <
typename T0,
typename T1,
typename T2>
321 __ESIMD_API std::enable_if_t<
322 __ESIMD_DNS::is_esimd_scalar<T0>::value &&
323 __ESIMD_DNS::is_esimd_scalar<T1>::value &&
324 __ESIMD_DNS::is_esimd_scalar<T2>::value &&
325 __ESIMD_NS::detail::is_type<T0, int16_t, uint16_t, int32_t, uint32_t,
327 __ESIMD_NS::detail::is_type<T1, int16_t, uint16_t, int32_t, uint32_t,
329 __ESIMD_NS::detail::is_type<T2, int16_t, uint16_t, int32_t, uint32_t,
331 std::remove_const_t<T0>>
333 __ESIMD_NS::simd<T1, 1> Src0 = src0;
334 __ESIMD_NS::simd<T0, 1> Result = esimd::rol<T0, T1, 1, T2>(Src0, src1);
346 template <
typename T0,
typename T1,
int SZ>
347 __ESIMD_API std::enable_if_t<
348 __ESIMD_NS::detail::is_type<T0, int16_t, uint16_t, int32_t, uint32_t,
350 __ESIMD_NS::detail::is_type<T1, int16_t, uint16_t, int32_t, uint32_t,
352 __ESIMD_NS::simd<T0, SZ>>
353 ror(__ESIMD_NS::simd<T1, SZ> src0, __ESIMD_NS::simd<T1, SZ> src1) {
354 return __esimd_ror<T0, T1, SZ>(src0.data(), src1.data());
365 template <
typename T0,
typename T1,
int SZ,
typename U>
366 __ESIMD_API std::enable_if_t<
367 __ESIMD_NS::detail::is_type<T0, int16_t, uint16_t, int32_t, uint32_t,
369 __ESIMD_NS::detail::is_type<T1, int16_t, uint16_t, int32_t, uint32_t,
371 __ESIMD_NS::detail::is_type<U, int16_t, uint16_t, int32_t, uint32_t,
373 __ESIMD_NS::simd<T0, SZ>>
374 ror(__ESIMD_NS::simd<T1, SZ> src0, U src1) {
375 __ESIMD_NS::simd<T1, SZ> Src1 = src1;
376 return esimd::ror<T0>(src0, Src1);
386 template <
typename T0,
typename T1,
typename T2>
387 __ESIMD_API std::enable_if_t<
388 __ESIMD_DNS::is_esimd_scalar<T0>::value &&
389 __ESIMD_DNS::is_esimd_scalar<T1>::value &&
390 __ESIMD_DNS::is_esimd_scalar<T2>::value &&
391 __ESIMD_NS::detail::is_type<T0, int16_t, uint16_t, int32_t, uint32_t,
393 __ESIMD_NS::detail::is_type<T1, int16_t, uint16_t, int32_t, uint32_t,
395 __ESIMD_NS::detail::is_type<T2, int16_t, uint16_t, int32_t, uint32_t,
397 std::remove_const_t<T0>>
399 __ESIMD_NS::simd<T1, 1> Src0 = src0;
400 __ESIMD_NS::simd<T0, 1> Result = esimd::ror<T0, T1, 1, T2>(Src0, src1);
414 template <
typename T,
typename T0,
typename T1,
int N>
415 __ESIMD_API __ESIMD_NS::simd<T, N>
imul_impl(__ESIMD_NS::simd<T, N> &rmd,
416 __ESIMD_NS::simd<T0, N> src0,
417 __ESIMD_NS::simd<T1, N> src1) {
418 static_assert(__ESIMD_DNS::is_dword_type<T>::value &&
419 __ESIMD_DNS::is_dword_type<T0>::value &&
420 __ESIMD_DNS::is_dword_type<T1>::value,
421 "expected 32-bit integer vector operands.");
422 using Comp32T = __ESIMD_DNS::computation_type_t<T0, T1>;
423 auto Src0 = src0.template bit_cast_view<Comp32T>();
424 auto Src1 = src1.template bit_cast_view<Comp32T>();
428 std::conditional_t<std::is_signed_v<Comp32T>,
int64_t, uint64_t>;
429 __ESIMD_NS::simd<Comp64T, N> Product64 = Src0;
433 auto Product32 = Product64.template bit_cast_view<T>();
434 if constexpr (N == 1) {
438 rmd = Product32.template select<N, 2>(0);
439 return Product32.template select<N, 2>(1);
447 template <
typename T,
typename T0,
typename T1,
int N>
448 __ESIMD_API __ESIMD_NS::simd<T, N>
imul(__ESIMD_NS::simd<T, N> &rmd,
449 __ESIMD_NS::simd<T0, N> src0,
450 __ESIMD_NS::simd<T1, N> src1) {
451 return imul_impl<T, T0, T1, N>(rmd, src0, src1);
459 template <
typename T,
typename T0,
typename T1,
int N>
460 __ESIMD_API std::enable_if_t<__ESIMD_DNS::is_dword_type<T1>::value,
461 __ESIMD_NS::simd<T, N>>
462 imul(__ESIMD_NS::simd<T, N> &rmd, __ESIMD_NS::simd<T0, N> src0, T1 src1) {
463 __ESIMD_NS::simd<T1, N> Src1V = src1;
464 return esimd::imul_impl<T, T0, T1, N>(rmd, src0, Src1V);
472 template <
typename T,
typename T0,
typename T1,
int N>
473 __ESIMD_API std::enable_if_t<__ESIMD_DNS::is_dword_type<T0>::value,
474 __ESIMD_NS::simd<T, N>>
475 imul(__ESIMD_NS::simd<T, N> &rmd, T0 src0, __ESIMD_NS::simd<T1, N> src1) {
476 __ESIMD_NS::simd<T0, N> Src0V = src0;
477 return esimd::imul_impl<T, T0, T1, N>(rmd, Src0V, src1);
484 template <
typename T,
typename T0,
typename T1>
485 __ESIMD_API std::enable_if_t<__ESIMD_DNS::is_dword_type<T>::value &&
486 __ESIMD_DNS::is_dword_type<T0>::value &&
487 __ESIMD_DNS::is_dword_type<T1>::value,
489 imul(T &rmd, T0 src0, T1 src1) {
490 __ESIMD_NS::simd<T, 1> RmdV = rmd;
491 __ESIMD_NS::simd<T0, 1> Src0V = src0;
492 __ESIMD_NS::simd<T1, 1> Src1V = src1;
493 __ESIMD_NS::simd<T, 1> Res =
494 esimd::imul_impl<T, T0, T1, 1>(RmdV, Src0V, Src1V);
500 __ESIMD_API __ESIMD_NS::simd<uint32_t, N>
501 addc(__ESIMD_NS::simd<uint32_t, N> &carry, __ESIMD_NS::simd<uint32_t, N> src0,
502 __ESIMD_NS::simd<uint32_t, N> src1) {
503 std::pair<__ESIMD_DNS::vector_type_t<uint32_t, N>,
504 __ESIMD_DNS::vector_type_t<uint32_t, N>>
505 Result = __esimd_addc<uint32_t, N>(src0.data(), src1.data());
507 carry = Result.first;
508 return Result.second;
512 __ESIMD_API __ESIMD_NS::simd<uint32_t, N>
513 addc(__ESIMD_NS::simd<uint32_t, N> &carry, __ESIMD_NS::simd<uint32_t, N> src0,
515 __ESIMD_NS::simd<uint32_t, N> Src1V = src1;
516 return addc(carry, src0, Src1V);
520 __ESIMD_API __ESIMD_NS::simd<uint32_t, N>
521 addc(__ESIMD_NS::simd<uint32_t, N> &carry, uint32_t src0,
522 __ESIMD_NS::simd<uint32_t, N> src1) {
523 __ESIMD_NS::simd<uint32_t, N> Src0V = src0;
524 return addc(carry, Src0V, src1);
527 __ESIMD_API uint32_t
addc(uint32_t &carry, uint32_t src0, uint32_t src1) {
528 __ESIMD_NS::simd<uint32_t, 1> CarryV = carry;
529 __ESIMD_NS::simd<uint32_t, 1> Src0V = src0;
530 __ESIMD_NS::simd<uint32_t, 1> Src1V = src1;
531 __ESIMD_NS::simd<uint32_t, 1> Res =
addc(CarryV, Src0V, Src1V);
537 __ESIMD_API __ESIMD_NS::simd<uint32_t, N>
538 subb(__ESIMD_NS::simd<uint32_t, N> &borrow, __ESIMD_NS::simd<uint32_t, N> src0,
539 __ESIMD_NS::simd<uint32_t, N> src1) {
540 std::pair<__ESIMD_DNS::vector_type_t<uint32_t, N>,
541 __ESIMD_DNS::vector_type_t<uint32_t, N>>
542 Result = __esimd_subb<uint32_t, N>(src0.data(), src1.data());
544 borrow = Result.first;
545 return Result.second;
549 __ESIMD_API __ESIMD_NS::simd<uint32_t, N>
550 subb(__ESIMD_NS::simd<uint32_t, N> &borrow, __ESIMD_NS::simd<uint32_t, N> src0,
552 __ESIMD_NS::simd<uint32_t, N> Src1V = src1;
553 return subb(borrow, src0, Src1V);
557 __ESIMD_API __ESIMD_NS::simd<uint32_t, N>
558 subb(__ESIMD_NS::simd<uint32_t, N> &borrow, uint32_t src0,
559 __ESIMD_NS::simd<uint32_t, N> src1) {
560 __ESIMD_NS::simd<uint32_t, N> Src0V = src0;
561 return subb(borrow, Src0V, src1);
564 __ESIMD_API uint32_t
subb(uint32_t &borrow, uint32_t src0, uint32_t src1) {
565 __ESIMD_NS::simd<uint32_t, 1> BorrowV = borrow;
566 __ESIMD_NS::simd<uint32_t, 1> Src0V = src0;
567 __ESIMD_NS::simd<uint32_t, 1> Src1V = src1;
568 __ESIMD_NS::simd<uint32_t, 1> Res =
subb(BorrowV, Src0V, Src1V);
580 template <
typename T,
int SZ,
typename U>
582 std::enable_if_t<std::is_integral<T>::value && std::is_integral<U>::value,
583 __ESIMD_NS::simd<T, SZ>>
584 quot(__ESIMD_NS::simd<T, SZ> src0, U src1) {
594 template <
typename T0,
typename T1>
595 __ESIMD_API std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<T0>::value &&
596 __ESIMD_DNS::is_esimd_scalar<T1>::value &&
597 std::is_integral<T0>::value &&
598 std::is_integral<T1>::value,
599 std::remove_const_t<T0>>
611 template <
typename T,
int SZ,
typename U>
613 std::enable_if_t<std::is_integral<T>::value && std::is_integral<U>::value,
614 __ESIMD_NS::simd<T, SZ>>
615 mod(__ESIMD_NS::simd<T, SZ> src0, U src1) {
625 template <
typename T0,
typename T1>
626 __ESIMD_API std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<T0>::value &&
627 __ESIMD_DNS::is_esimd_scalar<T1>::value &&
628 std::is_integral<T0>::value &&
629 std::is_integral<T1>::value,
630 std::remove_const_t<T0>>
644 template <
typename T,
int SZ,
typename U>
646 std::enable_if_t<std::is_integral<T>::value && std::is_integral<U>::value,
647 __ESIMD_NS::simd<T, SZ>>
648 div(__ESIMD_NS::simd<T, SZ> &remainder, __ESIMD_NS::simd<T, SZ> src0,
650 remainder = src0 % src1;
663 template <
typename T,
int SZ,
typename U>
665 std::enable_if_t<std::is_integral<T>::value && std::is_integral<U>::value &&
666 __ESIMD_DNS::is_esimd_scalar<U>::value,
667 __ESIMD_NS::simd<T, SZ>>
668 div(__ESIMD_NS::simd<T, SZ> &remainder, U src0,
669 __ESIMD_NS::simd<T, SZ> src1) {
670 remainder = src0 % src1;
683 template <
typename RT,
typename T0,
typename T1>
685 ESIMD_INLINE std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<RT>::value &&
686 __ESIMD_DNS::is_esimd_scalar<T0>::value &&
687 __ESIMD_DNS::is_esimd_scalar<T1>::value,
688 std::remove_const_t<RT>>
691 remainder[0] = src0 % src1;
696 #if defined(ESIMD_GEN7_5) || defined(ESIMD_GEN8) || defined(ESIMD_GEN8_5) || \
697 defined(ESIMD_GEN9) || defined(ESIMD_GEN9_5)
709 template <
typename T0,
typename T1,
int SZ,
typename U,
710 class Sat = __ESIMD_NS::saturation_off_tag>
711 __ESIMD_API __ESIMD_NS::simd<T0, SZ>
dp2(__ESIMD_NS::simd<T1, SZ> src0, U src1,
713 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
714 __ESIMD_NS::simd<float, SZ> Src0 = src0;
715 __ESIMD_NS::simd<float, SZ> Src1 = src1;
716 __ESIMD_NS::simd<float, SZ> Result = __esimd_dp2(Src0.data(), Src1.data());
717 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
720 return __ESIMD_NS::saturate<T0>(Result);
733 template <
typename T0,
typename T1,
int SZ,
typename U,
734 class Sat = __ESIMD_NS::saturation_off_tag>
735 __ESIMD_API __ESIMD_NS::simd<T0, SZ>
dp3(__ESIMD_NS::simd<T1, SZ> src0, U src1,
737 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
738 __ESIMD_NS::simd<float, SZ> Src0 = src0;
739 __ESIMD_NS::simd<float, SZ> Src1 = src1;
740 __ESIMD_NS::simd<float, SZ> Result = __esimd_dp3(Src0.data(), Src1.data());
741 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
744 return __ESIMD_NS::saturate<T0>(Result);
757 template <
typename T0,
typename T1,
int SZ,
typename U,
758 class Sat = __ESIMD_NS::saturation_off_tag>
759 __ESIMD_API __ESIMD_NS::simd<T0, SZ>
dp4(__ESIMD_NS::simd<T1, SZ> src0, U src1,
761 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
762 __ESIMD_NS::simd<float, SZ> Src0 = src0;
763 __ESIMD_NS::simd<float, SZ> Src1 = src1;
764 __ESIMD_NS::simd<float, SZ> Result = __esimd_dp4(Src0.data(), Src1.data());
765 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
768 return __ESIMD_NS::saturate<T0>(Result);
781 template <
typename T0,
typename T1,
typename U,
int SZ,
782 class Sat = __ESIMD_NS::saturation_off_tag>
783 __ESIMD_API __ESIMD_NS::simd<T0, SZ>
dph(__ESIMD_NS::simd<T1, SZ> src0, U src1,
785 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
786 __ESIMD_NS::simd<float, SZ> Src0 = src0;
787 __ESIMD_NS::simd<float, SZ> Src1 = src1;
788 __ESIMD_NS::simd<float, SZ> Result = __esimd_dph(Src0.data(), Src1.data());
789 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
792 return __ESIMD_NS::saturate<T0>(Result);
806 template <
typename RT,
typename T1,
typename T2,
int SZ,
807 class Sat = __ESIMD_NS::saturation_off_tag>
808 __ESIMD_API __ESIMD_NS::simd<RT, SZ>
line(__ESIMD_NS::simd<T1, 4> src0,
809 __ESIMD_NS::simd<T2, SZ> src1,
811 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
813 __ESIMD_NS::simd<float, 4> Src0 = src0;
814 __ESIMD_NS::simd<float, SZ> Src1 = src1;
815 __ESIMD_NS::simd<float, SZ> Result = __esimd_line(Src0.data(), Src1.data());
817 __ESIMD_NS::simd<RT, SZ> Result;
818 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
821 return __ESIMD_NS::saturate<RT>(Result);
835 template <
typename RT,
typename T,
int SZ,
836 class Sat = __ESIMD_NS::saturation_off_tag>
837 __ESIMD_API __ESIMD_NS::simd<RT, SZ>
838 line(
float P,
float Q, __ESIMD_NS::simd<T, SZ> src1, Sat sat = {}) {
839 __ESIMD_NS::simd<float, 4> Src0 = P;
841 return esimd::line<RT>(Src0, src1, sat);
866 template <
typename T0,
typename T1,
int SZ,
typename U,
867 class Sat = __ESIMD_NS::saturation_off_tag>
868 ESIMD_NODEBUG ESIMD_INLINE
869 std::enable_if_t<__ESIMD_DNS::is_fp_or_dword_type<T1>::value &&
870 std::is_floating_point<T1>::value &&
871 __ESIMD_DNS::is_fp_or_dword_type<U>::value &&
872 std::is_floating_point<U>::value,
873 __ESIMD_NS::simd<T0, SZ>>
874 dp2(__ESIMD_NS::simd<T1, SZ> src0, U src1, Sat sat = {}) {
875 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
877 __ESIMD_NS::simd<float, SZ> Src1 = src1;
878 __ESIMD_NS::simd<float, SZ> Result;
880 for (
int i = 0; i < SZ; i += 4) {
881 Result.select<4, 1>(i) = src0[i] * Src1[i] + src0[i + 1] * Src1[i + 1];
883 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
886 return __ESIMD_NS::saturate<T1>(Result);
899 template <
typename T0,
typename T1,
int SZ,
typename U,
900 class Sat = __ESIMD_NS::saturation_off_tag>
901 ESIMD_NODEBUG ESIMD_INLINE
902 std::enable_if_t<__ESIMD_DNS::is_fp_or_dword_type<T1>::value &&
903 std::is_floating_point<T1>::value &&
904 __ESIMD_DNS::is_fp_or_dword_type<U>::value &&
905 std::is_floating_point<U>::value,
906 __ESIMD_NS::simd<T0, SZ>>
907 dp3(__ESIMD_NS::simd<T1, SZ> src0, U src1, Sat sat = {}) {
908 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
910 __ESIMD_NS::simd<float, SZ> Src1 = src1;
911 __ESIMD_NS::simd<float, SZ> Result;
913 for (
int i = 0; i < SZ; i += 4) {
914 Result.select<4, 1>(i) = src0[i] * Src1[i] + src0[i + 1] * Src1[i + 1] +
915 src0[i + 2] * Src1[i + 2];
917 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
920 return __ESIMD_NS::saturate<T1>(Result);
933 template <
typename T0,
typename T1,
int SZ,
typename U,
934 class Sat = __ESIMD_NS::saturation_off_tag>
935 ESIMD_NODEBUG ESIMD_INLINE
936 std::enable_if_t<__ESIMD_DNS::is_fp_or_dword_type<T1>::value &&
937 std::is_floating_point<T1>::value &&
938 __ESIMD_DNS::is_fp_or_dword_type<U>::value &&
939 std::is_floating_point<U>::value,
940 __ESIMD_NS::simd<T0, SZ>>
941 dp4(__ESIMD_NS::simd<T1, SZ> src0, U src1, Sat sat = {}) {
942 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
944 __ESIMD_NS::simd<T1, SZ> Src1 = src1;
945 __ESIMD_NS::simd<float, SZ> Result;
947 for (
int i = 0; i < SZ; i += 4) {
948 Result.select<4, 1>(i) = src0[i] * Src1[i] + src0[i + 1] * Src1[i + 1] +
949 src0[i + 2] * Src1[i + 2] +
950 src0[i + 3] * Src1[i + 3];
952 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
955 return __ESIMD_NS::saturate<T1>(Result);
968 template <
typename T,
typename U,
int SZ,
969 class Sat = __ESIMD_NS::saturation_off_tag>
970 ESIMD_NODEBUG ESIMD_INLINE
971 std::enable_if_t<__ESIMD_DNS::is_fp_or_dword_type<T>::value &&
972 std::is_floating_point<T>::value &&
973 __ESIMD_DNS::is_fp_or_dword_type<U>::value &&
974 std::is_floating_point<U>::value,
975 __ESIMD_NS::simd<T, SZ>>
976 dph(__ESIMD_NS::simd<T, SZ> src0, U src1, Sat sat = {}) {
977 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
979 __ESIMD_NS::simd<float, SZ> Src1 = src1;
980 __ESIMD_NS::simd<float, SZ> Result;
982 for (
int i = 0; i < SZ; i += 4) {
983 Result.select<4, 1>(i) = src0[i] * Src1[i] + src0[i + 1] * Src1[i + 1] +
984 src0[i + 2] * Src1[i + 2] + 1.0 * Src1[i + 3];
986 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
989 return __ESIMD_NS::saturate<T>(Result);
1002 template <
typename T,
int SZ,
class Sat = __ESIMD_NS::saturation_off_tag>
1004 ESIMD_INLINE std::enable_if_t<__ESIMD_DNS::is_fp_or_dword_type<T>::value &&
1005 std::is_floating_point<T>::value,
1006 __ESIMD_NS::simd<T, SZ>>
1007 line(__ESIMD_NS::simd<T, 4> src0, __ESIMD_NS::simd<T, SZ> src1,
1009 static_assert(SZ % 4 == 0,
"result size is not a multiple of 4");
1011 __ESIMD_NS::simd<T, SZ> Src1 = src1;
1012 __ESIMD_NS::simd<T, SZ> Result;
1014 for (
int i = 0; i < SZ; i += 4) {
1015 Result.select<4, 1>(i) = src0[0] * src1[i] + src0[3];
1018 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
1021 return __ESIMD_NS::saturate<T>(Result);
1035 template <
typename T,
int SZ,
class Sat = __ESIMD_NS::saturation_off_tag>
1037 ESIMD_INLINE std::enable_if_t<__ESIMD_DNS::is_fp_or_dword_type<T>::value &&
1038 std::is_floating_point<T>::value,
1039 __ESIMD_NS::simd<T, SZ>>
1040 line(
float P,
float Q, __ESIMD_NS::simd<T, SZ> src1, Sat sat = {}) {
1041 __ESIMD_NS::simd<T, 4> Src0 = P;
1043 return esimd::line<T>(Src0, src1, sat);
1054 template <
typename T,
int SZ>
1055 __ESIMD_API __ESIMD_NS::simd<T, SZ>
frc(__ESIMD_NS::simd<T, SZ> src0) {
1056 __ESIMD_NS::simd<float, SZ> Src0 = src0;
1057 return __esimd_frc(Src0.data());
1065 template <
typename T> __ESIMD_API T
frc(T src0) {
1066 __ESIMD_NS::simd<T, 1> Src0 = src0;
1067 __ESIMD_NS::simd<T, 1> Result = esimd::frc<T>(Src0);
1072 template <
typename RT,
typename T0,
int SZ,
1073 class Sat = __ESIMD_NS::saturation_off_tag>
1074 __ESIMD_API __ESIMD_NS::simd<RT, SZ>
lzd(__ESIMD_NS::simd<T0, SZ> src0,
1077 __ESIMD_NS::simd<__ESIMD_NS::uint, SZ> Src0 = src0;
1078 return __esimd_lzd<__ESIMD_NS::uint, SZ>(Src0.data());
1081 template <
typename RT,
typename T0,
class Sat = __ESIMD_NS::saturation_off_tag>
1083 ESIMD_INLINE std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<RT>::value &&
1084 __ESIMD_DNS::is_esimd_scalar<T0>::value,
1085 std::remove_const_t<RT>>
1087 __ESIMD_NS::simd<T0, 1> Src0 = src0;
1088 __ESIMD_NS::simd<RT, 1> Result = esimd::lzd<RT>(Src0);
1093 #if defined(ESIMD_GEN7_5) || defined(ESIMD_GEN8) || defined(ESIMD_GEN8_5) || \
1094 defined(ESIMD_GEN9) || defined(ESIMD_GEN9_5)
1096 template <
int SZ,
typename U,
typename V,
1097 class Sat = __ESIMD_NS::saturation_off_tag>
1098 __ESIMD_API __ESIMD_NS::simd<float, SZ>
lrp(__ESIMD_NS::simd<float, SZ> src0,
1099 U src1, V src2, Sat sat = {}) {
1100 static_assert(SZ >= 4 && (SZ & 0x3) == 0,
1101 "vector size must be a multiple of 4");
1102 __ESIMD_NS::simd<float, SZ> Src1 = src1;
1103 __ESIMD_NS::simd<float, SZ> Src2 = src2;
1104 __ESIMD_NS::simd<float, SZ> Result =
1105 __esimd_lrp<SZ>(src0.data(), Src1.data(), Src2.data());
1107 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
1110 return __ESIMD_NS::saturate<float>(Result);
1124 template <
typename T,
int SZ,
typename U,
typename V,
1125 class Sat = __ESIMD_NS::saturation_off_tag>
1126 ESIMD_NODEBUG ESIMD_INLINE
1127 std::enable_if_t<__ESIMD_DNS::is_fp_or_dword_type<T>::value &&
1128 std::is_floating_point<T>::value &&
1129 __ESIMD_DNS::is_fp_or_dword_type<U>::value &&
1130 std::is_floating_point<U>::value,
1131 __ESIMD_NS::simd<T, SZ>>
1132 lrp(__ESIMD_NS::simd<T, SZ> src0, U src1, V src2, Sat sat = {}) {
1134 __ESIMD_NS::simd<float, SZ> Src1 = src1;
1135 __ESIMD_NS::simd<float, SZ> Src2 = src2;
1136 __ESIMD_NS::simd<float, SZ> Result;
1137 Result = Src1 * src0 + Src2 * (1.0f - src0);
1138 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
1141 return __ESIMD_NS::saturate<T>(Result);
1151 template <
typename T0,
typename T1,
int SZ>
1152 __ESIMD_API __ESIMD_NS::simd<T0, SZ>
bf_reverse(__ESIMD_NS::simd<T1, SZ> src0) {
1153 __ESIMD_NS::simd<unsigned, SZ> Src0 = src0;
1154 return __esimd_bfrev<unsigned>(Src0.data());
1158 template <
typename T0,
typename T1>
1160 ESIMD_INLINE std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<T0>::value &&
1161 __ESIMD_DNS::is_esimd_scalar<T1>::value,
1162 std::remove_const_t<T0>>
1164 __ESIMD_NS::simd<T1, 1> Src0 = src0;
1165 __ESIMD_NS::simd<T0, 1> Result = esimd::bf_reverse<T0>(Src0);
1170 template <
typename T0,
typename T1,
int SZ,
typename U,
typename V,
typename W>
1171 ESIMD_NODEBUG ESIMD_INLINE
1172 std::enable_if_t<std::is_integral<T1>::value, __ESIMD_NS::simd<T0, SZ>>
1173 bf_insert(U src0, V src1, W src2, __ESIMD_NS::simd<T1, SZ> src3) {
1174 typedef typename __ESIMD_DNS::dword_type<T1> DT1;
1175 static_assert(std::is_integral<DT1>::value &&
sizeof(DT1) ==
sizeof(
int),
1176 "operand conversion failed");
1177 __ESIMD_NS::simd<DT1, SZ> Src0 = src0;
1178 __ESIMD_NS::simd<DT1, SZ> Src1 = src1;
1179 __ESIMD_NS::simd<DT1, SZ> Src2 = src2;
1180 __ESIMD_NS::simd<DT1, SZ> Src3 = src3;
1182 return __esimd_bfi<DT1>(Src0.data(), Src1.data(), Src2.data(), Src3.data());
1186 template <
typename T0,
typename T1,
typename T2,
typename T3,
typename T4>
1188 ESIMD_INLINE std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<T0>::value &&
1189 __ESIMD_DNS::is_esimd_scalar<T4>::value,
1190 std::remove_const_t<T0>>
1192 __ESIMD_NS::simd<T4, 1> Src3 = src3;
1193 __ESIMD_NS::simd<T0, 1> Result = esimd::bf_insert<T0>(src0, src1, src2, Src3);
1198 template <
typename T0,
typename T1,
int SZ,
typename U,
typename V>
1199 ESIMD_NODEBUG ESIMD_INLINE
1200 std::enable_if_t<std::is_integral<T1>::value, __ESIMD_NS::simd<T0, SZ>>
1202 typedef typename __ESIMD_DNS::dword_type<T1> DT1;
1203 static_assert(std::is_integral<DT1>::value &&
sizeof(DT1) ==
sizeof(
int),
1204 "operand conversion failed");
1205 __ESIMD_NS::simd<DT1, SZ> Src0 = src0;
1206 __ESIMD_NS::simd<DT1, SZ> Src1 = src1;
1207 __ESIMD_NS::simd<DT1, SZ> Src2 = src2;
1209 return __esimd_sbfe<DT1>(Src0.data(), Src1.data(), Src2.data());
1213 template <
typename T0,
typename T1,
typename T2,
typename T3>
1215 ESIMD_INLINE std::enable_if_t<__ESIMD_DNS::is_esimd_scalar<T0>::value &&
1216 __ESIMD_DNS::is_esimd_scalar<T3>::value,
1217 std::remove_const_t<T0>>
1219 __ESIMD_NS::simd<T3, 1> Src2 = src2;
1220 __ESIMD_NS::simd<T0, 1> Result = esimd::bf_extract<T0>(src0, src1, Src2);
1230 template <
int SZ,
typename U,
class Sat = __ESIMD_NS::saturation_off_tag>
1231 __ESIMD_API __ESIMD_NS::simd<float, SZ>
1232 sincos(__ESIMD_NS::simd<float, SZ> &dstcos, U src0, Sat sat = {}) {
1241 constexpr
double __ESIMD_CONST_PI = 3.1415926535897932384626433832795;
1245 template <
typename T,
int SZ>
1246 ESIMD_NODEBUG ESIMD_INLINE __ESIMD_NS::simd<T, SZ>
1247 atan(__ESIMD_NS::simd<T, SZ> src0) {
1248 static_assert(std::is_floating_point<T>::value,
1249 "Floating point argument type is expected.");
1252 __ESIMD_NS::simd<T, SZ> OneP((T)1.0);
1253 __ESIMD_NS::simd<T, SZ> OneN((T)-1.0);
1254 __ESIMD_NS::simd<T, SZ> sign;
1255 __ESIMD_NS::simd_mask<SZ> Gt1 = Src0 > T(1.0);
1257 sign.merge(OneN, OneP, src0 < 0);
1261 __ESIMD_NS::simd<T, SZ> Src0P2 = Src0 * Src0;
1262 __ESIMD_NS::simd<T, SZ> Src0P4 = Src0P2 * Src0P2;
1264 __ESIMD_NS::simd<T, SZ> Result =
1265 (Src0P4 * T(0.185696) + ((Src0 * T(0.787997) + T(0.63693)) * Src0P2) +
1267 (((((Src0 * -T(0.000121387) + T(0.00202308)) * Src0P2) +
1268 (Src0 * -T(0.0149145)) + T(0.182569)) *
1270 ((Src0 * T(0.395889) + T(1.12158)) * Src0P2) + (Src0 * T(0.636918)) +
1273 Result.merge(Result - T(detail::__ESIMD_CONST_PI) / T(2.0), Gt1);
1278 template <
typename T> __ESIMD_API T
atan(T src0) {
1279 static_assert(std::is_floating_point<T>::value,
1280 "Floating point argument type is expected.");
1281 __ESIMD_NS::simd<T, 1> Src0 = src0;
1282 __ESIMD_NS::simd<T, 1> Result =
esimd::atan(Src0);
1288 template <
typename T,
int SZ>
1289 ESIMD_NODEBUG ESIMD_INLINE
1290 std::enable_if_t<std::is_floating_point<T>::value, __ESIMD_NS::simd<T, SZ>>
1291 acos(__ESIMD_NS::simd<T, SZ> src0) {
1294 __ESIMD_NS::simd_mask<SZ> Neg = src0 < T(0.0);
1295 __ESIMD_NS::simd_mask<SZ> TooBig = Src0 >= T(0.999998);
1299 Src0.merge(T(0.0), TooBig);
1301 __ESIMD_NS::simd<T, SZ> Src01m = T(1.0) - Src0;
1303 __ESIMD_NS::simd<T, SZ> Src0P2 = Src01m * Src01m;
1304 __ESIMD_NS::simd<T, SZ> Src0P4 = Src0P2 * Src0P2;
1306 __ESIMD_NS::simd<T, SZ> Result =
1307 (((Src01m * T(0.015098965761299077) - T(0.005516443930088506)) * Src0P4) +
1308 ((Src01m * T(0.047654245891495528) + T(0.163910606547823220)) * Src0P2) +
1309 Src01m * T(2.000291665285952400) - T(0.000007239283986332)) *
1312 Result.merge(T(0.0), TooBig);
1313 Result.merge(T(detail::__ESIMD_CONST_PI) - Result, Neg);
1317 template <
typename T>
1318 __ESIMD_API std::enable_if_t<std::is_floating_point<T>::value, T>
acos(T src0) {
1319 __ESIMD_NS::simd<T, 1> Src0 = src0;
1320 __ESIMD_NS::simd<T, 1> Result =
esimd::acos(Src0);
1326 template <
typename T,
int SZ>
1327 ESIMD_NODEBUG ESIMD_INLINE
1328 std::enable_if_t<std::is_floating_point<T>::value, __ESIMD_NS::simd<T, SZ>>
1329 asin(__ESIMD_NS::simd<T, SZ> src0) {
1330 __ESIMD_NS::simd_mask<SZ> Neg = src0 < T(0.0);
1332 __ESIMD_NS::simd<T, SZ> Result =
1335 Result.merge(-Result, Neg);
1339 template <
typename T>
1340 __ESIMD_API std::enable_if_t<std::is_floating_point<T>::value, T>
asin(T src0) {
1341 __ESIMD_NS::simd<T, 1> Src0 = src0;
1342 __ESIMD_NS::simd<T, 1> Result =
esimd::asin(Src0);
1353 __ESIMD_NS::simd<float, N>
atan2_fast(__ESIMD_NS::simd<float, N> y,
1354 __ESIMD_NS::simd<float, N> x);
1356 template <
typename T>
float atan2_fast(T y, T x);
1361 __ESIMD_NS::simd<float, N>
atan2(__ESIMD_NS::simd<float, N> y,
1362 __ESIMD_NS::simd<float, N> x);
1364 template <
typename T>
float atan2(T y, T x);
1369 __ESIMD_NS::simd<float, N>
fmod(__ESIMD_NS::simd<float, N> y,
1370 __ESIMD_NS::simd<float, N> x);
1372 template <
typename T>
float fmod(T y, T x);
1377 __ESIMD_NS::simd<float, N>
sin_emu(__ESIMD_NS::simd<float, N> x);
1379 template <
typename T>
float sin_emu(T x);
1384 __ESIMD_NS::simd<float, N>
cos_emu(__ESIMD_NS::simd<float, N> x);
1387 template <
typename T>
float cos_emu(T x);
1394 __ESIMD_NS::simd<float, N>
tanh_cody_waite(__ESIMD_NS::simd<float, N> x);
1397 float tanh(
float x);
1399 template <
int N> __ESIMD_NS::simd<float, N>
tanh(__ESIMD_NS::simd<float, N> x);
1406 ESIMD_INLINE __ESIMD_NS::simd<float, N>
1407 atan2_fast(__ESIMD_NS::simd<float, N> y, __ESIMD_NS::simd<float, N> x) {
1409 constexpr
float CONST_DBL_EPSILON = 0.00001f;
1410 __ESIMD_NS::simd<float, N> OneP(1.0f);
1411 __ESIMD_NS::simd<float, N> OneN(-1.0f);
1412 __ESIMD_NS::simd<float, N> sign;
1413 __ESIMD_NS::simd<float, N>
atan2;
1414 __ESIMD_NS::simd<float, N>
r;
1415 __ESIMD_NS::simd_mask<N> mask =
x < 0;
1418 r.merge((
x + abs_y) / (abs_y -
x), (
x - abs_y) / (
x + abs_y), mask);
1419 atan2.merge(
float(detail::__ESIMD_CONST_PI) * 0.75f,
1420 float(detail::__ESIMD_CONST_PI) * 0.25f, mask);
1421 atan2 += (0.1963f *
r *
r - 0.9817f) *
r;
1423 sign.merge(OneN, OneP,
y < 0);
1425 return atan2 * sign;
1430 __ESIMD_NS::simd<float, 1> vy =
y;
1431 __ESIMD_NS::simd<float, 1> vx =
x;
1439 ESIMD_INLINE __ESIMD_NS::simd<float, N>
atan2(__ESIMD_NS::simd<float, N> y,
1440 __ESIMD_NS::simd<float, N> x) {
1441 __ESIMD_NS::simd<float, N> v_distance;
1442 __ESIMD_NS::simd<float, N>
atan2;
1443 __ESIMD_NS::simd_mask<N> mask;
1445 constexpr
float CONST_DBL_EPSILON = 0.00001f;
1447 mask = (
x < -CONST_DBL_EPSILON && y < CONST_DBL_EPSILON && y >= 0.f);
1448 atan2.merge(
float(detail::__ESIMD_CONST_PI), 0.f, mask);
1449 mask = (
x < -CONST_DBL_EPSILON &&
y > -CONST_DBL_EPSILON &&
y < 0);
1450 atan2.merge(
float(-detail::__ESIMD_CONST_PI), mask);
1462 template <> ESIMD_INLINE
float atan2(
float y,
float x) {
1463 __ESIMD_NS::simd<float, 1> vy =
y;
1464 __ESIMD_NS::simd<float, 1> vx =
x;
1472 ESIMD_INLINE __ESIMD_NS::simd<float, N>
fmod(__ESIMD_NS::simd<float, N> y,
1473 __ESIMD_NS::simd<float, N> x) {
1477 auto fmod_sign_mask = (
y.template bit_cast_view<int32_t>()) & 0x80000000;
1479 __ESIMD_NS::simd<float, N> reminder =
1480 abs_y - abs_x * __ESIMD_NS::trunc<float>(abs_y / abs_x);
1482 abs_x.merge(0.0f, reminder >= 0);
1483 __ESIMD_NS::simd<float, N>
fmod = reminder + abs_x;
1487 (fmod_abs.template bit_cast_view<int32_t>()) | fmod_sign_mask;
1488 return fmod_bits.template bit_cast_view<float>();
1492 template <> ESIMD_INLINE
float fmod(
float y,
float x) {
1493 return fmod(__ESIMD_NS::simd<float, 1>(
y), __ESIMD_NS::simd<float, 1>(
x))[0];
1499 ESIMD_INLINE __ESIMD_NS::simd<float, N>
sin_emu(__ESIMD_NS::simd<float, N> x) {
1500 __ESIMD_NS::simd<float, N> x1;
1501 __ESIMD_NS::simd<float, N> x2;
1502 __ESIMD_NS::simd<float, N> t3;
1504 __ESIMD_NS::simd<float, N> sign;
1505 __ESIMD_NS::simd<float, N> fTrig;
1506 __ESIMD_NS::simd<float, N> TwoPI(
float(detail::__ESIMD_CONST_PI) * 2.0f);
1507 __ESIMD_NS::simd<float, N> CmpI((
float)detail::__ESIMD_CONST_PI);
1508 __ESIMD_NS::simd<float, N> OneP(1.0f);
1509 __ESIMD_NS::simd<float, N> OneN(-1.0f);
1512 x.merge(TwoPI +
x,
x < 0);
1514 x1.merge(CmpI -
x,
x - CmpI, (
x <=
float(detail::__ESIMD_CONST_PI)));
1515 x1.merge(
x, (
x <=
float(detail::__ESIMD_CONST_PI) * 0.5f));
1516 x1.merge(TwoPI -
x, (
x >
float(detail::__ESIMD_CONST_PI) * 1.5f));
1518 sign.merge(OneN, OneP, (
x >
float(detail::__ESIMD_CONST_PI)));
1521 t3 = x2 * x1 * 0.1666667f;
1524 x1 + t3 * (OneN + x2 * 0.05f *
1525 (OneP + x2 * 0.0238095f *
1526 (OneN + x2 * 0.0138889f *
1527 (OneP - x2 * 0.0090909f))));
1533 template <> ESIMD_INLINE
float sin_emu(
float x0) {
1540 ESIMD_INLINE __ESIMD_NS::simd<float, N>
cos_emu(__ESIMD_NS::simd<float, N> x) {
1545 template <> ESIMD_INLINE
float cos_emu(
float x0) {
1553 ESIMD_INLINE __ESIMD_NS::simd<float, N>
1554 tanh_cody_waite_impl(__ESIMD_NS::simd<float, N> x) {
1565 constexpr
float p0 = -0.8237728127E+00f;
1566 constexpr
float p1 = -0.3831010665E-02f;
1567 constexpr
float q0 = 0.2471319654E+01f;
1568 constexpr
float q1 = 1.0000000000E+00f;
1569 constexpr
float xsmall = 4.22863966691620432990E-04f;
1570 constexpr
float xmedium = 0.54930614433405484570f;
1571 constexpr
float xlarge = 8.66433975699931636772f;
1573 using RT = __ESIMD_NS::simd<float, N>;
1579 sign.merge(-1.f, 1.f, x < 0.f);
1581 auto isLarge = absX > xlarge;
1582 auto minor = absX <= xlarge;
1583 auto isGtMed = minor & (absX > xmedium);
1584 auto isGtSmall = (absX > xsmall) & (absX <= xmedium);
1587 res.merge(sign, x, isLarge);
1589 temp = ((temp - 2.f) / temp) * sign;
1590 res.merge(temp, isGtMed);
1591 res.merge((absX + absX * g * (g * p1 + p0) / (g + q0)) * sign, isGtSmall);
1597 ESIMD_INLINE __ESIMD_NS::simd<float, N>
1598 tanh_impl(__ESIMD_NS::simd<float, N> x) {
1605 constexpr
float xsmall = 0.000045f;
1606 constexpr
float xlarge = 40.f;
1608 using RT = __ESIMD_NS::simd<float, N>;
1613 sign.merge(-1.f, 1.f, x < 0.f);
1615 auto isLarge = (absX > xlarge);
1616 auto isLessE = (absX <= xlarge);
1619 res.merge(sign, x, isLarge);
1624 res.merge(((
exp - 1.f) / (
exp + 1.f)) * sign, (absX > xsmall) & isLessE);
1634 return detail::tanh_cody_waite_impl(__ESIMD_NS::simd<float, 1>(
x))[0];
1638 ESIMD_INLINE __ESIMD_NS::simd<float, N>
1640 return detail::tanh_cody_waite_impl(
x);
1646 return esimd::detail::tanh_impl(__ESIMD_NS::simd<float, 1>(
x))[0];
1650 ESIMD_INLINE __ESIMD_NS::simd<float, N>
tanh(__ESIMD_NS::simd<float, N> x) {
1651 return esimd::detail::tanh_impl(
x);
1654 template <
typename T,
int N>
1655 __ESIMD_NS::simd<T, N>
dp4(__ESIMD_NS::simd<T, N> v1,
1656 __ESIMD_NS::simd<T, N> v2) {
1657 auto retv = __esimd_dp4<T, N>(v1.data(), v2.data());
1679 template <argument_type src1_precision, argument_type src2_precision,
1680 typename T,
int systolic_depth,
int repeat_count,
typename T0,
1681 typename T1,
typename T2,
int N,
int N1,
int N2,
1682 typename Sat = __ESIMD_NS::saturation_off_tag>
1684 __ESIMD_API __ESIMD_NS::
simd<T, N> dpas(
1685 __ESIMD_NS::
simd<T0, N> src0, __ESIMD_NS::
simd<T1, N1> src1,
1686 __ESIMD_NS::
simd<T2, N2> src2,
1690 src1_precision, src2_precision>(src0, src1, src2);
1691 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
1694 return __ESIMD_NS::saturate<T>(result);
1707 template <argument_type src1_precision, argument_type src2_precision,
1708 int systolic_depth,
int repeat_count,
typename T,
typename T1,
1709 typename T2,
int N,
int N1,
int N2,
1710 typename Sat = __ESIMD_NS::saturation_off_tag>
1712 __ESIMD_API __ESIMD_NS::
simd<T, N> dpas(
1713 __ESIMD_NS::
simd<T, N> src0, __ESIMD_NS::
simd<T1, N1> src1,
1714 __ESIMD_NS::
simd<T2, N2> src2,
1716 return dpas<src1_precision, src2_precision, T, systolic_depth, repeat_count>(
1717 src0, src1, src2, sat);
1728 template <argument_type src1_precision, argument_type src2_precision,
1729 int systolic_depth,
int repeat_count,
typename T,
typename T1,
1730 typename T2,
int N,
int N1,
int N2,
1731 typename Sat = __ESIMD_NS::saturation_off_tag>
1733 __ESIMD_API __ESIMD_NS::
simd<T, N> dpas(
1734 __ESIMD_NS::
simd<T1, N1> src1, __ESIMD_NS::
simd<T2, N2> src2,
1737 __ESIMD_NS::simd<T, N> result =
1739 src1_precision, src2_precision>(src1, src2);
1741 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
1744 return __ESIMD_NS::saturate<T>(result);
1757 template <argument_type src1_precision, argument_type src2_precision,
1758 int systolic_depth,
int repeat_count,
typename T,
typename T1,
1759 typename T2,
int N,
int N1,
int N2,
1760 typename Sat = __ESIMD_NS::saturation_off_tag>
1763 __ESIMD_NS::
simd<T, N> src0, __ESIMD_NS::
simd<T1, N1> src1,
1764 __ESIMD_NS::
simd<T2, N2> src2,
1767 __ESIMD_NS::simd<T, N> result =
1769 src1_precision, src2_precision>(src0, src1, src2);
1770 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
1773 return __ESIMD_NS::saturate<T>(result);
1784 template <argument_type src1_precision, argument_type src2_precision,
1785 int systolic_depth,
int repeat_count,
typename T,
typename T1,
1786 typename T2,
int N,
int N1,
int N2,
1787 typename Sat = __ESIMD_NS::saturation_off_tag>
1790 __ESIMD_NS::
simd<T1, N1> src1, __ESIMD_NS::
simd<T2, N2> src2,
1793 __ESIMD_NS::simd<T, N> result =
1795 src1_precision, src2_precision>(src1, src2);
1797 if constexpr (std::is_same_v<Sat, __ESIMD_NS::saturation_off_tag>)
1800 return __ESIMD_NS::saturate<T>(result);
1811 enum class bfn_t : uint8_t {
x = 0xAA,
y = 0xCC,
z = 0xF0 };
1814 uint8_t val =
static_cast<uint8_t
>(
x);
1816 return static_cast<bfn_t>(res);
1820 uint8_t arg0 =
static_cast<uint8_t
>(
x);
1821 uint8_t arg1 =
static_cast<uint8_t
>(
y);
1822 uint8_t res = arg0 | arg1;
1823 return static_cast<bfn_t>(res);
1827 uint8_t arg0 =
static_cast<uint8_t
>(
x);
1828 uint8_t arg1 =
static_cast<uint8_t
>(
y);
1829 uint8_t res = arg0 & arg1;
1830 return static_cast<bfn_t>(res);
1834 uint8_t arg0 =
static_cast<uint8_t
>(
x);
1835 uint8_t arg1 =
static_cast<uint8_t
>(
y);
1836 uint8_t res = arg0 ^ arg1;
1837 return static_cast<bfn_t>(res);
1848 template <bfn_t FuncControl,
typename T,
int N>
1849 __ESIMD_API std::enable_if_t<std::is_integral_v<T>, __ESIMD_NS::simd<T, N>>
1850 bfn(__ESIMD_NS::simd<T, N> src0, __ESIMD_NS::simd<T, N> src1,
1851 __ESIMD_NS::simd<T, N> src2) {
1852 if constexpr ((
sizeof(T) == 8) || ((
sizeof(T) == 1) && (N % 4 == 0)) ||
1853 ((
sizeof(T) == 2) && (N % 2 == 0))) {
1857 auto Result = __ESIMD_ENS::bfn<FuncControl>(
1858 src0.template bit_cast_view<int32_t>().read(),
1859 src1.template bit_cast_view<int32_t>().read(),
1860 src2.template bit_cast_view<int32_t>().read());
1861 return Result.template bit_cast_view<T>();
1862 }
else if constexpr (
sizeof(T) == 2 ||
sizeof(T) == 4) {
1863 constexpr uint8_t FC =
static_cast<uint8_t
>(FuncControl);
1864 return __esimd_bfn<FC, T, N>(src0.data(), src1.data(), src2.data());
1865 }
else if constexpr (N % 2 == 0) {
1867 auto Result = __ESIMD_ENS::bfn<FuncControl>(
1868 src0.template bit_cast_view<int16_t>().read(),
1869 src1.template bit_cast_view<int16_t>().read(),
1870 src2.template bit_cast_view<int16_t>().read());
1871 return Result.template bit_cast_view<T>();
1874 __ESIMD_NS::simd<T, N + 1> Src0, Src1, Src2;
1875 Src0.template select<N, 1>() = src0;
1876 Src1.template select<N, 1>() = src1;
1877 Src2.template select<N, 1>() = src2;
1878 auto Result = __ESIMD_ENS::bfn<FuncControl>(Src0, Src1, Src2);
1879 return Result.template select<N, 1>();
1890 template <bfn_t FuncControl,
typename T>
1891 ESIMD_NODEBUG ESIMD_INLINE std::enable_if_t<
1892 __ESIMD_DNS::is_esimd_scalar<T>::value && std::is_integral_v<T>, T>
1894 __ESIMD_NS::simd<T, 1> Src0 = src0;
1895 __ESIMD_NS::simd<T, 1> Src1 = src1;
1896 __ESIMD_NS::simd<T, 1> Src2 = src2;
1897 __ESIMD_NS::simd<T, 1> Result =
1898 esimd::bfn<FuncControl, T, 1>(Src0, Src1, Src2);