22
33namespace glm
44{
5- // fastPow:
5+ // fastPow
66 template <typename genType>
77 GLM_FUNC_QUALIFIER genType fastPow (genType x, genType y)
88 {
99 return exp (y * log (x));
1010 }
11+
12+ template <>
13+ GLM_FUNC_QUALIFIER float fastPow (float x, float y)
14+ {
15+ // negative y always reciprocal, pow(x, -y) = 1 / pow(x, abs(-y))
16+ // when x is lower than 1.0, you can use this formula. pow(x, y) = 1 / glm::fastPow(1 / x, y)
17+ // ex: when x is '0.3'... pow(0.3, y) = 1 / glm::fastPow(1 / 0.3, y)
18+ uint32_t mantissa = 1065353216U | ((*(uint32_t *)&x) & 0x007FFFFF );
19+ float mx = *(float *)&mantissa;
20+ float lnx = y * float (1.44269504088896338700 ) * ((((*(uint32_t *)&x) >> 23 )-127 ) * float (0.69314718055994528623 ) + ((((float (-0.056571767549593956 ) * mx + float (0.4471786103806078 )) * mx - float (1.4699399880154467 )) * mx + float (2.8211719569953488 )) * mx - float (1.7417780977156199 )));
21+ uint32_t out = ((127U + uint32_t (lnx)) << 23U );
22+ lnx -= uint32_t (lnx);
23+ return (*(float *)(&out)) * ((float (0.34400110689651969 ) * lnx + float (0.65104678030290897 )) * lnx + float (1.0024760564002857 ));
24+ }
25+
26+ template <>
27+ GLM_FUNC_QUALIFIER double fastPow (double x, double y)
28+ {
29+ // negative y always reciprocal, pow(x, -y) = 1 / pow(x, abs(-y))
30+ uint64_t mantissa = 4607182418800017408U | ((*(uint64_t *)&x) & 0x000FFFFFFFFFFFFF );
31+ double mx = *(double *)&mantissa;
32+ double lnx = y * double (1.44269504088896338700 ) * ((((*(uint64_t *)&x) >> 52 )-1023 ) * double (0.69314718055994528623 ) + ((((double (-0.056571767549593956 ) * mx + double (0.4471786103806078 )) * mx - double (1.4699399880154467 )) * mx + double (2.8211719569953488 )) * mx - double (1.7417780977156199 )));
33+ uint64_t out = ((uint64_t )(1023U + uint64_t (lnx)) << 52U );
34+ lnx -= uint64_t (lnx);
35+ return (*(double *)(&out)) * ((double (0.34400110689651969 ) * lnx + double (0.65104678030290897 )) * lnx + double (1.0024760564002857 ));
36+ }
1137
1238 template <length_t L, typename T, qualifier Q>
1339 GLM_FUNC_QUALIFIER vec<L, T, Q> fastPow (vec<L, T, Q> const & x, vec<L, T, Q> const & y)
@@ -34,17 +60,30 @@ namespace glm
3460 }
3561
3662 // fastExp
37- // Note: This function provides accurate results only for value between -1 and 1, else avoid it.
38- template <typename T>
39- GLM_FUNC_QUALIFIER T fastExp (T x)
63+ template <>
64+ GLM_FUNC_QUALIFIER float fastExp (float x)
4065 {
41- // This has a better looking and same performance in release mode than the following code. However, in debug mode it's slower.
42- // return 1.0f + x * (1.0f + x * 0.5f * (1.0f + x * 0.3333333333f * (1.0f + x * 0.25 * (1.0f + x * 0.2f))));
43- T x2 = x * x;
44- T x3 = x2 * x;
45- T x4 = x3 * x;
46- T x5 = x4 * x;
47- return T (1 ) + x + (x2 * T (0.5 )) + (x3 * T (0.1666666667 )) + (x4 * T (0.041666667 )) + (x5 * T (0.008333333333 ));
66+ // negative x always reciprocal, exp(-x) = 1 / exp(abs(-x))
67+ uint32_t out = ((127U + uint32_t (x *= 1 .44269504088896338700f )) << 23U );
68+ float mx = x - uint32_t (x);
69+ /*
70+ //(accurate) 2 degree polynomial exp2(), interval [0, 1]
71+ return (*(float*)(&out)) * ((float(0.34400110689651969) * mx + float(0.65104678030290897)) * mx + float(1.0024760564002857));
72+ */
73+ return (*(float *)(&out)) * (mx + 0 .95696433397203284f );
74+ }
75+
76+ template <>
77+ GLM_FUNC_QUALIFIER double fastExp (double x)
78+ {
79+ // negative x always reciprocal, exp(-x) = 1 / exp(abs(-x))
80+ uint64_t out = ((uint64_t )(1023U + uint64_t (x *= 1.44269504088896338700 )) << 52U );
81+ double mx = x - uint64_t (x);
82+ /*
83+ //(accurate) 2 degree polynomial exp2(), interval [0, 1]
84+ return (*(double*)(&out)) * ((double(0.34400110689651969) * mx + double(0.65104678030290897)) * mx + double(1.0024760564002857));
85+ */
86+ return (*(double *)(&out)) * (mx + 0.95696433397203284 );
4887 }
4988 /* // Try to handle all values of float... but often shower than std::exp, glm::floor and the loop kill the performance
5089 GLM_FUNC_QUALIFIER float fastExp(float x)
@@ -93,14 +132,22 @@ namespace glm
93132 return std::log (x);
94133 }
95134
96- /* Slower than the VC7.1 function...
135+ // Slower than the VC7.1 function...
136+ template <>
97137 GLM_FUNC_QUALIFIER float fastLog (float x)
98138 {
99- float y1 = (x - 1.0f) / (x + 1.0f);
100- float y2 = y1 * y1;
101- return 2.0f * y1 * (1.0f + y2 * (0.3333333333f + y2 * (0.2f + y2 * 0.1428571429f)));
139+ // x less than 1 always negative log(0.2) = -log(1 / 0.2)
140+ uint32_t mantissa = 1065353216U | ((*(uint32_t *)&x) & 0x007FFFFF );
141+ return (((*(uint32_t *)&x) >> 23 )-127 ) * float (0.69314718055994528623 ) + ((float (-0.2390307190544787 ) * (*(float *)&mantissa) + float (1.4033913763229589 )) * (*(float *)&mantissa) - float (1.1609366765682689 ));
142+ }
143+
144+ template <>
145+ GLM_FUNC_QUALIFIER double fastLog (double x)
146+ {
147+ // x less than 1 always negative log(0.2) = -log(1 / 0.2)
148+ uint64_t mantissa = 4607182418800017408U | ((*(uint64_t *)&x) & 0x000FFFFFFFFFFFFF );
149+ return (((*(uint64_t *)&x) >> 52 )-1023 ) * double (0.69314718055994528623 ) + ((double (-0.2390307190544787 ) * (*(double *)&mantissa) + double (1.4033913763229589 )) * (*(double *)&mantissa) - double (1.1609366765682689 ));
102150 }
103- */
104151
105152 template <length_t L, typename T, qualifier Q>
106153 GLM_FUNC_QUALIFIER vec<L, T, Q> fastLog (vec<L, T, Q> const & x)
@@ -115,6 +162,24 @@ namespace glm
115162 return fastExp (static_cast <genType>(0.69314718055994530941723212145818 ) * x);
116163 }
117164
165+ template <>
166+ GLM_FUNC_QUALIFIER float fastExp2 (float x)
167+ {
168+ // negative x always reciprocal, exp2(-x) = 1 / exp2(abs(-x))
169+ uint32_t out = ((127U + uint32_t (x)) << 23U );
170+ x -= uint32_t (x);
171+ return (*(float *)(&out)) * ((float (0.34400110689651969 ) * x + float (0.65104678030290897 )) * x + float (1.0024760564002857 ));
172+ }
173+
174+ template <>
175+ GLM_FUNC_QUALIFIER double fastExp2 (double x)
176+ {
177+ // negative x always reciprocal, exp2(-x) = 1 / exp2(abs(-x))
178+ uint64_t out = ((uint64_t )(1023U + uint64_t (x)) << 52U );
179+ x -= uint64_t (x);
180+ return (*(double *)(&out)) * ((double (0.34400110689651969 ) * x + double (0.65104678030290897 )) * x + double (1.0024760564002857 ));
181+ }
182+
118183 template <length_t L, typename T, qualifier Q>
119184 GLM_FUNC_QUALIFIER vec<L, T, Q> fastExp2 (vec<L, T, Q> const & x)
120185 {
@@ -127,6 +192,20 @@ namespace glm
127192 {
128193 return fastLog (x) / static_cast <genType>(0.69314718055994530941723212145818 );
129194 }
195+
196+ template <>
197+ GLM_FUNC_QUALIFIER float fastLog2 (float x)
198+ {
199+ uint32_t mantissa = 1065353216U | ((*(uint32_t *)&x) & 0x007FFFFF );
200+ return (((*(uint32_t *)&x) >> 23 )-127 ) + ((float (-0.34484843300001944 ) * (*(float *)&mantissa) + float (2.0246657790474698 )) * (*(float *)&mantissa) - float (1.674877586071156 ));
201+ }
202+
203+ template <>
204+ GLM_FUNC_QUALIFIER double fastLog2 (double x)
205+ {
206+ uint64_t mantissa = 4607182418800017408U | ((*(uint64_t *)&x) & 0x000FFFFFFFFFFFFF );
207+ return (((*(uint64_t *)&x) >> 52 )-1023 ) + ((double (-0.34484843300001944 ) * (*(double *)&mantissa) + double (2.0246657790474698 )) * (*(double *)&mantissa) - double (1.674877586071156 ));
208+ }
130209
131210 template <length_t L, typename T, qualifier Q>
132211 GLM_FUNC_QUALIFIER vec<L, T, Q> fastLog2 (vec<L, T, Q> const & x)
0 commit comments