2020
2121namespace LIBC_NAMESPACE_DECL {
2222
23- static constexpr float16 ONE_OVER_TWO = 0 .5f16;
24-
2523#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
2624static constexpr size_t N_ASINPIF16_EXCEPTS = 3 ;
2725
@@ -31,14 +29,12 @@ static constexpr fputil::ExceptValues<float16, N_ASINPIF16_EXCEPTS>
3129 // x = 0.0, asinfpi(0.0) = 0.0
3230 {0x0000 , 0x0000 , 0 , 0 , 0 },
3331
34- // x = 1.0, asinfpi(1) = 1/2
35- {(fputil::FPBits<float16>(1 .0f16)).uintval (),
36- (fputil::FPBits<float16>(ONE_OVER_TWO)).uintval (), 0 , 0 , 0 },
37-
38- // x = -1.0, asinfpi(-1.0) = -1/2
39- {(fputil::FPBits<float16>(-1 .0f16)).uintval (),
40- (fputil::FPBits<float16>(-ONE_OVER_TWO)).uintval (), 0 , 0 , 0 },
32+ // x = 0x1.004p-3, asinpif16(x) = 0x1.47p-5 (RZ)
33+ {0x3001U , 0x291cU , 1U , 0U , 1U },
34+ // x = 0x1.0bp-1, asinpif16(x) = 0x1.658p-3 (RZ)
35+ {0x382cU , 0x3196U , 1U , 0U , 0U },
4136 }};
37+
4238#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
4339
4440LLVM_LIBC_FUNCTION (float16, asinpif16, (float16 x)) {
@@ -94,33 +90,27 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
9490 // it's very accurate in the range [0, 0.5] and has a maximum error of
9591 // 0.0000000000000001 in the range [0, 0.5].
9692 static constexpr double POLY_COEFFS[10 ] = {
97- 0.318309886183791 , // x^1
98- 0.0530516476972984 , // x^3
99- 0.0238732414637843 , // x^5
100- 0.0142102627760621 , // x^7
101- 0.00967087327815336 , // x^9
102- 0.00712127941391293 , // x^11
103- 0.00552355646848375 , // x^13
104- 0.00444514782463692 , // x^15
105- 0.00367705242846804 , // x^17
106- 0.00310721681820837 // x^19
93+ 0x1 .45f306dc9c889p-2 , // x^1
94+ 0x1 .b2995e7b7b5fdp -5 , // x^3
95+ 0x1 .8723a1d588a36p-6 , // x^5
96+ 0x1 .d1a452f20430dp -7 , // x^7
97+ 0x1 .3ce52a3a09f61p-7 , // x^9
98+ 0x1 .d2b33e303d375p -8 , // x^11
99+ 0x1 .69fde663c674fp-8 , // x^13
100+ 0x1 .235134885f19bp-8 , // x^15
107101 };
108-
109102 // polynomial evaluation using horner's method
110103 // work only for |x| in [0, 0.5]
111- auto asinpi_polyeval = [](double xsq) -> double {
112- return fputil::polyeval (xsq, POLY_COEFFS[0 ], POLY_COEFFS[1 ], POLY_COEFFS[2 ],
113- POLY_COEFFS[3 ], POLY_COEFFS[4 ], POLY_COEFFS[5 ],
114- POLY_COEFFS[6 ], POLY_COEFFS[7 ], POLY_COEFFS[8 ],
115- POLY_COEFFS[9 ]);
104+ auto asinpi_polyeval = [](double x) -> double {
105+ return x * fputil::polyeval (x * x, POLY_COEFFS[0 ], POLY_COEFFS[1 ],
106+ POLY_COEFFS[2 ], POLY_COEFFS[3 ], POLY_COEFFS[4 ],
107+ POLY_COEFFS[5 ], POLY_COEFFS[6 ], POLY_COEFFS[7 ]);
116108 };
117109
118110 // if |x| <= 0.5:
119- if (LIBC_UNLIKELY (x_abs <= ONE_OVER_TWO )) {
111+ if (LIBC_UNLIKELY (x_abs <= 0 .5f16 )) {
120112 // Use polynomial approximation of asin(x)/pi in the range [0, 0.5]
121- double xd = static_cast <double >(x);
122- double xsq = xd * xd;
123- double result = xd * asinpi_polyeval (xsq);
113+ double result = asinpi_polyeval (fputil::cast<double >(x_abs));
124114 return fputil::cast<float16>(signed_result (result));
125115 }
126116
@@ -151,11 +141,9 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
151141 // = 0.5 - 0.5 * x
152142 // = multiply_add(-0.5, x, 0.5)
153143
154- double u = static_cast <double >(
155- fputil::multiply_add (-ONE_OVER_TWO, x_abs, ONE_OVER_TWO));
156- double u_sqrt = fputil::sqrt<double >(static_cast <double >(u));
157- double asinpi_sqrt_u = u_sqrt * asinpi_polyeval (u);
158- double result = fputil::multiply_add (-2 .0f16, asinpi_sqrt_u, ONE_OVER_TWO);
144+ double u = fputil::multiply_add (-0.5 , fputil::cast<double >(x_abs), 0.5 );
145+ double asinpi_sqrt_u = asinpi_polyeval (fputil::sqrt<double >(u));
146+ double result = fputil::multiply_add (-2.0 , asinpi_sqrt_u, 0.5 );
159147
160148 return fputil::cast<float16>(signed_result (result));
161149}
0 commit comments