3#include "native/attributes.h"
5namespace ftz {
namespace detail {
namespace math {
6 struct log_result {
unsigned int bits, valid; };
9 template <
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
10 [[nodiscard]] native_constexpr native_inline native_const
float log1p_kernel(
float x) {
11 unsigned int word = fp32_encode(x);
12 if ((word & 0x7fffffffu) <= 0x33000000u)
return x;
13 float z = fp32_mul<true,Hardware>(x,x);
15 if ((word & 0x80000000u) != 0u) {
16 t = fp32_fma<true,Hardware>(x,fp32_decode(0x40800000u),fp32_decode(0x3f800000u));
17 h = fp32_decode(0xb44f5480u);
18 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x352754efu));
19 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xb5bb75dbu));
20 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x369a1c19u));
21 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xb7866f43u));
22 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x3861235au));
23 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xb93e98dfu));
24 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x3a24a041u));
25 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xbb117f6au));
26 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x3c04b7c5u));
27 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xbcfda364u));
28 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x3e029133u));
29 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xbf1a5884u));
32 t = fp32_fma<true,Hardware>(x,fp32_decode(0x40000000u),fp32_decode(0xbf800000u));
33 h = fp32_decode(0xb29c7ee2u);
34 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x3378ea39u));
35 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xb3faaccbu));
36 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x34c9e1cdu));
37 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xb5b13b5eu));
38 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x36902a0au));
39 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xb76af011u));
40 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x38423d8au));
41 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xb9225d51u));
42 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x3a0988b0u));
43 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xbaed1a41u));
44 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x3bd13ce0u));
45 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xbcbeef90u));
46 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0x3db786beu));
47 h = fp32_fma<true,Hardware>(h,t,fp32_decode(0xbec19b82u));
49 return fp32_fma<true,Hardware>(z,h,x);
51 template <
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
52 [[nodiscard]] native_constexpr native_inline native_const log_result log_words(
unsigned int word) {
53 unsigned int magnitude = word & 0x7fffffffu;
54 log_result result;result.bits=0x7fc00000u;result.valid=0u;
55 if (magnitude > 0x7f800000u)
return result;
56 if (magnitude < 0x00800000u) {
57 result.bits=0xff800000u;result.valid=1u;
return result;
59 if ((word & 0x80000000u) != 0u)
return result;
61 if (magnitude == 0x7f800000u) {result.bits=word;
return result;}
62 int exponent=(int)(word >> 23)-127;
63 unsigned int mantissa=(word & 0x007fffffu) | 0x3f800000u;
64 if (mantissa >= 0x3fc00000u) {mantissa-=0x00800000u;exponent+=1;}
66 float r=fp32_add<true,Hardware>(fp32_decode(mantissa),-1.0f);
67 float p=log1p_kernel<Hardware>(r);
68 float e=(float)exponent;
70 float low=fp32_fma<true,Hardware>(e,fp32_decode(0x35bfbe8eu),p);
71 result.bits=fp32_encode(fp32_fma<true,Hardware>(e,fp32_decode(0x3f317200u),low));
74 template <
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
75 [[nodiscard]] native_constexpr native_inline native_const log_result log1p_words(
unsigned int word) {
76 unsigned int magnitude=word & 0x7fffffffu;
77 bool negative=(word & 0x80000000u) != 0u;
78 log_result result;result.bits=0x7fc00000u;result.valid=0u;
79 if (magnitude > 0x7f800000u || (negative && magnitude > 0x3f800000u))
return result;
81 if (magnitude < 0x00800000u) {result.bits=word & 0x80000000u;
return result;}
82 if (negative && magnitude == 0x3f800000u) {result.bits=0xff800000u;
return result;}
83 if (magnitude == 0x7f800000u) {result.bits=word;
return result;}
84 if (magnitude <= 0x33000000u) {result.bits=word;
return result;}
85 float x=fp32_decode(word);
86 if ((!negative && magnitude <= 0x3f800000u) || (negative && magnitude <= 0x3f000000u)) {
87 result.bits=fp32_encode(log1p_kernel<Hardware>(x));
return result;
91 return log_words<Hardware>(fp32_encode(fp32_add<true,Hardware>(1.0f,x)));
93 template <
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
94 [[nodiscard]] native_constexpr native_inline native_const
float log(
float value) {
95 return fp32_decode(log_words<Hardware>(fp32_encode(value)).bits);
97 template <
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
98 [[nodiscard]] native_constexpr native_inline native_const
float log1p(
float value) {
99 return fp32_decode(log1p_words<Hardware>(fp32_encode(value)).bits);
FP32 bit casts, precise arithmetic and signed flush-to-zero normalization.