2 * Single-precision vector 2^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.962 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)
31 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
)
33 /* 2^n may overflow, break it up into s1*s2. */
34 v_u32_t b
= v_cond_u32 (n
<= v_f32 (0.0f
)) & v_u32 (0x82000000);
35 v_f32_t s1
= v_as_f32_u32 (v_u32 (0x7f000000) + b
);
36 v_f32_t s2
= v_as_f32_u32 (e
- b
);
37 v_u32_t cmp2
= v_cond_u32 (absn
> v_f32 (192.0f
));
38 v_u32_t r2
= v_as_u32_f32 (s1
* s1
);
39 v_u32_t r1
= v_as_u32_f32 (v_fma_f32 (poly
, s2
, s2
) * s1
);
40 /* Similar to r1 but avoids double rounding in the subnormal range. */
41 v_u32_t r0
= v_as_u32_f32 (v_fma_f32 (poly
, scale
, scale
));
42 return v_as_f32_u32 ((cmp2
& r2
) | (~cmp2
& cmp1
& r1
) | (~cmp1
& r0
));
47 V_NAME(exp2f
) (v_f32_t x
)
49 v_f32_t n
, r
, r2
, scale
, p
, q
, poly
, absn
;
52 /* exp2(x) = 2^n (1 + poly(r)), with 1 + poly(r) in [1/sqrt(2),sqrt(2)]
53 x = n + r, with r in [-1/2, 1/2]. */
59 e
= v_as_u32_f32 (z
) << 23;
63 e
= v_as_u32_s32 (v_round_s32 (x
)) << 23;
65 scale
= v_as_f32_u32 (e
+ v_u32 (0x3f800000));
67 cmp
= v_cond_u32 (absn
> v_f32 (126.0f
));
69 p
= v_fma_f32 (C0
, r
, C1
);
70 q
= v_fma_f32 (C2
, r
, C3
);
71 q
= v_fma_f32 (p
, r2
, q
);
73 poly
= v_fma_f32 (q
, r2
, p
);
74 if (unlikely (v_any_u32 (cmp
)))
75 return specialcase (poly
, n
, e
, absn
, cmp
, scale
);
76 return v_fma_f32 (poly
, scale
, scale
);