Skip to content

Commit a04132c

Browse files
ZvRzyan18christophe-lunarg
authored andcommitted
Reimplement glm::fastTan, glm::fastAsin, glm::fastAcos, glm::fastAtan
1 parent 903308d commit a04132c

File tree

1 file changed

+76
-8
lines changed

1 file changed

+76
-8
lines changed

glm/gtx/fast_trigonometry.inl

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,36 @@ namespace detail
2525
{
2626
return detail::functor1<vec, L, T, T, Q>::call(cos_52s, x);
2727
}
28+
29+
30+
31+
//polynomials
32+
template<typename T>
33+
GLM_FUNC_QUALIFIER T tanPoly(T x, T sign)
34+
{
35+
return sign * ((((((T(-9.580235e-4) * x + T(1.025743e-2)) * x - T(1.964406e-3)) * x - T(1.656241e-1)) * x - T(2.652585e-4)) * x + T(1.000025e-0)) * x - T(3.973469e-7))
36+
/ ((((((T(-9.580235e-4) * x - T(1.228280e-3)) * x + T(4.313990e-2)) * x - T(8.634596e-4)) * x - T(4.997638e-1)) * x - T(2.400507e-5)) * x + T(1.000000e-0));
37+
}
38+
39+
template<typename T>
40+
GLM_FUNC_QUALIFIER T asinPoly(T x)
41+
{
42+
return ((((((T(1.550104e-1) * x - T(6.284173e-2)) * x + T(5.446719e-2)) * x + T(1.561094e-1)) * x + T(9.531123e-4)) * x + T(9.999680e-1)) * x + T(1.740546e-7));
43+
}
44+
45+
template<typename T>
46+
GLM_FUNC_QUALIFIER T acosPoly(T x)
47+
{
48+
return ((((((T(-1.550104e-1) * x + T(6.284173e-2)) * x - 5.446719e-2) * x - T(1.561094e-1)) * x - T(9.531123e-4)) * x - T(9.999680e-1)) * x + T(1.570796e-0));
49+
}
2850
}//namespace detail
2951

3052
// wrapAngle
3153
template<typename T>
3254
GLM_FUNC_QUALIFIER T wrapAngle(T angle)
3355
{
56+
//glm::trunc() is much faster than glm::mod but i got an error when i try to use it
57+
//return abs<T>(angle - trunc<T>(angle * T(0.15915494309189534561)) * two_pi<T>());
3458
return abs<T>(mod<T>(angle, two_pi<T>()));
3559
}
3660

@@ -79,7 +103,28 @@ namespace detail
79103
template<typename T>
80104
GLM_FUNC_QUALIFIER T fastTan(T x)
81105
{
82-
return x + (x * x * x * T(0.3333333333)) + (x * x * x * x * x * T(0.1333333333333)) + (x * x * x * x * x * x * x * T(0.0539682539));
106+
T ms = (x < T(0.0)) ? T(-1.0) : T(1.0);
107+
T mx = x * ms;
108+
109+
if(mx > two_pi<T>())
110+
mx = wrapAngle<T>(mx);
111+
112+
switch((int)(mx * T(0.6366197))) //(1.0 / half_pi<T>())
113+
{
114+
case 0:
115+
return detail::tanPoly<T>(mx, ms);
116+
break;
117+
case 1:
118+
return -detail::tanPoly<T>(pi<T>() - mx, ms);
119+
break;
120+
case 2:
121+
return detail::tanPoly<T>(mx - pi<T>(), ms);
122+
break;
123+
case 3:
124+
return -detail::tanPoly<T>(two_pi<T>() - mx, ms);
125+
break;
126+
}
127+
return T(NAN);
83128
}
84129

85130
template<length_t L, typename T, qualifier Q>
@@ -92,7 +137,11 @@ namespace detail
92137
template<typename T>
93138
GLM_FUNC_QUALIFIER T fastAsin(T x)
94139
{
95-
return x + (x * x * x * T(0.166666667)) + (x * x * x * x * x * T(0.075)) + (x * x * x * x * x * x * x * T(0.0446428571)) + (x * x * x * x * x * x * x * x * x * T(0.0303819444));// + (x * x * x * x * x * x * x * x * x * x * x * T(0.022372159));
140+
T ms = (x < T(0.0)) ? T(-1.0) : T(1.0);
141+
T mx = x * ms;
142+
if(mx > T(0.5))
143+
return ms * (half_pi<T>() - T(2.0) * detail::asinPoly<T>(fastSqrt<T>((T(1.0) - mx) * T(0.5))) );
144+
return ms * detail::asinPoly<T>(mx);
96145
}
97146

98147
template<length_t L, typename T, qualifier Q>
@@ -105,7 +154,18 @@ namespace detail
105154
template<typename T>
106155
GLM_FUNC_QUALIFIER T fastAcos(T x)
107156
{
108-
return T(1.5707963267948966192313216916398) - fastAsin(x); //(PI / 2)
157+
bool is_negative = (x < T(0.0));
158+
T mx = is_negative ? -x : x;
159+
160+
if(is_negative)
161+
{
162+
if(mx > T(0.5))
163+
return T(2.0) * detail::acosPoly<T>(fastSqrt<T>((T(1.0) - mx) * T(0.5)));
164+
return pi<T>() - detail::acosPoly<T>(mx);
165+
}
166+
if(mx > T(0.5))
167+
return (pi<T>() - T(2.0) * detail::acosPoly<T>(fastSqrt<T>((T(1.0) - mx) * T(0.5))) );
168+
return detail::acosPoly<T>(mx);
109169
}
110170

111171
template<length_t L, typename T, qualifier Q>
@@ -114,24 +174,32 @@ namespace detail
114174
return detail::functor1<vec, L, T, T, Q>::call(fastAcos, x);
115175
}
116176

117-
// atan
177+
// atan2
118178
template<typename T>
119179
GLM_FUNC_QUALIFIER T fastAtan(T y, T x)
120180
{
121-
T sgn = sign(y) * sign(x);
122-
return abs(fastAtan(y / x)) * sgn;
181+
if (y < T(0.0) && x < T(0.0))
182+
return fastAtan<T>(y / x) - pi<T>();
183+
else if(y > T(0.0) && x < T(0.0))
184+
return fastAtan<T>(y / x) + pi<T>();
185+
return fastAtan<T>(y / x);
123186
}
124187

125188
template<length_t L, typename T, qualifier Q>
126189
GLM_FUNC_QUALIFIER vec<L, T, Q> fastAtan(vec<L, T, Q> const& y, vec<L, T, Q> const& x)
127190
{
128191
return detail::functor2<vec, L, T, Q>::call(fastAtan, y, x);
129192
}
130-
193+
// atan
131194
template<typename T>
132195
GLM_FUNC_QUALIFIER T fastAtan(T x)
133196
{
134-
return x - (x * x * x * T(0.333333333333)) + (x * x * x * x * x * T(0.2)) - (x * x * x * x * x * x * x * T(0.1428571429)) + (x * x * x * x * x * x * x * x * x * T(0.111111111111)) - (x * x * x * x * x * x * x * x * x * x * x * T(0.0909090909));
197+
T ms = (x < T(0.0)) ? T(-1.0) : T(1.0);
198+
T mx = x * ms;
199+
mx = (mx * fastInverseSqrt<T>(T(1.0) + mx * mx));
200+
if(mx > T(0.5))
201+
return ms * (half_pi<T>() - T(2.0) * detail::asinPoly<T>(fastSqrt<T>((T(1.0) - mx) * T(0.5))));
202+
return ms * detail::asinPoly<T>(mx);
135203
}
136204

137205
template<length_t L, typename T, qualifier Q>

0 commit comments

Comments
 (0)