1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
#ifndef DataFormatsMathapprox_asin_h
#define DataFormatsMathapprox_asin_h
#include <cmath>
template <int DEGREE>
constexpr float approx_asin_P(float z);
// degree = 3 => absolute accuracy is 8 bits
template <>
constexpr float approx_asin_P<3>(float z) {
return 1.f + z * 0.2133004963397979736328125f;
}
// degree = 5 => absolute accuracy is 11 bits
template <>
constexpr float approx_asin_P<5>(float z) {
return 1.f + z * (0.154711246490478515625f + z * 0.1322681009769439697265625f);
}
// degree = 7 => absolute accuracy is 15 bits
template <>
constexpr float approx_asin_P<7>(float z) {
return 1.f + z * (0.169519245624542236328125f + z * (4.9031913280487060546875e-2f + z * 0.10941398143768310546875));
}
// degree = 9 => absolute accuracy is 18 bits
template <>
constexpr float approx_asin_P<9>(float z) {
return 1.f + z * (0.166020572185516357421875f +
z * (8.44048559665679931640625e-2f +
z * (1.11602735705673694610595703125e-3f + z * 0.103476583957672119140625f)));
}
// degree = 11 => absolute accuracy is 21 bits
template <>
constexpr float approx_asin_P<11>(float z) {
return 1.f + z * (0.1668075025081634521484375f +
z * (7.20207393169403076171875e-2f +
z * (6.607978045940399169921875e-2f +
z * ((-3.6048568785190582275390625e-2f) + z * 0.10574872791767120361328125f))));
}
/*
// degree = 3 => absolute accuracy is 8 bits
template<> constexpr float approx_asin_P< 3 >(float z){
return 1.f + z * 0.2114248573780059814453125f;
}
// degree = 5 => absolute accuracy is 12 bits
template<> constexpr float approx_asin_P< 5 >(float z){
return 1.f + z * (0.1556626856327056884765625f + z * 0.1295671761035919189453125f);
}
// degree = 7 => absolute accuracy is 15 bits
template<> constexpr float approx_asin_P< 7 >(float z){
return 1.f + z * (0.1691854894161224365234375f + z * (5.1305986940860748291015625e-2f + z * 0.1058919131755828857421875f));
}
// degree = 9 => absolute accuracy is 18 bits
template<> constexpr float approx_asin_P< 9 >(float z){
return 1.f + z * (0.166119158267974853515625f + z * (8.322779834270477294921875e-2f + z * (5.28236292302608489990234375e-3f + z * 9.89462435245513916015625e-2f)));
}
// degree = 11 => absolute accuracy is 21 bits
template<> constexpr float approx_asin_P< 11 >(float z){
return 1.f + z * (0.1667812168598175048828125f + z * (7.249967753887176513671875e-2f + z * (6.321799755096435546875e-2f + z * ((-2.913488447666168212890625e-2f) + z * 9.9913299083709716796875e-2f))));
}
*/
// valid for |x|<0.71
template <int DEGREE>
constexpr float unsafe_asin07(float x) {
auto z = x * x;
return x * approx_asin_P<DEGREE>(z);
}
template <int DEGREE>
constexpr float unsafe_acos07(float x) {
constexpr float pihalf = M_PI / 2;
return pihalf - unsafe_asin07<DEGREE>(x);
}
// for |x|> 0.71 use slower
template <int DEGREE>
constexpr float unsafe_acos71(float x) {
constexpr float pi = M_PI;
auto z = 1.f - x * x;
z = std::sqrt(z) * approx_asin_P<DEGREE>(z);
return x > 0 ? z : pi - z;
}
template <int DEGREE>
constexpr float unsafe_asin71(float x) {
constexpr float pihalf = M_PI / 2;
return pihalf - unsafe_acos71<DEGREE>(x);
}
template <int DEGREE>
constexpr float unsafe_asin(float x) {
return (std::abs(x) < 0.71f) ? unsafe_asin07<DEGREE>(x) : unsafe_asin71<DEGREE>(x);
}
template <int DEGREE>
constexpr float unsafe_acos(float x) {
return (std::abs(x) < 0.71f) ? unsafe_acos07<DEGREE>(x) : unsafe_acos71<DEGREE>(x);
}
#endif
|