12#ifndef EIGEN_ARCH_GENERIC_PACKET_MATH_FREXP_LDEXP_H
13#define EIGEN_ARCH_GENERIC_PACKET_MATH_FREXP_LDEXP_H
16#include "../../InternalHeaderCheck.h"
25struct make_integer<float> {
26 using type = numext::int32_t;
29struct make_integer<double> {
30 using type = numext::int64_t;
33struct make_integer<half> {
34 using type = numext::int16_t;
37struct make_integer<bfloat16> {
38 using type = numext::int16_t;
41template <
typename Packet>
42EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Packet pfrexp_generic_get_biased_exponent(
const Packet& a) {
43 using Scalar =
typename unpacket_traits<Packet>::type;
44 using PacketI =
typename unpacket_traits<Packet>::integer_packet;
45 static constexpr int mantissa_bits = numext::numeric_limits<Scalar>::digits - 1;
46 return pcast<PacketI, Packet>(plogical_shift_right<mantissa_bits>(preinterpret<PacketI>(pabs(a))));
51template <
typename Packet>
52EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Packet pfrexp_generic(
const Packet& a, Packet& exponent) {
53 using Scalar =
typename unpacket_traits<Packet>::type;
54 using ScalarUI = std::make_unsigned_t<typename make_integer<Scalar>::type>;
55 static constexpr int TotalBits =
sizeof(Scalar) * CHAR_BIT, MantissaBits = numext::numeric_limits<Scalar>::digits - 1,
56 ExponentBits = TotalBits - MantissaBits - 1;
58 constexpr ScalarUI scalar_sign_mantissa_mask =
59 ~(((ScalarUI(1) << ExponentBits) - ScalarUI(1)) << MantissaBits);
60 const Packet sign_mantissa_mask = pset1frombits<Packet>(
static_cast<ScalarUI
>(scalar_sign_mantissa_mask));
61 const Packet half = pset1<Packet>(Scalar(0.5));
62 const Packet zero = pzero(a);
63 const Packet normal_min = pset1<Packet>((numext::numeric_limits<Scalar>::min)());
66 const Packet is_denormal = pcmp_lt(pabs(a), normal_min);
67 constexpr ScalarUI scalar_normalization_offset = ScalarUI(MantissaBits + 1);
69 const Scalar scalar_normalization_factor = Scalar(ScalarUI(1) <<
int(scalar_normalization_offset));
70 const Packet normalization_factor = pset1<Packet>(scalar_normalization_factor);
71 const Packet normalized_a = pselect(is_denormal, pmul(a, normalization_factor), a);
74 const Scalar scalar_exponent_offset = -Scalar((ScalarUI(1) << (ExponentBits - 1)) - ScalarUI(2));
75 Packet exponent_offset = pset1<Packet>(scalar_exponent_offset);
76 const Packet normalization_offset = pset1<Packet>(-Scalar(scalar_normalization_offset));
77 exponent_offset = pselect(is_denormal, padd(exponent_offset, normalization_offset), exponent_offset);
80 exponent = pfrexp_generic_get_biased_exponent(normalized_a);
83 const Scalar scalar_non_finite_exponent = Scalar((ScalarUI(1) << ExponentBits) - ScalarUI(1));
84 const Packet non_finite_exponent = pset1<Packet>(scalar_non_finite_exponent);
85 const Packet is_zero_or_not_finite = por(pcmp_eq(a, zero), pcmp_eq(exponent, non_finite_exponent));
86 const Packet m = pselect(is_zero_or_not_finite, a, por(pand(normalized_a, sign_mantissa_mask), half));
87 exponent = pselect(is_zero_or_not_finite, zero, padd(exponent, exponent_offset));
93template <
typename Packet>
94EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Packet pldexp_apply_factors(
const Packet& a,
const Packet& c1,
const Packet& c2) {
95 Packet out = pmul(a, c1);
96 EIGEN_OPTIMIZATION_BARRIER(out)
98 EIGEN_OPTIMIZATION_BARRIER(out)
104template <
typename Packet>
105EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Packet pldexp_generic(
const Packet& a,
const Packet& exponent) {
138 using PacketI =
typename unpacket_traits<Packet>::integer_packet;
139 using Scalar =
typename unpacket_traits<Packet>::type;
140 using ScalarI =
typename unpacket_traits<PacketI>::type;
141 static constexpr int TotalBits =
sizeof(Scalar) * CHAR_BIT, MantissaBits = numext::numeric_limits<Scalar>::digits - 1,
142 ExponentBits = TotalBits - MantissaBits - 1;
144 constexpr ScalarI bias_value = (ScalarI(1) << (ExponentBits - 1)) - ScalarI(1);
145 constexpr ScalarI max_exp_value = (ScalarI(1) << ExponentBits) + ScalarI(MantissaBits - 1);
146 constexpr ScalarI last_max_value = bias_value - ScalarI(1);
147 const Packet max_exponent = pset1<Packet>(Scalar(max_exp_value));
148 const Packet neg_max_exponent = pset1<Packet>(Scalar(-max_exp_value));
149 const Packet last_max = pset1<Packet>(Scalar(last_max_value));
150 const Packet neg_last_max = pset1<Packet>(Scalar(-last_max_value));
151 const PacketI bias = pset1<PacketI>(bias_value);
152 const PacketI e = pcast<Packet, PacketI>(pmin(pmax(exponent, neg_max_exponent), max_exponent));
153 const PacketI b = pcast<Packet, PacketI>(pmin(pmax(exponent, neg_last_max), last_max));
154 const PacketI t = pandnot(psub(e, b), pset1<PacketI>(ScalarI(1)));
155 const Packet c1 = preinterpret<Packet>(plogical_shift_left<MantissaBits - 1>(padd(t, padd(bias, bias))));
156 const Packet c2 = preinterpret<Packet>(plogical_shift_left<MantissaBits>(padd(psub(e, t), bias)));
157 return pldexp_apply_factors(a, c1, c2);
169template <
typename Packet>
170EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Packet pldexp_fast(
const Packet& a,
const Packet& exponent) {
171 using PacketI =
typename unpacket_traits<Packet>::integer_packet;
172 using Scalar =
typename unpacket_traits<Packet>::type;
173 using ScalarI =
typename unpacket_traits<PacketI>::type;
174 static constexpr int TotalBits =
sizeof(Scalar) * CHAR_BIT, MantissaBits = numext::numeric_limits<Scalar>::digits - 1,
175 ExponentBits = TotalBits - MantissaBits - 1;
177 const Packet bias = pset1<Packet>(Scalar((ScalarI(1) << (ExponentBits - 1)) - ScalarI(1)));
178 const Packet limit = pset1<Packet>(Scalar((ScalarI(1) << ExponentBits) - ScalarI(1)));
180 const PacketI e = pcast<Packet, PacketI>(pmin(pmax(padd(exponent, bias), pzero(limit)), limit));
182 return pmul(a, preinterpret<Packet>(plogical_shift_left<MantissaBits>(e)));