11#ifndef EIGEN_ARCH_GENERIC_PACKET_MATH_POW_H
12#define EIGEN_ARCH_GENERIC_PACKET_MATH_POW_H
15#include "../../InternalHeaderCheck.h"
27template <
typename Packet>
28EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet cbrt_halley_iteration_step(
const Packet& x_k,
30 using Scalar =
typename unpacket_traits<Packet>::type;
31 Packet x_k_cb = pmul(x_k, pmul(x_k, x_k));
32 Packet denom = pmadd(pset1<Packet>(Scalar(2)), x_k_cb, y);
33 Packet num = psub(x_k_cb, y);
34 Packet r = pdiv(num, denom);
35 return pnmadd(x_k, r, x_k);
40template <
typename Packet>
41EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet cbrt_decompose(
const Packet& x, Packet& e_div3) {
42 using Scalar =
typename unpacket_traits<Packet>::type;
50 constexpr Scalar kOneThird = Scalar(1) / 3;
51 e_div3 = pceil(pmul(e, pset1<Packet>(kOneThird)));
52 Packet e_mod3 = pnmadd(pset1<Packet>(Scalar(3)), e_div3, e);
55 return pldexp_fast(s, e_mod3);
58template <
typename Packet>
59EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet cbrt_special_cases_and_sign(
const Packet& x,
60 const Packet& abs_root) {
62 const Packet sign_mask = psignmask<Packet>();
63 const Packet x_sign = pand(sign_mask, x);
64 Packet root = por(x_sign, abs_root);
67 const Packet is_not_finite = por(pisinf(x), pisnan(x));
68 const Packet is_zero = pcmp_eq(pzero(x), x);
69 const Packet use_x = por(is_not_finite, is_zero);
70 return pselect(use_x, x, root);
101template <
typename Packet>
102EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcbrt_float(
const Packet& x) {
103 using Scalar =
typename unpacket_traits<Packet>::type;
104 static_assert(std::is_same<Scalar, float>::value,
"Scalar type must be float");
109 const Packet y = cbrt_decompose(pabs(x), e_div3);
113 constexpr float alpha[] = {5.9220016002655029296875e-01f, -1.3859539031982421875e+00f, 1.4581282138824462890625e+00f,
114 3.408401906490325927734375e-01f};
115 Packet r = ppolevl<Packet, 3>::run(y, alpha);
118 r = cbrt_halley_iteration_step(r, y);
121 r = pldexp_fast(r, e_div3);
123 return cbrt_special_cases_and_sign(x, r);
132template <
typename Packet>
133EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcbrt_double(
const Packet& x) {
134 using Scalar =
typename unpacket_traits<Packet>::type;
135 static_assert(std::is_same<Scalar, double>::value,
"Scalar type must be double");
140 const Packet y = cbrt_decompose(pabs(x), e_div3);
144 constexpr double alpha[] = {-4.69470621553356115551736138513660989701747894287109375e-01,
145 1.072314636518546304699839311069808900356292724609375e+00,
146 3.81249427609571867048288140722434036433696746826171875e-01};
147 Packet r = ppolevl<Packet, 2>::run(y, alpha);
150 r = cbrt_halley_iteration_step(r, y);
151 r = cbrt_halley_iteration_step(r, y);
154 r = pldexp_fast(r, e_div3);
155 return cbrt_special_cases_and_sign(x, r);
163template <
typename Scalar>
164struct accurate_log2 {
165 template <
typename Packet>
166 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void operator()(
const Packet& x, Packet& log2_x_hi, Packet& log2_x_lo)
const {
167 log2_x_hi = plog2(x);
168 log2_x_lo = pzero(x);
185struct accurate_log2<float> {
186 template <
typename Packet>
187 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void operator()(
const Packet& z, Packet& log2_x_hi, Packet& log2_x_lo)
const {
189 constexpr double kC0 = 1.442695041742110273474963832995854318141937255859375e+00;
190 constexpr float kC0_hi =
static_cast<float>(kC0);
191 constexpr float kC0_lo =
static_cast<float>(kC0 -
static_cast<double>(kC0_hi));
192 const Packet c0_hi = pset1<Packet>(kC0_hi);
193 const Packet c0_lo = pset1<Packet>(kC0_lo);
195 constexpr double kC1 = -7.2134751588268664068692714863573201000690460205078125e-01;
196 constexpr float kC1_hi =
static_cast<float>(kC1);
197 constexpr float kC1_lo =
static_cast<float>(kC1 -
static_cast<double>(kC1_hi));
198 const Packet c1_hi = pset1<Packet>(kC1_hi);
199 const Packet c1_lo = pset1<Packet>(kC1_lo);
201 constexpr float c[] = {
202 9.7010828554630279541015625e-02, -1.6896486282348632812500000e-01, 1.7200836539268493652343750e-01,
203 -1.7892272770404815673828125e-01, 2.0505344867706298828125000e-01, -2.4046677350997924804687500e-01,
204 2.8857553005218505859375000e-01, -3.6067414283752441406250000e-01, 4.8089790344238281250000000e-01};
208 const Packet one = pset1<Packet>(1.0f);
209 const Packet x = psub(z, one);
210 Packet p = ppolevl<Packet, 8>::run(x, c);
214 twoprod(x, p, p_hi, p_lo);
215 fast_twosum(c1_hi, c1_lo, p_hi, p_lo, p_hi, p_lo);
216 twoprod(p_hi, p_lo, x, p_hi, p_lo);
217 fast_twosum(c0_hi, c0_lo, p_hi, p_lo, p_hi, p_lo);
219 twoprod(p_hi, p_lo, x, log2_x_hi, log2_x_lo);
231struct accurate_log2<double> {
232 template <
typename Packet>
233 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void operator()(
const Packet& x, Packet& log2_x_hi, Packet& log2_x_lo)
const {
255 const Packet q12 = pset1<Packet>(2.87074255468000586e-9);
256 const Packet q10 = pset1<Packet>(2.38957980901884082e-8);
257 const Packet q8 = pset1<Packet>(2.31032094540014656e-7);
258 const Packet q6 = pset1<Packet>(2.27279857398537278e-6);
259 const Packet q4 = pset1<Packet>(2.31271023278625638e-5);
260 const Packet q2 = pset1<Packet>(2.47556738444535513e-4);
261 const Packet q0 = pset1<Packet>(2.88543873228900172e-3);
262 const Packet C_hi = pset1<Packet>(0.0400377511598501157);
263 const Packet C_lo = pset1<Packet>(-4.77726582251425391e-19);
264 const Packet one = pset1<Packet>(1.0);
266 const Packet cst_2_log2e_hi = pset1<Packet>(2.88539008177792677);
267 const Packet cst_2_log2e_lo = pset1<Packet>(4.07660016854549667e-17);
271 twoprod(cst_2_log2e_hi, cst_2_log2e_lo, psub(x, one), t_hi, t_lo);
274 doubleword_div_fp(t_hi, t_lo, padd(x, one), r_hi, r_lo);
278 twoprod(r_hi, r_lo, r_hi, r_lo, r2_hi, r2_lo);
281 twoprod(r2_hi, r2_lo, r2_hi, r2_lo, r4_hi, r4_lo);
285 Packet q_even = pmadd(q12, r4_hi, q8);
286 Packet q_odd = pmadd(q10, r4_hi, q6);
287 q_even = pmadd(q_even, r4_hi, q4);
288 q_odd = pmadd(q_odd, r4_hi, q2);
289 q_even = pmadd(q_even, r4_hi, q0);
290 Packet q = pmadd(q_odd, r2_hi, q_even);
298 twoprod(r2_hi, r2_lo, q, p_hi, p_lo);
301 fast_twosum(C_hi, C_lo, p_hi, p_lo, p1_hi, p1_lo);
304 twoprod(r2_hi, r2_lo, p1_hi, p1_lo, p2_hi, p2_lo);
307 fast_twosum(one, p2_hi, p2_lo, p3_hi, p3_lo);
310 twoprod(p3_hi, p3_lo, r_hi, r_lo, log2_x_hi, log2_x_lo);
319template <
typename Packet>
320EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet generic_pow_impl(
const Packet& x,
const Packet& y) {
321 using Scalar =
typename unpacket_traits<Packet>::type;
324 Packet m_x = pfrexp(x, e_x);
327 constexpr Scalar sqrt_half = Scalar(0.70710678118654752440);
328 const Packet m_x_scale_mask = pcmp_lt(m_x, pset1<Packet>(sqrt_half));
329 m_x = pselect(m_x_scale_mask, pmul(pset1<Packet>(Scalar(2)), m_x), m_x);
330 e_x = pselect(m_x_scale_mask, psub(e_x, pset1<Packet>(Scalar(1))), e_x);
334 accurate_log2<Scalar>()(m_x, rx_hi, rx_lo);
338 Packet f1_hi, f1_lo, f2_hi, f2_lo;
339 twoprod(e_x, y, f1_hi, f1_lo);
340 twoprod(rx_hi, rx_lo, y, f2_hi, f2_lo);
348 fast_twosum(f1_hi, f1_lo, f2_hi, f2_lo, f_hi, f_lo);
352 absolute_split(f_hi, n_z, r_z);
353 r_z = padd(r_z, f_lo);
355 absolute_split(r_z, n_r, r_z);
356 n_z = padd(n_z, n_r);
362 const Packet e_r = generic_exp2_reduced(r_z);
366 constexpr Scalar kPldExpThresh = std::numeric_limits<Scalar>::max_exponent - 2;
367 const Packet pldexp_fast_unsafe = pcmp_lt(pset1<Packet>(kPldExpThresh), pabs(n_z));
368 if (predux_any(pldexp_fast_unsafe)) {
369 return pldexp(e_r, n_z);
371 return pldexp_fast(e_r, n_z);
375template <
typename Packet>
376EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS std::enable_if_t<!is_scalar<Packet>::value, Packet> generic_pow(
377 const Packet& x,
const Packet& y) {
378 using Scalar =
typename unpacket_traits<Packet>::type;
380 const Packet cst_inf = pinf<Packet>();
381 const Packet cst_zero = pset1<Packet>(Scalar(0));
382 const Packet cst_one = pset1<Packet>(Scalar(1));
384 const Packet x_abs = pabs(x);
385 Packet result = generic_pow_impl(x_abs, y);
391 const Packet x_is_negative = pcmp_lt(x, cst_zero);
392 const Packet x_is_zero = pcmp_eq(x, cst_zero);
393 const Packet x_is_one = pcmp_eq(x, cst_one);
394 const Packet x_has_signbit = psignbit(x);
395 const Packet x_abs_gt_one = pcmp_lt(cst_one, x_abs);
396 const Packet x_abs_is_inf = pcmp_eq(x_abs, cst_inf);
399 const Packet y_abs = pabs(y);
400 const Packet y_abs_is_inf = pcmp_eq(y_abs, cst_inf);
401 const Packet y_is_negative = pcmp_lt(y, cst_zero);
402 const Packet y_is_zero = pcmp_eq(y, cst_zero);
403 const Packet y_is_one = pcmp_eq(y, cst_one);
405 const Packet y_is_int = pandnot(pcmp_eq(pfloor(y), y), y_abs_is_inf);
406 const Packet y_div_2 = pmul(y, pset1<Packet>(Scalar(0.5)));
407 const Packet y_is_even = pcmp_eq(pround(y_div_2), y_div_2);
408 const Packet y_is_odd_int = pandnot(y_is_int, y_is_even);
410 constexpr Scalar huge_exponent =
411 (NumTraits<Scalar>::max_exponent() * Scalar(EIGEN_LN2)) / NumTraits<Scalar>::epsilon();
412 const Packet y_abs_is_huge = pcmp_le(pset1<Packet>(huge_exponent), y_abs);
418 result = por(pandnot(x_is_negative, y_is_int), result);
429 result = pselect(x_is_zero, pand(y_is_negative, cst_inf), result);
433 result = pselect(pand(x_has_signbit, y_is_odd_int), pnegate(result), result);
441 Packet inf_y_val = pand(pxor(y_is_negative, x_abs_gt_one), cst_inf);
442 inf_y_val = pselect(pcmp_eq(x, pset1<Packet>(Scalar(-1.0))), cst_one, inf_y_val);
443 result = pselect(y_abs_is_huge, inf_y_val, result);
453 auto x_pos_inf_value = pandnot(cst_inf, y_is_negative);
454 auto x_neg_inf_value = pselect(y_is_odd_int, pnegate(x_pos_inf_value), x_pos_inf_value);
455 result = pselect(x_abs_is_inf, pselect(x_is_negative, x_neg_inf_value, x_pos_inf_value), result);
458 result = por(por(pisnan(x), pisnan(y)), result);
463 result = pselect(y_is_one, x, pselect(por(x_is_one, y_is_zero), cst_one, result));
468template <
typename Scalar>
469EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS std::enable_if_t<is_scalar<Scalar>::value, Scalar> generic_pow(
470 const Scalar& x,
const Scalar& y) {
471 return numext::pow(x, y);
481template <
typename Scalar>
482constexpr numext::uint64_t max_squaring_exponent() {
483 return numext::uint64_t(1) << (std::is_same<typename NumTraits<Scalar>::Real,
double>::value ? 20 : 12);
486template <typename ScalarExponent, bool IsInteger = NumTraits<ScalarExponent>::IsInteger>
487struct exponent_helper {
488 using safe_abs_type = numext::uint64_t;
491 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE safe_abs_type safe_abs(
const ScalarExponent& exp) {
492 eigen_assert(((numext::isfinite)(exp) && exp == numext::floor(exp)) &&
"exp must be an integer");
493 return static_cast<safe_abs_type
>(numext::abs(exp));
497template <
typename ScalarExponent>
498struct exponent_helper<ScalarExponent, true> {
501 using safe_abs_type =
typename numext::get_integer_by_size<
sizeof(ScalarExponent)>::unsigned_type;
502 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE safe_abs_type safe_abs(
const ScalarExponent& exp) {
503 ScalarExponent mask = numext::signbit(exp);
504 safe_abs_type result = safe_abs_type(exp ^ mask);
505 return result + safe_abs_type(ScalarExponent(1) & mask);
509template <typename ScalarExponent, bool IsSigned = NumTraits<ScalarExponent>::IsSigned>
510struct exponent_is_negative {
511 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool run(
const ScalarExponent& exponent) {
512 return exponent < ScalarExponent(0);
516template <
typename ScalarExponent>
517struct exponent_is_negative<ScalarExponent, false> {
518 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool run(
const ScalarExponent&) {
return false; }
523template <
typename AbsExponentType>
524EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AbsExponentType highest_set_bit(AbsExponentType m) {
525 AbsExponentType bit = AbsExponentType(1);
526 while ((m >> 1) >= bit) bit <<= 1;
531template <
typename Packet,
typename ScalarExponent>
532EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet int_pow_wrapping(
const Packet& x,
const ScalarExponent& exponent) {
533 using Scalar =
typename unpacket_traits<Packet>::type;
534 using ExponentHelper = exponent_helper<ScalarExponent>;
535 using AbsExponentType =
typename ExponentHelper::safe_abs_type;
536 Packet cst_pos_one = pset1<Packet>(Scalar(1));
537 if (exponent == ScalarExponent(0))
return cst_pos_one;
538 eigen_assert(!exponent_is_negative<ScalarExponent>::run(exponent));
540 AbsExponentType m = ExponentHelper::safe_abs(exponent);
542 for (AbsExponentType bit = highest_set_bit(m) >> 1; bit != 0; bit >>= 1) {
544 if ((m & bit) != 0) y = pmul(y, x);
551template <
typename Scalar>
552struct is_double_word_base
553 : bool_constant<(std::is_same<Scalar, float>::value || std::is_same<Scalar, double>::value) &&
554 std::numeric_limits<Scalar>::is_iec559> {};
555template <
typename RealScalar>
556struct is_double_word_base<std::complex<RealScalar>> : is_double_word_base<RealScalar> {};
560template <
typename Packet,
typename>
561struct has_exponent_bit_ops : false_type {};
562template <
typename Packet>
563struct has_exponent_bit_ops<Packet, void_t<typename unpacket_traits<Packet>::integer_packet>> : true_type {};
565template <typename Packet, bool IsComplex = NumTraits<typename unpacket_traits<Packet>::type>::IsComplex,
566 bool IsScalar = is_scalar<Packet>::value>
570template <
typename Packet>
571struct real_view<Packet, true, false> {
572 using type =
typename unpacket_traits<Packet>::as_real;
574template <
typename Scalar>
575struct real_view<Scalar, true, true> {
576 using type =
typename NumTraits<Scalar>::Real;
579template <
typename Packet>
580struct use_double_word : bool_constant<is_double_word_base<typename unpacket_traits<Packet>::type>::value &&
581 has_exponent_bit_ops<typename real_view<Packet>::type>::value> {};
586template <
typename Packet>
587struct flushes_subnormals
588 : bool_constant<EIGEN_ARCH_ARM && !is_scalar<Packet>::value &&
589 std::is_same<typename NumTraits<typename unpacket_traits<Packet>::type>::Real, float>::value> {};
592template <
typename Packet>
593EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet exponent_bits_shift_right(
const Packet& bits) {
594 using PacketI =
typename unpacket_traits<Packet>::integer_packet;
595 constexpr int kMantissaBits = numext::numeric_limits<typename unpacket_traits<Packet>::type>::digits - 1;
596 return preinterpret<Packet>(plogical_shift_right<kMantissaBits>(preinterpret<PacketI>(bits)));
598template <
typename Packet>
599EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet exponent_bits_sub(
const Packet& a_bits,
const Packet& b_bits) {
600 using PacketI =
typename unpacket_traits<Packet>::integer_packet;
601 return preinterpret<Packet>(psub(preinterpret<PacketI>(a_bits), preinterpret<PacketI>(b_bits)));
607template <
typename Packet>
608struct binary_exponent_scaling {
609 using Scalar =
typename unpacket_traits<Packet>::type;
610 using Bits = std::make_unsigned_t<typename make_integer<Scalar>::type>;
611 static constexpr int kMantissaBits = numext::numeric_limits<Scalar>::digits - 1;
612 static constexpr int kBias = numext::numeric_limits<Scalar>::max_exponent - 1;
613 static constexpr Bits kExponentMask = ((Bits(1) << (CHAR_BIT *
sizeof(Scalar) - kMantissaBits - 1)) - Bits(1))
616 static constexpr Bits kMagicBits = Bits(kBias + kMantissaBits) << kMantissaBits;
620 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet inverse_scale(
const Packet& x, Packet& e) {
621 Packet exponent_bits = pand(x, pset1frombits<Packet>(kExponentMask));
622 Packet biased = exponent_bits_shift_right(exponent_bits);
623 Packet magic = pset1frombits<Packet>(kMagicBits);
624 e = psub(por(biased, magic), padd(magic, pset1<Packet>(Scalar(kBias + 1))));
626 Packet two_bias_plus_one = pset1frombits<Packet>(Bits(2 * kBias + 1) << kMantissaBits);
627 return exponent_bits_sub(two_bias_plus_one, exponent_bits);
634 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet scale_result(
const Packet& x,
const Packet& e) {
635 constexpr int kLimit = 4 * numext::numeric_limits<Scalar>::max_exponent;
636 constexpr int kZeroBelow =
637 numext::numeric_limits<Scalar>::min_exponent - numext::numeric_limits<Scalar>::digits - 64;
638 Packet zero_below = pset1<Packet>(Scalar(kZeroBelow));
639 Packet value = pselect(pcmp_lt(e, zero_below), pmul(x, pzero(x)), x);
640 Packet exponent = pmin(pmax(e, zero_below), pset1<Packet>(Scalar(kLimit)));
642 return with_subnormals(value, exponent, pldexp(value, exponent), flushes_subnormals<Packet>());
644 return pldexp(value, exponent);
648 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet with_subnormals(
const Packet&,
const Packet&,
const Packet& r,
657 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet with_subnormals(
const Packet& x,
const Packet& e,
const Packet& r,
659 using PacketI =
typename unpacket_traits<Packet>::integer_packet;
660 constexpr int kShift = numext::numeric_limits<Scalar>::digits - numext::numeric_limits<Scalar>::min_exponent;
661 Packet below = pcmp_lt(pabs(r), pset1<Packet>((numext::numeric_limits<Scalar>::min)()));
662 if (!predux_any(below))
return r;
663 Packet t = pldexp(pand(below, pabs(x)), padd(e, pset1<Packet>(Scalar(kShift))));
664 Packet k = preinterpret<Packet>(pcast<Packet, PacketI>(print(t)));
665 Packet rebuilt = pand(below, pcmp_lt(t, pset1<Packet>(Scalar(Bits(1) << kMantissaBits))));
666 return pselect(rebuilt, por(k, pand(x, pset1<Packet>(Scalar(-0.0)))), r);
670 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool any_subnormal(
const Packet& x) {
671 using PacketI =
typename unpacket_traits<Packet>::integer_packet;
672 using Int =
typename unpacket_traits<PacketI>::type;
673 PacketI magnitude = preinterpret<PacketI>(pandnot(x, pset1<Packet>(Scalar(-0.0))));
675 pand(pcmp_lt(pzero(magnitude), magnitude), pcmp_lt(magnitude, pset1<PacketI>(Int(1) << kMantissaBits)));
676 return predux_any(preinterpret<Packet>(subnormal));
682 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void input_scale(
const Packet& x, Packet& lift, Packet& scale,
684 constexpr int kDigits = numext::numeric_limits<Scalar>::digits;
685 Packet is_subnormal = pcmp_lt(pabs(x), pset1<Packet>((numext::numeric_limits<Scalar>::min)()));
686 lift = pselect(is_subnormal, pset1<Packet>(Scalar(Bits(1) << kDigits)), pset1<Packet>(Scalar(1)));
687 scale = inverse_scale(pmul(x, lift), e);
688 e = psub(e, pselect(is_subnormal, pset1<Packet>(Scalar(kDigits)), pzero(x)));
698template <typename Packet, bool IsComplex = NumTraits<typename unpacket_traits<Packet>::type>::IsComplex>
699struct repeated_squaring_ops {
700 using Scalar =
typename unpacket_traits<Packet>::type;
701 using Scaling = binary_exponent_scaling<Packet>;
702 using Bound = Packet;
704 Packet hi, lo, exponent, special;
706 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool any_subnormal(
const Packet& x) {
return Scaling::any_subnormal(x); }
708 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool any_below_normal(
const Packet& x,
const Packet& r) {
709 Packet abs_x = pabs(x);
710 Packet regular = pand(pcmp_lt(pzero(x), abs_x), pcmp_lt(abs_x, pset1<Packet>(NumTraits<Scalar>::infinity())));
711 return predux_any(pand(regular, pcmp_lt(pabs(r), pset1<Packet>((numext::numeric_limits<Scalar>::min)()))));
714 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool in_range(
const Packet& x,
const Packet& bound) {
715 Packet abs_x = pabs(x);
716 Packet out = por(pcmp_lt(pmul(abs_x, bound), pset1<Packet>(Scalar(1))), pcmp_lt_or_nan(bound, abs_x));
717 return !predux_any(out);
722 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void power_base(
const Packet& m,
bool reciprocal, Packet& hi,
729 Packet cst_pos_one = pset1<Packet>(Scalar(1));
730 Packet q = pdiv(cst_pos_one, m);
732 twoprod(q, m, p_hi, p_lo);
733 fast_twosum(q, pdiv(psub(psub(cst_pos_one, p_hi), p_lo), m), hi, lo);
735 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE State base(
const Packet& x,
bool reciprocal,
bool scaled,
739 power_base(x, reciprocal, b.hi, b.lo);
740 b.exponent = pzero(x);
745 Scaling::input_scale(x, lift, scale, b.exponent);
746 power_base(pmul(pmul(x, lift), scale), reciprocal, b.hi, b.lo);
748 b.exponent = pnegate(b.exponent);
749 b.special = pdiv(pset1<Packet>(Scalar(1)), x);
755 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void multiply(State& y,
const State& b) {
756 fast_twoprod(y.hi, y.lo, b.hi, b.lo, y.hi, y.lo);
757 y.exponent = padd(y.exponent, b.exponent);
759 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void square(State& y) { multiply(y, y); }
760 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void renormalize(State& y) {
762 Packet scale = Scaling::inverse_scale(y.hi, e);
763 y.hi = pmul(y.hi, scale);
764 y.lo = pmul(y.lo, scale);
765 y.exponent = padd(y.exponent, e);
767 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet result(
const Packet&,
const State& y,
const State& b,
bool odd,
769 if (!scaled)
return y.hi;
770 Packet use_special = por(pisnan(y.hi), pcmp_eq(y.hi, pzero(y.hi)));
771 return pselect(use_special, odd ? b.special : pabs(b.special), Scaling::scale_result(y.hi, y.exponent));
775 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
int renormalization_steps(
const Scalar&) {
return 4; }
777 struct SpecialBases {
778 static constexpr bool any =
false;
780 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SpecialBases special_bases(
const Packet&,
bool) {
781 return SpecialBases();
783 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet without_special_bases(
const Packet& x,
const SpecialBases&) {
786 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet with_special_bases(
const Packet& r,
const SpecialBases&,
bool) {
794template <typename Packet, bool IsScalar = is_scalar<Packet>::value>
795struct complex_components {
796 using Scalar =
typename unpacket_traits<Packet>::type;
797 using RealScalar =
typename NumTraits<Scalar>::Real;
798 using R =
typename unpacket_traits<Packet>::as_real;
799 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE R flip(
const R& x) {
return pcplxflip(Packet(x)).v; }
800 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE R odd_lanes() {
801 return pcmp_eq(pset1<Packet>(Scalar(0, 1)).v, pset1<R>(RealScalar(1)));
803 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void split(
const Packet& z, R& re, R& im) {
805 re = pselect(odd, flip(z.v), z.v);
806 im = pselect(odd, z.v, flip(z.v));
808 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet join(
const R& re,
const R& im) {
809 return Packet(pselect(odd_lanes(), im, re));
812 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE R magnitude(
const Packet& z) {
814 return pmax(abs_z, flip(abs_z));
817 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE R minor_magnitude(
const Packet& z) {
819 return pmin(abs_z, flip(abs_z));
822 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE R exceeds(
const Packet& z,
const R& bound) {
823 return pcmp_lt_or_nan(bound, pabs(z.v));
825 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool any_zero(
const Packet& z) {
826 return predux_any(pcmp_eq(z.v, pzero(z.v)));
829 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void special_masks(
const Packet& z, R& zero, R& inf, R& nan) {
830 R zero_lane = pcmp_eq(z.v, pzero(z.v));
831 R inf_lane = pcmp_eq(pabs(z.v), pset1<R>(NumTraits<RealScalar>::infinity()));
832 R nan_lane = pisnan(z.v);
833 zero = pand(zero_lane, flip(zero_lane));
834 inf = por(inf_lane, flip(inf_lane));
835 nan = pandnot(por(nan_lane, flip(nan_lane)), inf);
837 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet replace(
const R& mask,
const Scalar& value,
const Packet& z) {
838 return Packet(pselect(mask, pset1<Packet>(value).v, z.v));
842template <
typename Scalar>
843struct complex_components<Scalar, true> {
844 using R =
typename NumTraits<Scalar>::Real;
845 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void split(
const Scalar& z, R& re, R& im) {
846 re = numext::real(z);
847 im = numext::imag(z);
849 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar join(
const R& re,
const R& im) {
return Scalar(re, im); }
850 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE R magnitude(
const Scalar& z) {
851 return numext::maxi(numext::abs(numext::real(z)), numext::abs(numext::imag(z)));
853 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE R minor_magnitude(
const Scalar& z) {
854 return numext::mini(numext::abs(numext::real(z)), numext::abs(numext::imag(z)));
856 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE R exceeds(
const Scalar& z,
const R& bound) {
857 return por(pcmp_lt_or_nan(bound, numext::abs(numext::real(z))),
858 pcmp_lt_or_nan(bound, numext::abs(numext::imag(z))));
860 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool any_zero(
const Scalar& z) {
861 return numext::real(z) == R(0) || numext::imag(z) == R(0);
863 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void special_masks(
const Scalar& z, R& zero, R& inf, R& nan) {
864 R re = numext::real(z), im = numext::imag(z);
865 bool is_inf = (numext::isinf)(re) || (numext::isinf)(im);
866 zero = re == R(0) && im == R(0) ? R(1) : R(0);
867 inf = is_inf ? R(1) : R(0);
868 nan = !is_inf && ((numext::isnan)(re) || (numext::isnan)(im)) ? R(1) : R(0);
870 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar replace(
const R& mask,
const Scalar& value,
const Scalar& z) {
871 return mask != R(0) ? value : z;
883template <
typename Packet>
884struct repeated_squaring_ops<Packet, true> {
885 using Scalar =
typename unpacket_traits<Packet>::type;
886 using Real =
typename NumTraits<Scalar>::Real;
887 using Components = complex_components<Packet>;
888 using R =
typename Components::R;
889 using Scaling = binary_exponent_scaling<R>;
894 R re_hi, re_lo, im_hi, im_lo, exponent;
895 R separated, coefficient_hi, coefficient_lo, coefficient_exponent;
897 bool negative, any_zero;
899 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool any_subnormal(
const Packet& x) {
900 return Scaling::any_subnormal(x.v);
903 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool any_below_normal(
const Packet&,
const Packet&) {
return false; }
910 static constexpr int kMinExponent = numext::numeric_limits<Real>::min_exponent;
911 static constexpr int kDigits = numext::numeric_limits<Real>::digits;
912 static constexpr int kSeparationExponent = kMinExponent + kDigits + 64;
913 static constexpr int kFirstOrderLog2Limit = (1 - kDigits - 2 * kSeparationExponent) / 2;
914 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool every_step(
const Real& count) {
915 return kFirstOrderLog2Limit < 64 &&
916 count > Real(numext::uint64_t(1) << (kFirstOrderLog2Limit < 64 ? kFirstOrderLog2Limit : 0));
918 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
int renormalization_steps(
const Real& count) {
919 return every_step(count) ? 1 : 4;
923 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool in_range(
const Packet& x,
const R& bound) {
924 R magnitude = Components::magnitude(x);
925 R minor = Components::minor_magnitude(x);
926 R one = pset1<R>(Real(1));
927 R out = por(pcmp_lt(pmul(magnitude, bound), one), Components::exceeds(x, bound));
928 out = por(out, pandnot(pcmp_lt(pmul(minor, bound), one), pcmp_eq(minor, pzero(minor))));
929 return predux_any(out) ==
false;
931 template <
typename Count>
932 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE State base(
const Packet& x,
bool reciprocal,
bool scaled,
935 b.any_separated =
false;
937 Components::split(x, re, im);
938 b.negative = reciprocal;
939 b.any_zero = Components::any_zero(x);
941 power_base(re, im, reciprocal, b);
942 b.exponent = pzero(re);
946 Scaling::input_scale(Components::magnitude(x), lift, scale, b.exponent);
947 R wr = pmul(pmul(re, lift), scale), wi = pmul(pmul(im, lift), scale);
952 int separation_exponent = every_step(Real(m)) ? kSeparationExponent - 56 : kSeparationExponent;
954 pset1frombits<R>(
typename Scaling::Bits(Scaling::kBias + separation_exponent) << Scaling::kMantissaBits);
956 R re_separated = pandnot(pcmp_lt(pabs(wr), separation), pcmp_eq(re, zero));
957 R im_separated = pandnot(pcmp_lt(pabs(wi), separation), pcmp_eq(im, zero));
958 b.separated = por(re_separated, im_separated);
959 b.any_separated = predux_any(b.separated);
960 if (b.any_separated) {
961 R s_lift, s_scale, s_exponent, count_exponent;
962 Scaling::input_scale(pselect(im_separated, im, re), s_lift, s_scale, s_exponent);
963 R s = pmul(pmul(pselect(im_separated, im, re), s_lift), s_scale);
966 numext::uint64_t n = numext::uint64_t(m);
967 numext::uint64_t unit = highest_set_bit(n) >> (kDigits - 1);
968 numext::uint64_t n_hi = unit > 1 ? n & ~(unit - 1) : n;
969 R count_hi = pset1<R>(Real(n_hi)), count_lo = pset1<R>(Real(n - n_hi));
970 R count_scale = Scaling::inverse_scale(count_hi, count_exponent);
974 R l = pselect(im_separated, wr, wi);
976 R p_hi, p_lo, c_hi, c_lo;
977 twoprod(q, l, p_hi, p_lo);
978 R q_lo = pdiv(psub(psub(s, p_hi), p_lo), l);
979 R scaled_count = pmul(count_hi, count_scale);
980 R scaled_count_lo = pmul(count_lo, count_scale);
981 twoprod(scaled_count, q, c_hi, c_lo);
982 fast_twosum(c_hi, pmadd(scaled_count, q_lo, pmadd(scaled_count_lo, q, c_lo)), p_hi, p_lo);
983 R sign = pselect(im_separated, pset1<R>(Real(reciprocal ? -0.125 : 0.125)),
984 pset1<R>(Real(reciprocal ? 0.125 : -0.125)));
985 b.coefficient_hi = pmul(p_hi, sign);
986 b.coefficient_lo = pmul(p_lo, sign);
987 b.coefficient_exponent = padd(padd(psub(s_exponent, b.exponent), count_exponent), pset1<R>(Real(3)));
988 wr = pselect(re_separated, zero, wr);
989 wi = pselect(im_separated, zero, wi);
991 power_base(wr, wi, reciprocal, b);
992 if (reciprocal) b.exponent = pnegate(b.exponent);
999 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void power_base(
const R& wr,
const R& wi,
bool reciprocal, State& b) {
1000 b.re_lo = b.im_lo = pzero(wr);
1006 R inv = pdiv(pset1<R>(
typename NumTraits<Scalar>::Real(1)), pmadd(wr, wr, pmul(wi, wi)));
1007 R qr = pmul(wr, inv), qi = pnegate(pmul(wi, inv));
1008 R a_hi, a_lo, c_hi, c_lo, s_hi, s_lo, t_hi, t_lo;
1009 twoprod(qr, wr, a_hi, a_lo);
1010 twoprod(qi, wi, c_hi, c_lo);
1011 twodiff(a_hi, a_lo, c_hi, c_lo, s_hi, s_lo);
1012 twoprod(qr, wi, a_hi, a_lo);
1013 twoprod(qi, wr, c_hi, c_lo);
1014 twosum(a_hi, a_lo, c_hi, c_lo, t_hi, t_lo);
1015 R er = psub(psub(pset1<R>(
typename NumTraits<Scalar>::Real(1)), s_hi), s_lo);
1016 R t = padd(t_hi, t_lo);
1017 fast_twosum(qr, pmadd(er, qr, pmul(t, qi)), b.re_hi, b.re_lo);
1018 fast_twosum(qi, pmsub(er, qi, pmul(t, qr)), b.im_hi, b.im_lo);
1020 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void square(State& y) {
1021 R a_hi, a_lo, c_hi, c_lo, p_hi, p_lo;
1022 fast_twoprod(y.re_hi, y.re_lo, y.re_hi, y.re_lo, a_hi, a_lo);
1023 fast_twoprod(y.im_hi, y.im_lo, y.im_hi, y.im_lo, c_hi, c_lo);
1024 fast_twoprod(y.re_hi, y.re_lo, y.im_hi, y.im_lo, p_hi, p_lo);
1025 twodiff(a_hi, a_lo, c_hi, c_lo, y.re_hi, y.re_lo);
1026 y.im_hi = padd(p_hi, p_hi);
1027 y.im_lo = padd(p_lo, p_lo);
1028 y.exponent = padd(y.exponent, y.exponent);
1030 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void multiply(State& y,
const State& b) {
1031 R ac_hi, ac_lo, bd_hi, bd_lo, ad_hi, ad_lo, bc_hi, bc_lo;
1032 fast_twoprod(y.re_hi, y.re_lo, b.re_hi, b.re_lo, ac_hi, ac_lo);
1033 fast_twoprod(y.im_hi, y.im_lo, b.im_hi, b.im_lo, bd_hi, bd_lo);
1034 fast_twoprod(y.re_hi, y.re_lo, b.im_hi, b.im_lo, ad_hi, ad_lo);
1035 fast_twoprod(y.im_hi, y.im_lo, b.re_hi, b.re_lo, bc_hi, bc_lo);
1036 twodiff(ac_hi, ac_lo, bd_hi, bd_lo, y.re_hi, y.re_lo);
1037 twosum(ad_hi, ad_lo, bc_hi, bc_lo, y.im_hi, y.im_lo);
1038 y.exponent = padd(y.exponent, b.exponent);
1040 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void renormalize(State& y) {
1042 R scale = Scaling::inverse_scale(pmax(pabs(y.re_hi), pabs(y.im_hi)), e);
1043 y.re_hi = pmul(y.re_hi, scale);
1044 y.re_lo = pmul(y.re_lo, scale);
1045 y.im_hi = pmul(y.im_hi, scale);
1046 y.im_lo = pmul(y.im_lo, scale);
1047 y.exponent = padd(y.exponent, e);
1049 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet result(
const Packet& x,
const State& y,
const State& b,
bool odd,
1052 R re = y.re_hi, im = y.im_hi;
1053 if (b.any_zero) zero_component_signs(x, b.negative, odd, re, im);
1054 return Components::join(re, im);
1056 R re = Scaling::scale_result(y.re_hi, y.exponent);
1057 R im = Scaling::scale_result(y.im_hi, y.exponent);
1058 if (b.any_separated) {
1060 R e = padd(y.exponent, b.coefficient_exponent);
1062 R re_hi, re_lo, im_hi, im_lo;
1063 fast_twoprod(b.coefficient_hi, b.coefficient_lo, y.im_hi, y.im_lo, re_hi, re_lo);
1064 fast_twoprod(b.coefficient_hi, b.coefficient_lo, y.re_hi, y.re_lo, im_hi, im_lo);
1065 re = pselect(pand(b.separated, pcmp_eq(y.re_hi, zero)), Scaling::scale_result(pnegate(re_hi), e), re);
1066 im = pselect(pand(b.separated, pcmp_eq(y.im_hi, zero)), Scaling::scale_result(im_hi, e), im);
1068 if (b.any_zero) zero_component_signs(x, b.negative, odd, re, im);
1069 return Components::join(re, im);
1076 struct SpecialBases {
1080 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SpecialBases special_bases(
const Packet& x,
bool scaled) {
1081 SpecialBases special;
1083 special.any =
false;
1086 Components::special_masks(x, zero, inf, nan);
1087 special.any = predux_any(por(por(zero, inf), nan));
1091 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet without_special_bases(
const Packet& x,
1092 const SpecialBases& special) {
1093 if (!special.any)
return x;
1095 Components::special_masks(x, zero, inf, nan);
1096 return Components::replace(por(por(zero, inf), nan), Scalar(1, 1), x);
1098 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet with_special_bases(
const Packet& r,
const SpecialBases& special,
1100 if (!special.any)
return r;
1102 Components::special_masks(special.x, zero, inf, nan);
1103 Real real_inf = NumTraits<Real>::infinity(), real_nan = NumTraits<Real>::quiet_NaN();
1104 Packet out = Components::replace(negative ? zero : inf, Scalar(real_inf, Real(0)), r);
1105 out = Components::replace(negative ? inf : zero, Scalar(0), out);
1106 return Components::replace(nan, Scalar(real_nan, real_nan), out);
1112 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
void zero_component_signs(
const Packet& x,
bool negative,
bool odd,
1116 Components::split(x, x_re, x_im);
1117 R imaginary = pcmp_eq(x_re, zero);
1118 R one_zero = pxor(imaginary, pcmp_eq(x_im, zero));
1119 R minus_zero = pset1<R>(Real(-0.0));
1121 R power_imaginary = odd ? imaginary : zero;
1122 R n_sign = negative ? minus_zero : zero;
1123 R extra = odd ? n_sign : pselect(imaginary, pxor(n_sign, minus_zero), n_sign);
1124 R sign = pxor(pand(pxor(pxor(x_re, x_im), pselect(power_imaginary, im, re)), minus_zero), extra);
1125 re = pselect(pand(one_zero, power_imaginary), sign, re);
1126 im = pselect(pandnot(one_zero, power_imaginary), sign, im);
1131template <
typename Packet,
typename ScalarExponent>
1132EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet int_pow_plain(
const Packet& x,
const ScalarExponent& exponent) {
1133 using Scalar =
typename unpacket_traits<Packet>::type;
1134 using ExponentHelper = exponent_helper<ScalarExponent>;
1135 using AbsExponentType =
typename ExponentHelper::safe_abs_type;
1136 if (exponent == ScalarExponent(0))
return pset1<Packet>(Scalar(1));
1138 Packet base = exponent_is_negative<ScalarExponent>::run(exponent) ? pdiv(pset1<Packet>(Scalar(1)), x) : x;
1139 AbsExponentType m = ExponentHelper::safe_abs(exponent);
1141 for (AbsExponentType bit = highest_set_bit(m) >> 1; bit != 0; bit >>= 1) {
1143 if ((m & bit) != 0) y = pmul(y, base);
1156template <
typename Packet,
typename ScalarExponent>
1157EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet int_pow_double_word(
const Packet& x,
const ScalarExponent& exponent) {
1158 using Scalar =
typename unpacket_traits<Packet>::type;
1159 using ExponentHelper = exponent_helper<ScalarExponent>;
1160 using AbsExponentType =
typename ExponentHelper::safe_abs_type;
1161 using Ops = repeated_squaring_ops<Packet>;
1162 if (exponent == ScalarExponent(0))
return pset1<Packet>(Scalar(1));
1164 bool negative = exponent_is_negative<ScalarExponent>::run(exponent);
1165 AbsExponentType m = ExponentHelper::safe_abs(exponent);
1166 bool odd = (m & AbsExponentType(1)) != 0;
1167 if (m == AbsExponentType(1) && !negative)
return x;
1170 EIGEN_IF_CONSTEXPR (!NumTraits<Scalar>::IsComplex) {
1171 if (m == AbsExponentType(1) && !flushes_subnormals<Packet>::value)
return pdiv(pset1<Packet>(Scalar(1)), x);
1172 if (m == AbsExponentType(2) && !negative)
return pmul(x, x);
1174 AbsExponentType top = highest_set_bit(m);
1182 using Real =
typename NumTraits<Scalar>::Real;
1183 using RealBits = std::make_unsigned_t<typename make_integer<Real>::type>;
1184 constexpr int kBudget = -(numext::numeric_limits<Real>::min_exponent + numext::numeric_limits<Real>::digits);
1185 constexpr int kMantissaBits = numext::numeric_limits<Real>::digits - 1;
1186 constexpr RealBits kBiasBits = RealBits(numext::numeric_limits<Real>::max_exponent - 1);
1187 int b = numext::uint64_t(m) > numext::uint64_t(kBudget) ? 0 : kBudget / int(m);
1188 EIGEN_IF_CONSTEXPR (NumTraits<Scalar>::IsComplex)
1189 b = numext::mini(b - 1, (numext::numeric_limits<Real>::max_exponent - 1) / 2);
1192 EIGEN_IF_CONSTEXPR (flushes_subnormals<Packet>::value) b = -1;
1193 typename Ops::Bound bound =
1194 pset1frombits<typename Ops::Bound>(RealBits(kBiasBits + RealBits(b < 0 ? 0 : b)) << kMantissaBits);
1195 bool scaled = b < 0 || !Ops::in_range(x, bound);
1197 typename Ops::SpecialBases special = Ops::special_bases(x, scaled);
1198 Packet x_regular = Ops::without_special_bases(x, special);
1199 if (special.any) scaled = b < 0 || !Ops::in_range(x_regular, bound);
1201 typename Ops::State base = Ops::base(x_regular, negative, scaled, m);
1202 typename Ops::State y = base;
1203 int renormalization_steps = Ops::renormalization_steps(Real(m));
1204 int steps_since_renormalization = 0;
1205 for (AbsExponentType bit = top >> 1; bit != 0; bit >>= 1) {
1207 if ((m & bit) != 0) Ops::multiply(y, base);
1208 if (scaled && ++steps_since_renormalization == renormalization_steps) {
1209 Ops::renormalize(y);
1210 steps_since_renormalization = 0;
1213 return Ops::with_special_bases(Ops::result(x_regular, y, base, odd, scaled), special, negative);
1216template <
typename Packet,
typename ScalarExponent>
1217EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE Packet int_pow_lanewise(
const Packet& x,
const ScalarExponent& exponent) {
1218 using Scalar =
typename unpacket_traits<Packet>::type;
1219 EIGEN_ALIGN_TO_BOUNDARY(unpacket_traits<Packet>::alignment) Scalar values[unpacket_traits<Packet>::size];
1221 for (Scalar& value : values) value = int_pow_double_word(value, exponent);
1222 return pload<Packet>(values);
1225template <
typename Packet,
typename ScalarExponent>
1226EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet int_pow_double_word(
const Packet& x,
const ScalarExponent& exponent,
1228 return int_pow_double_word(x, exponent);
1234template <
typename Packet,
typename ScalarExponent>
1235EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet int_pow_double_word(
const Packet& x,
const ScalarExponent& exponent,
1237 using Ops = repeated_squaring_ops<Packet>;
1238 if (Ops::any_subnormal(x))
return int_pow_lanewise(x, exponent);
1239 Packet r = int_pow_double_word(x, exponent);
1240 if (exponent_helper<ScalarExponent>::safe_abs(exponent) <= 2 && Ops::any_below_normal(x, r))
1241 return int_pow_lanewise(x, exponent);
1245template <
typename Packet,
typename ScalarExponent>
1246EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet int_pow(
const Packet& x,
const ScalarExponent& exponent, true_type) {
1248 return int_pow_double_word(x, exponent, flushes_subnormals<Packet>());
1250 return int_pow_double_word(x, exponent);
1254template <
typename Packet,
typename ScalarExponent>
1255EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet int_pow(
const Packet& x,
const ScalarExponent& exponent, false_type) {
1256 return int_pow_plain(x, exponent);
1259template <
typename Packet,
typename ScalarExponent>
1260EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet int_pow(
const Packet& x,
const ScalarExponent& exponent) {
1261 return int_pow(x, exponent, use_double_word<Packet>());
1266template <
typename Packet,
typename ScalarExponent>
1267EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool use_repeated_squaring(
const ScalarExponent& exponent) {
1268 using Scalar =
typename unpacket_traits<Packet>::type;
1269 return use_double_word<Packet>::value ? numext::abs(exponent) <= ScalarExponent(max_squaring_exponent<Scalar>())
1270 : (exponent <= ScalarExponent(7) && exponent >= ScalarExponent(-3));
1275template <
typename Packet,
typename ScalarExponent>
1276EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool use_repeated_squaring_for_integer(
const ScalarExponent& exponent) {
1277 using Scalar =
typename unpacket_traits<Packet>::type;
1278 constexpr numext::uint64_t kExactLimit = numext::uint64_t(1) << numext::numeric_limits<Scalar>::digits;
1279 return exponent_helper<ScalarExponent>::safe_abs(exponent) > kExactLimit ||
1280 use_repeated_squaring<Packet>(
static_cast<Scalar
>(exponent));
1283template <
typename Packet>
1284EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::enable_if_t<!is_scalar<Packet>::value, Packet> gen_pow(
1285 const Packet& x,
const typename unpacket_traits<Packet>::type& exponent) {
1286 const Packet exponent_packet = pset1<Packet>(exponent);
1288 return generic_pow_impl(pabs(x), exponent_packet);
1291template <
typename Scalar>
1292EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::enable_if_t<is_scalar<Scalar>::value, Scalar> gen_pow(
1293 const Scalar& x,
const Scalar& exponent) {
1294 return numext::pow(x, exponent);
1301template <
typename Packet,
typename ScalarExponent>
1302EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet handle_nonint_nonint_errors(
const Packet& x,
const Packet& powx,
1303 const ScalarExponent& exponent) {
1304 using Scalar =
typename unpacket_traits<Packet>::type;
1305 const Packet cst_zero = pzero(x);
1306 const Packet cst_one = pset1<Packet>(Scalar(1));
1307 const Packet cst_inf = pinf<Packet>();
1308 const Packet cst_nan = pnan<Packet>();
1310 const Packet abs_x = pabs(x);
1313 Packet result = por(pcmp_lt(x, cst_zero), powx);
1315 if (!(numext::isfinite)(exponent)) {
1316 if (exponent != exponent) {
1318 result = pselect(pcmp_eq(x, cst_one), cst_one, cst_nan);
1321 const Packet abs_x_is_one = pcmp_eq(abs_x, cst_one);
1322 if (exponent > ScalarExponent(0)) {
1324 result = pand(pcmp_lt(cst_one, abs_x), cst_inf);
1327 result = pand(pcmp_lt(abs_x, cst_one), cst_inf);
1330 result = pselect(abs_x_is_one, cst_one, result);
1334 const Packet x_is_zero = pcmp_eq(x, cst_zero);
1335 const Packet abs_x_is_inf = pcmp_eq(abs_x, cst_inf);
1336 if (exponent < ScalarExponent(0)) {
1338 result = pselect(x_is_zero, cst_inf, result);
1339 result = pselect(abs_x_is_inf, cst_zero, result);
1342 result = pselect(x_is_zero, cst_zero, result);
1343 result = pselect(abs_x_is_inf, cst_inf, result);
1350 result = por(pisnan(x), result);
1355template <
typename Packet,
typename ScalarExponent,
1356 std::enable_if_t<NumTraits<typename unpacket_traits<Packet>::type>::IsSigned,
bool> =
true>
1357EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet handle_negative_exponent(
const Packet& x,
const ScalarExponent& exponent) {
1358 using Scalar =
typename unpacket_traits<Packet>::type;
1364 Packet cst_pos_one = pset1<Packet>(Scalar(1));
1365 const bool exponent_is_odd = exponent % ScalarExponent(2) != ScalarExponent(0);
1366 const Packet exp_is_odd = exponent_is_odd ? ptrue<Packet>(x) : pzero<Packet>(x);
1368 const Packet abs_x = pabs(x);
1369 const Packet abs_x_is_one = pcmp_eq(abs_x, cst_pos_one);
1371 Packet result = pselect(exp_is_odd, x, abs_x);
1372 result = pselect(abs_x_is_one, result, pzero<Packet>(x));
1376template <
typename Packet,
typename ScalarExponent,
1377 std::enable_if_t<!NumTraits<typename unpacket_traits<Packet>::type>::IsSigned,
bool> =
true>
1378EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet handle_negative_exponent(
const Packet& x,
const ScalarExponent&) {
1379 using Scalar =
typename unpacket_traits<Packet>::type;
1386 const Scalar pos_one = Scalar(1);
1388 const Packet cst_pos_one = pset1<Packet>(pos_one);
1390 const Packet x_is_one = pcmp_eq(x, cst_pos_one);
1392 return pand(x_is_one, x);
1397template <
typename Packet,
typename ScalarExponent,
1398 bool BaseIsIntegerType = NumTraits<typename unpacket_traits<Packet>::type>::IsInteger,
1399 bool ExponentIsIntegerType = NumTraits<ScalarExponent>::IsInteger,
1400 bool ExponentIsSigned = NumTraits<ScalarExponent>::IsSigned>
1401struct unary_pow_impl;
1403template <
typename Packet,
typename ScalarExponent,
bool ExponentIsSigned>
1404struct unary_pow_impl<Packet, ScalarExponent, false, false, ExponentIsSigned> {
1405 using Scalar =
typename unpacket_traits<Packet>::type;
1406 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet run(
const Packet& x,
const ScalarExponent& exponent) {
1407 const bool exponent_is_integer = (numext::isfinite)(exponent) && numext::round(exponent) == exponent;
1408 if (exponent_is_integer) {
1409 return unary_pow::use_repeated_squaring<Packet>(exponent) ? unary_pow::int_pow(x, exponent)
1410 : generic_pow(x, pset1<Packet>(exponent));
1412 Packet result = unary_pow::gen_pow(x, exponent);
1413 result = unary_pow::handle_nonint_nonint_errors(x, result, exponent);
1419template <
typename Packet,
typename ScalarExponent,
bool ExponentIsSigned>
1420struct unary_pow_impl<Packet, ScalarExponent, false, true, ExponentIsSigned> {
1421 using Scalar =
typename unpacket_traits<Packet>::type;
1426 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet run(
const Packet& x,
const ScalarExponent& exponent) {
1427 return run(x, exponent,
1428 bool_constant < unary_pow::use_double_word<Packet>::value && !NumTraits<Scalar>::IsComplex > ());
1430 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet run(
const Packet& x,
const ScalarExponent& exponent, true_type) {
1431 return unary_pow::use_repeated_squaring_for_integer<Packet>(exponent)
1432 ? unary_pow::int_pow(x, exponent)
1433 : generic_pow(x, pset1<Packet>(static_cast<Scalar>(exponent)));
1435 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet run(
const Packet& x,
const ScalarExponent& exponent, false_type) {
1436 return unary_pow::int_pow(x, exponent);
1440template <
typename Packet,
typename ScalarExponent>
1441struct unary_pow_impl<Packet, ScalarExponent, true, true, true> {
1442 using Scalar =
typename unpacket_traits<Packet>::type;
1443 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(
const Packet& x,
const ScalarExponent& exponent) {
1444 if (exponent < ScalarExponent(0)) {
1445 return unary_pow::handle_negative_exponent(x, exponent);
1447 return unary_pow::int_pow_wrapping(x, exponent);
1452template <
typename Packet,
typename ScalarExponent>
1453struct unary_pow_impl<Packet, ScalarExponent, true, true, false> {
1454 using Scalar =
typename unpacket_traits<Packet>::type;
1455 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(
const Packet& x,
const ScalarExponent& exponent) {
1456 return unary_pow::int_pow_wrapping(x, exponent);