13#ifndef EIGEN_ARCH_GENERIC_PACKET_MATH_TRIG_H
14#define EIGEN_ARCH_GENERIC_PACKET_MATH_TRIG_H
17#include "../../InternalHeaderCheck.h"
29enum class TrigFunction : uint8_t { Sin, Cos, Tan, SinCos };
40inline float trig_reduce_huge(
float xf, Eigen::numext::int32_t* quadrant) {
41 using Eigen::numext::int32_t;
42 using Eigen::numext::int64_t;
43 using Eigen::numext::uint32_t;
44 using Eigen::numext::uint64_t;
46 const double pio2_62 = 3.4061215800865545e-19;
47 const uint64_t zero_dot_five = uint64_t(1) << 61;
51 static const uint32_t two_over_pi[] = {
52 0x00000028, 0x000028be, 0x0028be60, 0x28be60db, 0xbe60db93, 0x60db9391, 0xdb939105, 0x9391054a, 0x91054a7f,
53 0x054a7f09, 0x4a7f09d5, 0x7f09d5f4, 0x09d5f47d, 0xd5f47d4d, 0xf47d4d37, 0x7d4d3770, 0x4d377036, 0x377036d8,
54 0x7036d8a5, 0x36d8a566, 0xd8a5664f, 0xa5664f10, 0x664f10e4, 0x4f10e410, 0x10e41000, 0xe4100000};
56 uint32_t xi = numext::bit_cast<uint32_t>(xf);
61 uint32_t e = (xi >> 23) - 118;
63 xi = ((xi & 0x007fffffu) | 0x00800000u) << (e & 0x7);
66 uint32_t twoopi_1 = two_over_pi[i - 1];
67 uint32_t twoopi_2 = two_over_pi[i + 3];
68 uint32_t twoopi_3 = two_over_pi[i + 7];
72 p = uint64_t(xi) * twoopi_3;
73 p = uint64_t(xi) * twoopi_2 + (p >> 32);
74 p = (uint64_t(xi * twoopi_1) << 32) + p;
77 uint64_t q = (p + zero_dot_five) >> 62;
84 return float(
double(int64_t(p)) * pio2_62);
87template <TrigFunction Func,
typename Packet>
88EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psincos_float(
const Packet& _x) {
89 using PacketI =
typename unpacket_traits<Packet>::integer_packet;
91 const Packet cst_2oPI = pset1<Packet>(0.636619746685028076171875f);
92 const Packet cst_rounding_magic = pset1<Packet>(12582912);
93 const PacketI csti_1 = pset1<PacketI>(1);
94 const Packet cst_sign_mask = psignmask<Packet>();
99 Packet y = pmul(x, cst_2oPI);
102 Packet y_round = padd(y, cst_rounding_magic);
103 EIGEN_OPTIMIZATION_BARRIER(y_round)
104 PacketI y_int = preinterpret<PacketI>(y_round);
105 y = psub(y_round, cst_rounding_magic);
109#if defined(EIGEN_VECTORIZE_FMA)
112 constexpr float huge_th = (Func == TrigFunction::Sin) ? 117435.992f : 71476.0625f;
113 x = pmadd(y, pset1<Packet>(-1.57079601287841796875f), x);
114 x = pmadd(y, pset1<Packet>(-3.1391647326017846353352069854736328125e-07f), x);
115 x = pmadd(y, pset1<Packet>(-5.390302529957764765544681040410068817436695098876953125e-15f), x);
123 constexpr float huge_th = (Func == TrigFunction::Sin) ? 25966.f : 18838.f;
124 x = pmadd(y, pset1<Packet>(-1.5703125), x);
125 EIGEN_OPTIMIZATION_BARRIER(x)
126 x = pmadd(y, pset1<Packet>(-0.000483989715576171875), x);
127 EIGEN_OPTIMIZATION_BARRIER(x)
128 x = pmadd(y, pset1<Packet>(1.62865035235881805419921875e-07), x);
129 EIGEN_OPTIMIZATION_BARRIER(x)
130 x = pmadd(y, pset1<Packet>(5.5644315544167710640977020375430583953857421875e-11), x);
146 if (predux_any(pcmp_le(pset1<Packet>(huge_th), pabs(_x)))) {
147 const int PacketSize = unpacket_traits<Packet>::size;
148 EIGEN_ALIGN_TO_BOUNDARY(unpacket_traits<Packet>::alignment)
float vals[PacketSize];
149 EIGEN_ALIGN_TO_BOUNDARY(unpacket_traits<Packet>::alignment)
float x_cpy[PacketSize];
150 EIGEN_ALIGN_TO_BOUNDARY(unpacket_traits<Packet>::alignment) Eigen::numext::int32_t y_int2[PacketSize];
151 pstoreu(vals, pabs(_x));
153 pstoreu(y_int2, y_int);
154 for (
int k = 0; k < PacketSize; ++k) {
156 if (val >= huge_th && (numext::isfinite)(val)) x_cpy[k] = trig_reduce_huge(val, &y_int2[k]);
158 x = ploadu<Packet>(x_cpy);
159 y_int = ploadu<PacketI>(y_int2);
164 Packet poly_mask = preinterpret<Packet>(pcmp_eq(pand(y_int, csti_1), pzero(y_int)));
166 Packet x2 = pmul(x, x);
169 Packet y1 = pset1<Packet>(2.4372266125283204019069671630859375e-05f);
170 y1 = pmadd(y1, x2, pset1<Packet>(-0.00138865201734006404876708984375f));
171 y1 = pmadd(y1, x2, pset1<Packet>(0.041666619479656219482421875f));
172 y1 = pmadd(y1, x2, pset1<Packet>(-0.5f));
173 y1 = pmadd(y1, x2, pset1<Packet>(1.f));
183 Packet y2 = pset1<Packet>(-0.0001959234114083702898469196984621021329076029360294342041015625f);
184 y2 = pmadd(y2, x2, pset1<Packet>(0.0083326873655616851693794799871284340042620897293090820312500000f));
185 y2 = pmadd(y2, x2, pset1<Packet>(-0.1666666203982298255503735617821803316473960876464843750000000000f));
187 y2 = pmadd(y2, x, x);
193 Packet sign_bit = (Func == TrigFunction::Sin) ? pxor(_x, preinterpret<Packet>(plogical_shift_left<30>(y_int)))
194 : preinterpret<Packet>(plogical_shift_left<30>(padd(y_int, csti_1)));
195 sign_bit = pand(sign_bit, cst_sign_mask);
197 if ((Func == TrigFunction::SinCos) || (Func == TrigFunction::Tan)) {
198 Packet peven = peven_mask(x);
199 Packet ysin = pselect(poly_mask, y2, y1);
200 Packet ycos = pselect(poly_mask, y1, y2);
201 Packet sign_bit_sin = pxor(_x, preinterpret<Packet>(plogical_shift_left<30>(y_int)));
202 Packet sign_bit_cos = preinterpret<Packet>(plogical_shift_left<30>(padd(y_int, csti_1)));
203 sign_bit_sin = pand(sign_bit_sin, cst_sign_mask);
204 sign_bit_cos = pand(sign_bit_cos, cst_sign_mask);
205 y = (Func == TrigFunction::SinCos) ? pselect(peven, pxor(ysin, sign_bit_sin), pxor(ycos, sign_bit_cos))
206 : pdiv(pxor(ysin, sign_bit_sin), pxor(ycos, sign_bit_cos));
208 y = (Func == TrigFunction::Sin) ? pselect(poly_mask, y2, y1) : pselect(poly_mask, y1, y2);
209 y = pxor(y, sign_bit);
214template <
typename Packet>
215EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psin_float(
const Packet& x) {
216 return psincos_float<TrigFunction::Sin>(x);
219template <
typename Packet>
220EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcos_float(
const Packet& x) {
221 return psincos_float<TrigFunction::Cos>(x);
224template <
typename Packet>
225EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet ptan_float(
const Packet& x) {
226 return psincos_float<TrigFunction::Tan>(x);
232template <
typename Packet>
234 return pset1<Packet>(-1.5707963267948965579989817342720925807952880859375);
236template <
typename Packet>
238 return pset1<Packet>(-6.12323399573676603586882014729198302312846062338790e-17);
240template <
typename Packet>
242 return pset1<Packet>(1.4973849048591698329435081771059920083527504761695190e-33);
248template <
typename Packet>
249Packet trig_reduce_small_double(
const Packet& x,
const Packet& q) {
250#ifdef EIGEN_HAS_SINGLE_INSTRUCTION_MADD
254 t = pmadd(cst_pio2_1<Packet>(), q, x);
255 t = pmadd(cst_pio2_2<Packet>(), q, t);
256 t = pmadd(cst_pio2_3<Packet>(), q, t);
266 twoprod(cst_pio2_1<Packet>(), q, qp_hi, qp_lo);
270 Packet t_hi = padd(x, qp_hi);
271 Packet v = psub(t_hi, x);
272 Packet t_lo = padd(psub(x, psub(t_hi, v)), psub(qp_hi, v));
275 t_lo = padd(t_lo, qp_lo);
276 t_lo = pmadd(cst_pio2_2<Packet>(), q, t_lo);
277 t_lo = pmadd(cst_pio2_3<Packet>(), q, t_lo);
279 return padd(t_hi, t_lo);
283template <TrigFunction Func,
typename Packet>
284EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psincos_double(
const Packet& x) {
285 using PacketI =
typename unpacket_traits<Packet>::integer_packet;
286 using ScalarI =
typename unpacket_traits<PacketI>::type;
288 const Packet cst_sign_mask = psignmask<Packet>();
291 const double small_th = 15;
293 const double huge_th = 1e14;
296 const Packet cst_2oPI_hi =
297 pset1<Packet>(0.63661977236758138243288840385503135621547698974609375);
298 const Packet cst_2oPI_lo =
299 pset1<Packet>(-3.9357353350364971763790381828183628368294820823718866e-17);
301 const PacketI cst_one = pset1<PacketI>(ScalarI(1));
303 Packet x_abs = pabs(x);
309 if (EIGEN_PREDICT_FALSE(predux_any(pcmp_le(pset1<Packet>(small_th), x_abs)))) {
311 Packet prod_hi, prod_lo;
312 twoprod(x_abs, cst_2oPI_hi, prod_hi, prod_lo);
314 prod_lo = pmadd(x_abs, cst_2oPI_lo, prod_lo);
317 Packet q = pround(prod_hi);
319 Packet frac = padd(psub(prod_hi, q), prod_lo);
321 q = padd(q, pand(pcmp_lt(pset1<Packet>(0.5), frac), pset1<Packet>(1.0)));
322 q = padd(q, pand(pcmp_lt(frac, pset1<Packet>(-0.5)), pset1<Packet>(-1.0)));
324 q_int = pcast<Packet, PacketI>(q);
325 s = trig_reduce_small_double(x_abs, q);
328 Packet qval_noround = pmul(x_abs, cst_2oPI_hi);
329 q_int = pcast<Packet, PacketI>(padd(qval_noround, pset1<Packet>(0.5)));
330 Packet q = pcast<PacketI, Packet>(q_int);
331 s = trig_reduce_small_double(x_abs, q);
334 Packet ss = pmul(s, s);
339 Packet scos = pset1<Packet>(-1.1368926065317776472832699312119132152576472805094454088248312473297119140625e-11);
340 scos = pmadd(scos, ss, pset1<Packet>(2.0875905481768720039634091158002593413556269297259859740734100341796875e-09));
341 scos = pmadd(scos, ss, pset1<Packet>(-2.7557315712466412785356544880299711763882442028261721134185791015625e-07));
342 scos = pmadd(scos, ss, pset1<Packet>(2.480158729424286522739599714082459058772656135261058807373046875e-05));
343 scos = pmadd(scos, ss, pset1<Packet>(-1.388888888888178789471350427220386336557567119598388671875e-03));
344 scos = pmadd(scos, ss, pset1<Packet>(4.166666666666664353702032030923874117434024810791015625e-02));
345 scos = pmadd(scos, ss, pset1<Packet>(-0.5));
346 scos = pmadd(scos, ss, pset1<Packet>(1.0));
352 Packet ssin = pset1<Packet>(1.59193066075142890698150587293845624470289834562208852730691432952880859375e-10);
353 ssin = pmadd(ssin, ss, pset1<Packet>(-2.50511517945670206974594627392927126408039839589037001132965087890625e-08));
354 ssin = pmadd(ssin, ss, pset1<Packet>(2.755731622544328228235042954619160582296899519860744476318359375e-06));
355 ssin = pmadd(ssin, ss, pset1<Packet>(-1.9841269837089632013978068858506276228581555187702178955078125e-04));
356 ssin = pmadd(ssin, ss, pset1<Packet>(8.333333333331312264835588621281203813850879669189453125e-03));
357 ssin = pmadd(ssin, ss, pset1<Packet>(-0.1666666666666666574148081281236954964697360992431640625));
358 ssin = pmul(ssin, ss);
359 ssin = pmadd(ssin, s, s);
361 Packet poly_mask = preinterpret<Packet>(pcmp_eq(pand(q_int, cst_one), pzero(q_int)));
363 Packet sign_sin = pxor(x, preinterpret<Packet>(plogical_shift_left<62>(q_int)));
364 Packet sign_cos = preinterpret<Packet>(plogical_shift_left<62>(padd(q_int, cst_one)));
365 Packet sign_bit, sFinalRes;
366 if (Func == TrigFunction::Sin) {
368 sFinalRes = pselect(poly_mask, ssin, scos);
369 }
else if (Func == TrigFunction::Cos) {
371 sFinalRes = pselect(poly_mask, scos, ssin);
372 }
else if (Func == TrigFunction::Tan) {
373 sign_bit = pxor(sign_sin, sign_cos);
374 sFinalRes = pdiv(pselect(poly_mask, ssin, scos), pselect(poly_mask, scos, ssin));
375 }
else if (Func == TrigFunction::SinCos) {
376 Packet peven = peven_mask(x);
377 sign_bit = pselect(peven, sign_sin, sign_cos);
378 sFinalRes = pselect(pxor(peven, poly_mask), scos, ssin);
380 sign_bit = pand(sign_bit, cst_sign_mask);
381 sFinalRes = pxor(sFinalRes, sign_bit);
386 if (EIGEN_PREDICT_FALSE(predux_any(pcmp_le(pset1<Packet>(huge_th), x_abs)))) {
387 const int PacketSize = unpacket_traits<Packet>::size;
388 EIGEN_ALIGN_TO_BOUNDARY(unpacket_traits<Packet>::alignment)
double sincos_vals[PacketSize];
389 EIGEN_ALIGN_TO_BOUNDARY(unpacket_traits<Packet>::alignment)
double x_cpy[PacketSize];
391 pstoreu(sincos_vals, sFinalRes);
392 for (
int k = 0; k < PacketSize; ++k) {
393 double val = x_cpy[k];
394 if (numext::abs(val) > huge_th && (numext::isfinite)(val)) {
395 if (Func == TrigFunction::Sin) {
396 sincos_vals[k] = numext::sin(val);
397 }
else if (Func == TrigFunction::Cos) {
398 sincos_vals[k] = numext::cos(val);
399 }
else if (Func == TrigFunction::Tan) {
400 sincos_vals[k] = numext::tan(val);
401 }
else if (Func == TrigFunction::SinCos) {
402 sincos_vals[k] = k % 2 == 0 ? numext::sin(val) : numext::cos(val);
406 sFinalRes = ploadu<Packet>(sincos_vals);
411template <
typename Packet>
412EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psin_double(
const Packet& x) {
413 return psincos_double<TrigFunction::Sin>(x);
416template <
typename Packet>
417EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcos_double(
const Packet& x) {
418 return psincos_double<TrigFunction::Cos>(x);
421template <
typename Packet>
422EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet ptan_double(
const Packet& x) {
423 return psincos_double<TrigFunction::Tan>(x);
426template <
typename Packet>
427EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
428 std::enable_if_t<std::is_same<typename unpacket_traits<Packet>::type,
float>::value, Packet>
429 psincos_selector(
const Packet& x) {
430 return psincos_float<TrigFunction::SinCos, Packet>(x);
433template <
typename Packet>
434EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
435 std::enable_if_t<std::is_same<typename unpacket_traits<Packet>::type,
double>::value, Packet>
436 psincos_selector(
const Packet& x) {
437 return psincos_double<TrigFunction::SinCos, Packet>(x);
445template <
typename Packet>
446EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pacos_float(
const Packet& x_in) {
447 using Scalar =
typename unpacket_traits<Packet>::type;
448 static_assert(std::is_same<Scalar, float>::value,
"Scalar type must be float");
450 const Packet cst_one = pset1<Packet>(Scalar(1));
451 const Packet cst_pi = pset1<Packet>(Scalar(EIGEN_PI));
452 const Packet p6 = pset1<Packet>(Scalar(2.36423197202384471893310546875e-3));
453 const Packet p5 = pset1<Packet>(Scalar(-1.1368644423782825469970703125e-2));
454 const Packet p4 = pset1<Packet>(Scalar(2.717843465507030487060546875e-2));
455 const Packet p3 = pset1<Packet>(Scalar(-4.8969544470310211181640625e-2));
456 const Packet p2 = pset1<Packet>(Scalar(8.8804088532924652099609375e-2));
457 const Packet p1 = pset1<Packet>(Scalar(-0.214591205120086669921875));
458 const Packet p0 = pset1<Packet>(Scalar(1.57079637050628662109375));
463 const Packet neg_mask = psignbit(x_in);
464 const Packet abs_x = pabs(x_in);
470 Packet x2 = pmul(x_in, x_in);
471 Packet p_even = pmadd(p6, x2, p4);
472 Packet p_odd = pmadd(p5, x2, p3);
473 p_even = pmadd(p_even, x2, p2);
474 p_odd = pmadd(p_odd, x2, p1);
475 p_even = pmadd(p_even, x2, p0);
476 Packet p = pmadd(p_odd, abs_x, p_even);
481 Packet denom = psqrt(psub(cst_one, abs_x));
482 Packet result = pmul(denom, p);
484 return pselect(neg_mask, psub(cst_pi, result), result);
488template <
typename Packet>
489EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pasin_float(
const Packet& x_in) {
490 using Scalar =
typename unpacket_traits<Packet>::type;
491 static_assert(std::is_same<Scalar, float>::value,
"Scalar type must be float");
493 constexpr float kPiOverTwo =
static_cast<float>(EIGEN_PI / 2);
495 const Packet cst_half = pset1<Packet>(0.5f);
496 const Packet cst_one = pset1<Packet>(1.0f);
497 const Packet cst_two = pset1<Packet>(2.0f);
498 const Packet cst_pi_over_two = pset1<Packet>(kPiOverTwo);
500 const Packet abs_x = pabs(x_in);
501 const Packet sign_mask = pandnot(x_in, abs_x);
502 const Packet invalid_mask = pcmp_lt(cst_one, abs_x);
509 const Packet x_large = psqrt(pnmadd(cst_half, abs_x, cst_half));
510 const Packet large_mask = pcmp_lt(cst_half, abs_x);
511 const Packet x = pselect(large_mask, x_large, abs_x);
512 const Packet x2 = pmul(x, x);
516 constexpr float alpha[] = {5.08838854730129241943359375e-2f, 3.95139865577220916748046875e-2f,
517 7.550220191478729248046875e-2f, 0.16664917767047882080078125f, 1.00000011920928955078125f};
518 Packet p = ppolevl<Packet, 4>::run(x2, alpha);
521 const Packet p_large = pnmadd(cst_two, p, cst_pi_over_two);
522 p = pselect(large_mask, p_large, p);
524 p = pxor(p, sign_mask);
526 return por(invalid_mask, p);
529template <
typename Scalar>
530struct patan_reduced {
531 template <
typename Packet>
532 static EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet run(
const Packet& x);
536template <
typename Packet>
537EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patan_reduced<double>::run(
const Packet& x) {
538 constexpr double alpha[] = {2.6667153866462208e-05, 3.0917513112462781e-03, 5.2574296781008604e-02,
539 3.0409318473444424e-01, 7.5365702534987022e-01, 8.2704055405494614e-01,
540 3.3004361289279920e-01};
542 constexpr double beta[] = {
543 2.7311202462436667e-04, 1.0899150928962708e-02, 1.1548932646420353e-01, 4.9716458728465573e-01, 1.0,
544 9.3705509168587852e-01, 3.3004361289279920e-01};
546 Packet x2 = pmul(x, x);
547 Packet p = ppolevl<Packet, 6>::run(x2, alpha);
548 Packet q = ppolevl<Packet, 6>::run(x2, beta);
549 return pmul(x, pdiv(p, q));
554template <
typename Packet>
555EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patan_reduced<float>::run(
const Packet& x) {
556 constexpr float alpha[] = {1.12026982009410858154296875e-01f, 7.296695709228515625e-01f, 8.109951019287109375e-01f};
558 constexpr float beta[] = {1.00917108356952667236328125e-02f, 2.8318560123443603515625e-01f, 1.0f,
559 8.109951019287109375e-01f};
561 Packet x2 = pmul(x, x);
562 Packet p = ppolevl<Packet, 2>::run(x2, alpha);
563 Packet q = ppolevl<Packet, 3>::run(x2, beta);
564 return pmul(x, pdiv(p, q));
567template <
typename Packet>
568EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet generic_atan(
const Packet& x_in) {
569 using Scalar =
typename unpacket_traits<Packet>::type;
571 constexpr Scalar kPiOverTwo =
static_cast<Scalar
>(EIGEN_PI / 2);
573 const Packet cst_signmask = psignmask<Packet>();
574 const Packet cst_one = pset1<Packet>(Scalar(1));
575 const Packet cst_pi_over_two = pset1<Packet>(kPiOverTwo);
581 const Packet abs_x = pabs(x_in);
582 const Packet x_signmask = pand(x_in, cst_signmask);
583 const Packet large_mask = pcmp_lt(cst_one, abs_x);
584 const Packet x = pselect(large_mask, preciprocal(abs_x), abs_x);
585 const Packet p = patan_reduced<Scalar>::run(x);
587 Packet result = pselect(large_mask, psub(cst_pi_over_two, p), p);
589 return pxor(result, x_signmask);
596#ifdef EIGEN_FAST_MATH
608EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS T ptanh_float(
const T& a_x) {
613#ifdef EIGEN_VECTORIZE_FMA
614 const T plus_clamp = pset1<T>(8.01773357391357422f);
615 const T minus_clamp = pset1<T>(-8.01773357391357422f);
617 const T plus_clamp = pset1<T>(7.90738964080810547f);
618 const T minus_clamp = pset1<T>(-7.90738964080810547f);
620 const T x = pmax(pmin(a_x, plus_clamp), minus_clamp);
630 constexpr float alpha[] = {1.394553628e-8f, 2.102733560e-5f, 3.520756727e-3f, 1.340216100e-1f};
633 constexpr float beta[] = {8.015776984e-7f, 3.326951409e-4f, 2.597254514e-2f, 4.673548340e-1f, 1.0f};
636 const T x2 = pmul(x, x);
637 const T x3 = pmul(x2, x);
639 T p = ppolevl<T, 3>::run(x2, alpha);
640 T q = ppolevl<T, 4>::run(x2, beta);
661EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS T ptanh_float(
const T& x) {
665 constexpr float alpha[] = {-1.46725140511989593505859375e-02f, -3.333333432674407958984375e-01f};
666 constexpr float beta[] = {1.570280082523822784423828125e-02, 4.4401752948760986328125e-01, 1.0f};
667 const T x2 = pmul(x, x);
668 const T x3 = pmul(x2, x);
669 const T p = ppolevl<T, 1>::run(x2, alpha);
670 const T q = ppolevl<T, 2>::run(x2, beta);
671 const T small_tanh = pmadd(x3, pdiv(p, q), x);
673 const T sign_mask = psignmask<T>();
674 const T abs_x = pandnot(x, sign_mask);
675 constexpr float kSmallThreshold = 1.25f;
676 const T large_mask = pcmp_lt(pset1<T>(kSmallThreshold), abs_x);
678 if (!predux_any(large_mask)) {
683 const T one = pset1<T>(1.0f);
684 const T two = pset1<T>(2.0f);
685 const T s = pexp_float<T, true>(pmul(two, abs_x));
686 const T abs_tanh = psub(one, pdiv(two, padd(s, one)));
689 constexpr float kHugeThreshold = 16.0f;
690 const T huge_mask = pcmp_lt(pset1<T>(kHugeThreshold), abs_x);
691 const T x_sign = pand(sign_mask, x);
692 const T large_tanh = por(x_sign, pselect(huge_mask, one, abs_tanh));
693 return pselect(large_mask, large_tanh, small_tanh);
708EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS T ptanh_double(
const T& a_x) {
713#ifdef EIGEN_VECTORIZE_FMA
714 const T plus_clamp = pset1<T>(17.6610191624600077);
715 const T minus_clamp = pset1<T>(-17.6610191624600077);
717 const T plus_clamp = pset1<T>(17.714196154005176);
718 const T minus_clamp = pset1<T>(-17.714196154005176);
720 const T x = pmax(pmin(a_x, plus_clamp), minus_clamp);
729 constexpr double alpha[] = {2.6158007860482230e-23, 7.6534862268749319e-19, 3.1309488231386680e-15,
730 4.2303918148209176e-12, 2.4618379131293676e-09, 6.8644367682497074e-07,
731 9.3839087674268880e-05, 5.9809711724441161e-03, 1.5184719640284322e-01};
734 constexpr double beta[] = {6.463747022670968018e-21, 5.782506856739003571e-17,
735 1.293019623712687916e-13, 1.123643448069621992e-10,
736 4.492975677839633985e-08, 8.785185266237658698e-06,
737 8.295161192716231542e-04, 3.437448108450402717e-02,
738 4.851805297361760360e-01, 1.0};
741 const T x2 = pmul(x, x);
742 const T x3 = pmul(x2, x);
746 T p = ppolevl<T, 8>::run(x2, alpha);
747 T q = ppolevl<T, 9>::run(x2, beta);
756template <
typename Packet>
757EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patanh_float(
const Packet& x) {
758 using Scalar =
typename unpacket_traits<Packet>::type;
759 static_assert(std::is_same<Scalar, float>::value,
"Scalar type must be float");
763 constexpr float alpha[] = {0.1819281280040740966796875f, 8.2311116158962249755859375e-2f,
764 0.14672131836414337158203125f, 0.1997792422771453857421875f, 0.3333373963832855224609375f};
765 const Packet x2 = pmul(x, x);
766 const Packet x3 = pmul(x, x2);
767 Packet p = ppolevl<Packet, 4>::run(x2, alpha);
770 const Packet half = pset1<Packet>(0.5f);
771 const Packet one = pset1<Packet>(1.0f);
772 const Packet x_gt_half = pcmp_le(half, pabs(x));
774 if (!predux_any(x_gt_half)) {
779 Packet r = pdiv(padd(one, x), psub(one, x));
780 r = pmul(half, plog(r));
782 const Packet x_eq_one = pcmp_eq(one, pabs(x));
783 const Packet x_gt_one = pcmp_lt(one, pabs(x));
784 const Packet sign_mask = psignmask<Packet>();
785 const Packet x_sign = pand(sign_mask, x);
786 const Packet inf = pinf<Packet>();
787 return por(x_gt_one, pselect(x_eq_one, por(x_sign, inf), pselect(x_gt_half, r, p)));
790template <
typename Packet>
791EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patanh_double(
const Packet& x) {
792 using Scalar =
typename unpacket_traits<Packet>::type;
793 static_assert(std::is_same<Scalar, double>::value,
"Scalar type must be double");
796 constexpr double alpha[] = {3.3071338469301391e-03, -4.7129526768798737e-02, 1.8185306179826699e-01,
797 -2.5949536095445679e-01, 1.2306328729812676e-01};
799 constexpr double beta[] = {-3.8679974580640881e-03, 7.6391885763341910e-02, -4.2828141436397615e-01,
800 9.8733495886883648e-01, -1.0000000000000000e+00, 3.6918986189438030e-01};
802 const Packet x2 = pmul(x, x);
803 const Packet x3 = pmul(x, x2);
804 Packet p = ppolevl<Packet, 4>::run(x2, alpha);
805 Packet q = ppolevl<Packet, 5>::run(x2, beta);
806 Packet y_small = pmadd(x3, pdiv(p, q), x);
808 const Packet half = pset1<Packet>(0.5);
809 const Packet one = pset1<Packet>(1.0);
810 const Packet x_gt_half = pcmp_le(half, pabs(x));
812 if (!predux_any(x_gt_half)) {
817 Packet y_large = pdiv(padd(one, x), psub(one, x));
818 y_large = pmul(half, plog(y_large));
820 const Packet x_eq_one = pcmp_eq(one, pabs(x));
821 const Packet x_gt_one = pcmp_lt(one, pabs(x));
822 const Packet sign_mask = psignmask<Packet>();
823 const Packet x_sign = pand(sign_mask, x);
824 const Packet inf = pinf<Packet>();
825 return por(x_gt_one, pselect(x_eq_one, por(x_sign, inf), pselect(x_gt_half, y_large, y_small)));
839template <
typename Packet>
840EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psinh_float(
const Packet& x) {
841 using Scalar =
typename unpacket_traits<Packet>::type;
842 static_assert(std::is_same<Scalar, float>::value,
"Scalar type must be float");
844 const Packet sign_mask = psignmask<Packet>();
845 const Packet abs_x = pandnot(x, sign_mask);
846 const Packet x_sign = pand(x, sign_mask);
850 constexpr float alpha[] = {2.7557314045e-06f, 1.9841270114e-04f, 8.3333335817e-03f, 1.6666666716e-01f};
851 const Packet x2 = pmul(x, x);
852 Packet p_small = ppolevl<Packet, 3>::run(x2, alpha);
853 p_small = pmadd(pmul(x2, x), p_small, x);
859 const Packet half_e = pset1<Packet>(1.3591409142295225f);
860 const Packet one = pset1<Packet>(1.0f);
861 const Packet e = pmul(pexp(psub(abs_x, one)), half_e);
866 const Packet quarter = pset1<Packet>(0.25f);
867 Packet p_medium = psub(e, pdiv(quarter, e));
870 const Packet large_threshold = pset1<Packet>(20.0f);
871 const Packet large_mask = pcmp_lt(large_threshold, abs_x);
872 Packet p_large = pselect(large_mask, e, p_medium);
873 p_large = por(x_sign, p_large);
875 const Packet small_mask = pcmp_lt(abs_x, one);
876 return pselect(small_mask, p_small, p_large);
879template <
typename Packet>
880EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psinh_double(
const Packet& x) {
881 using Scalar =
typename unpacket_traits<Packet>::type;
882 static_assert(std::is_same<Scalar, double>::value,
"Scalar type must be double");
884 const Packet sign_mask = psignmask<Packet>();
885 const Packet abs_x = pandnot(x, sign_mask);
886 const Packet x_sign = pand(x, sign_mask);
891 constexpr double alpha[] = {
892 8.2206352466243297e-18,
893 2.8114572543455206e-15,
894 7.6471637318198164e-13,
895 1.6059043836821613e-10,
896 2.5052108385441718e-08,
897 2.7557319223985893e-06,
898 1.9841269841269841e-04,
899 8.3333333333333332e-03,
900 1.6666666666666666e-01,
902 const Packet x2 = pmul(x, x);
903 Packet p_small = ppolevl<Packet, 8>::run(x2, alpha);
904 p_small = pmadd(pmul(x2, x), p_small, x);
909 const Packet half_e = pset1<Packet>(1.3591409142295225);
910 const Packet one = pset1<Packet>(1.0);
911 const Packet e = pmul(pexp(psub(abs_x, one)), half_e);
915 const Packet quarter = pset1<Packet>(0.25);
916 Packet p_medium = psub(e, pdiv(quarter, e));
919 const Packet large_threshold = pset1<Packet>(20.0);
920 const Packet large_mask = pcmp_lt(large_threshold, abs_x);
921 Packet p_large = pselect(large_mask, e, p_medium);
922 p_large = por(x_sign, p_large);
923 const Packet small_mask = pcmp_lt(abs_x, one);
924 return pselect(small_mask, p_small, p_large);
933template <
typename Packet>
934EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcosh_float(
const Packet& x) {
935 const Packet abs_x = pabs(x);
941 const Packet half_e = pset1<Packet>(1.3591409142295225f);
942 const Packet one = pset1<Packet>(1.0f);
943 const Packet e = pmul(pexp(psub(abs_x, one)), half_e);
947 const Packet quarter = pset1<Packet>(0.25f);
948 Packet p_medium = padd(e, pdiv(quarter, e));
951 const Packet large_threshold = pset1<Packet>(20.0f);
952 const Packet large_mask = pcmp_lt(large_threshold, abs_x);
953 return pselect(large_mask, e, p_medium);
956template <
typename Packet>
957EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcosh_double(
const Packet& x) {
958 const Packet abs_x = pabs(x);
963 const Packet half_e = pset1<Packet>(1.3591409142295225);
964 const Packet one = pset1<Packet>(1.0);
965 const Packet e = pmul(pexp(psub(abs_x, one)), half_e);
968 const Packet quarter = pset1<Packet>(0.25);
969 Packet p_medium = padd(e, pdiv(quarter, e));
972 const Packet large_threshold = pset1<Packet>(20.0);
973 const Packet large_mask = pcmp_lt(large_threshold, abs_x);
974 return pselect(large_mask, e, p_medium);
986template <
typename Packet>
987EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pasinh_float(
const Packet& x) {
988 const Packet sign_mask = psignmask<Packet>();
989 const Packet abs_x = pandnot(x, sign_mask);
990 const Packet x_sign = pand(x, sign_mask);
991 const Packet one = pset1<Packet>(1.0f);
994 const Packet large_mask = pcmp_lt(pset1<Packet>(1e10f), abs_x);
996 const Packet x2 = pmul(abs_x, pselect(large_mask, pzero(abs_x), abs_x));
1000 Packet normal_arg = padd(abs_x, pdiv(x2, padd(one, psqrt(padd(one, x2)))));
1002 Packet large_arg = psub(abs_x, one);
1004 Packet result = generic_log1p(pselect(large_mask, large_arg, normal_arg));
1006 const Packet ln2 = pset1<Packet>(0.6931471805599453f);
1007 result = pselect(large_mask, padd(result, ln2), result);
1008 return por(x_sign, result);
1011template <
typename Packet>
1012EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pasinh_double(
const Packet& x) {
1013 const Packet sign_mask = psignmask<Packet>();
1014 const Packet abs_x = pandnot(x, sign_mask);
1015 const Packet x_sign = pand(x, sign_mask);
1016 const Packet one = pset1<Packet>(1.0);
1018 const Packet large_mask = pcmp_lt(pset1<Packet>(1e150), abs_x);
1019 const Packet x2 = pmul(abs_x, pselect(large_mask, pzero(abs_x), abs_x));
1020 Packet normal_arg = padd(abs_x, pdiv(x2, padd(one, psqrt(padd(one, x2)))));
1021 Packet large_arg = psub(abs_x, one);
1022 Packet result = generic_log1p(pselect(large_mask, large_arg, normal_arg));
1023 const Packet ln2 = pset1<Packet>(0.6931471805599453);
1024 result = pselect(large_mask, padd(result, ln2), result);
1025 return por(x_sign, result);
1034template <
typename Packet>
1035EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pacosh_float(
const Packet& x) {
1036 const Packet one = pset1<Packet>(1.0f);
1037 const Packet two = pset1<Packet>(2.0f);
1038 const Packet t = psub(x, one);
1039 const Packet huge_mask = pcmp_lt(pset1<Packet>(1e10f), x);
1041 const Packet t_tp2 = pmul(pselect(huge_mask, pzero(t), t), padd(t, two));
1042 Packet normal_arg = padd(t, psqrt(t_tp2));
1044 Packet huge_arg = t;
1046 Packet result = generic_log1p(pselect(huge_mask, huge_arg, normal_arg));
1047 const Packet ln2 = pset1<Packet>(0.6931471805599453f);
1048 result = pselect(huge_mask, padd(result, ln2), result);
1050 const Packet invalid_mask = pcmp_lt(x, one);
1051 return por(invalid_mask, result);
1054template <
typename Packet>
1055EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pacosh_double(
const Packet& x) {
1056 const Packet one = pset1<Packet>(1.0);
1057 const Packet two = pset1<Packet>(2.0);
1058 const Packet t = psub(x, one);
1059 const Packet huge_mask = pcmp_lt(pset1<Packet>(1e150), x);
1060 const Packet t_tp2 = pmul(pselect(huge_mask, pzero(t), t), padd(t, two));
1061 Packet normal_arg = padd(t, psqrt(t_tp2));
1062 Packet huge_arg = t;
1063 Packet result = generic_log1p(pselect(huge_mask, huge_arg, normal_arg));
1064 const Packet ln2 = pset1<Packet>(0.6931471805599453);
1065 result = pselect(huge_mask, padd(result, ln2), result);
1066 const Packet invalid_mask = pcmp_lt(x, one);
1067 return por(invalid_mask, result);