2 * Single-precision vector e^x function.
4 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 * See https://llvm.org/LICENSE.txt for license information.
6 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
13 static const float Poly
[] = {
14 /* maxerr: 1.45358 +0.5 ulp. */
21 #define C0 v_f32 (Poly[0])
22 #define C1 v_f32 (Poly[1])
23 #define C2 v_f32 (Poly[2])
24 #define C3 v_f32 (Poly[3])
25 #define C4 v_f32 (Poly[4])
27 #define Shift v_f32 (0x1.8p23f)
28 #define InvLn2 v_f32 (0x1.715476p+0f)
29 #define Ln2hi v_f32 (0x1.62e4p-1f)
30 #define Ln2lo v_f32 (0x1.7f7d1cp-20f)
34 specialcase (v_f32_t poly
, v_f32_t n
, v_u32_t e
, v_f32_t absn
, v_u32_t cmp1
, v_f32_t scale
)
36 /* 2^n may overflow, break it up into s1*s2. */
37 v_u32_t b
= v_cond_u32 (n
<= v_f32 (0.0f
)) & v_u32 (0x82000000);
38 v_f32_t s1
= v_as_f32_u32 (v_u32 (0x7f000000) + b
);
39 v_f32_t s2
= v_as_f32_u32 (e
- b
);
40 v_u32_t cmp2
= v_cond_u32 (absn
> v_f32 (192.0f
));
41 v_u32_t r2
= v_as_u32_f32 (s1
* s1
);
42 v_u32_t r1
= v_as_u32_f32 (v_fma_f32 (poly
, s2
, s2
) * s1
);
43 /* Similar to r1 but avoids double rounding in the subnormal range. */
44 v_u32_t r0
= v_as_u32_f32 (v_fma_f32 (poly
, scale
, scale
));
45 return v_as_f32_u32 ((cmp2
& r2
) | (~cmp2
& cmp1
& r1
) | (~cmp1
& r0
));
50 V_NAME(expf
) (v_f32_t x
)
52 v_f32_t n
, r
, r2
, scale
, p
, q
, poly
, absn
, z
;
55 /* exp(x) = 2^n (1 + poly(r)), with 1 + poly(r) in [1/sqrt(2),sqrt(2)]
56 x = ln2*n + r, with r in [-ln2/2, ln2/2]. */
58 z
= v_fma_f32 (x
, InvLn2
, Shift
);
60 r
= v_fma_f32 (n
, -Ln2hi
, x
);
61 r
= v_fma_f32 (n
, -Ln2lo
, r
);
62 e
= v_as_u32_f32 (z
) << 23;
66 r
= v_fma_f32 (n
, -Ln2hi
, x
);
67 r
= v_fma_f32 (n
, -Ln2lo
, r
);
68 e
= v_as_u32_s32 (v_round_s32 (z
)) << 23;
70 scale
= v_as_f32_u32 (e
+ v_u32 (0x3f800000));
72 cmp
= v_cond_u32 (absn
> v_f32 (126.0f
));
74 p
= v_fma_f32 (C0
, r
, C1
);
75 q
= v_fma_f32 (C2
, r
, C3
);
76 q
= v_fma_f32 (p
, r2
, q
);
78 poly
= v_fma_f32 (q
, r2
, p
);
79 if (unlikely (v_any_u32 (cmp
)))
80 return specialcase (poly
, n
, e
, absn
, cmp
, scale
);
81 return v_fma_f32 (poly
, scale
, scale
);