3#include "native/attributes.h"
6namespace ftz {
namespace detail {
namespace math {
12 template <
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
13 [[nodiscard]] native_constexpr native_inline native_const
unsigned int tanh_words(
unsigned int word) {
14 unsigned int magnitude = word & 0x7fffffffu;
15 unsigned int sign = word & 0x80000000u;
16 if (magnitude > 0x7f800000u) {
19 if (magnitude < 0x00800000u) {
24 if (magnitude <= 0x39800000u) {
29 if (magnitude >= 0x41200000u) {
30 return sign | 0x3f800000u;
32 float x = fp32_decode(magnitude);
33 float z = fp32_mul<true,Hardware>(x, x);
35 if (magnitude <= 0x3f800000u) {
36 t = fp32_fma<true,Hardware>(z, fp32_decode(0x40000000u), fp32_decode(0xbf800000u));
37 h = fp32_decode(0x34facb37u);
38 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xb63a0d2du));
39 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x37813497u));
40 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xb8bfb3f8u));
41 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3a0e6d24u));
42 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbb535f6cu));
43 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3c9d20e4u));
44 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbded544du));
45 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3f5c6e3eu));
47 else if (magnitude <= 0x40000000u) {
48 t = fp32_fma<true,Hardware>(z, fp32_decode(0x3f000000u), fp32_decode(0xbfa00000u));
49 h = fp32_decode(0x38752140u);
50 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xb9183513u));
51 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x398d9ee0u));
52 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xba2fdf3au));
53 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3ae1130du));
54 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbb8bc302u));
55 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3c2d6773u));
56 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbcd7a178u));
57 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3d86d45du));
58 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbe2e2df9u));
59 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3f14c222u));
61 else if (magnitude <= 0x40400000u) {
62 t = fp32_fma<true,Hardware>(z, fp32_decode(0x3e800000u), fp32_decode(0xbfd00000u));
63 h = fp32_decode(0xb947bd66u);
64 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x39dfe5a4u));
65 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xba4a3864u));
66 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3ae2b84bu));
67 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbb813c08u));
68 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3c1129ceu));
69 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbca3c0b8u));
70 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3d3bcdf4u));
71 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbde4f8bcu));
72 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3ec662fcu));
74 else if (magnitude <= 0x40800000u) {
75 t = fp32_fma<true,Hardware>(z, fp32_decode(0x3e800000u), fp32_decode(0xc0480000u));
76 h = fp32_decode(0xb58f6d10u);
77 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x36863471u));
78 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xb758ec9du));
79 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x384b3fb7u));
80 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xb9404721u));
81 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3a356f7bu));
82 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbb2d3d49u));
83 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3c2a7e14u));
84 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbd36d397u));
85 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3e9091d7u));
87 else if (magnitude <= 0x40c00000u) {
88 t = fp32_fma<true,Hardware>(z, fp32_decode(0x3d800000u), fp32_decode(0xbfd00000u));
89 h = fp32_decode(0xb9405fbfu);
90 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x39ab4d5fu));
91 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xb9c08feeu));
92 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3a2bf5fau));
93 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbaa65b2au));
94 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3b1584c1u));
95 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbb86bc79u));
96 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3bf71905u));
97 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbc67da1fu));
98 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3ce35ff2u));
99 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbd76f5e5u));
100 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3e48ced7u));
102 else if (magnitude <= 0x41000000u) {
103 t = fp32_fma<true,Hardware>(z, fp32_decode(0x3d800000u), fp32_decode(0xc0480000u));
104 h = fp32_decode(0xb59171b1u);
105 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3671d749u));
106 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xb72757e1u));
107 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x380d4deeu));
108 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xb8f4646bu));
109 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x39d46b54u));
110 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbabdbc02u));
111 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3bb1ed8au));
112 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbcb95c19u));
113 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3e10d0b5u));
116 t = fp32_fma<true,Hardware>(z, fp32_decode(0x3d000000u), fp32_decode(0xc0240000u));
117 h = fp32_decode(0xb811c415u);
118 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x38c8e73cu));
119 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xb980a2b8u));
120 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3a37296bu));
121 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbb06690eu));
122 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3bcea86au));
123 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0xbcb08499u));
124 h = fp32_fma<true,Hardware>(h, t, fp32_decode(0x3de229ecu));
127 unsigned int rounded_magnitude = fp32_encode(fp32_mul<true,Hardware>(x, h));
128 return (rounded_magnitude > 0x3f800000u ? 0x3f800000u : rounded_magnitude) | sign;
130 template <
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
131 [[nodiscard]] native_constexpr native_inline native_const
float tanh(
float value) {
132 return fp32_decode(tanh_words<Hardware>(fp32_encode(value)));
FP32 bit casts, precise arithmetic and signed flush-to-zero normalization.