Thanks Lazy Pony on decomp.me for documenting this! * Calculate 2^x as a float */
| 310 | * Calculate 2^x as a float |
| 311 | */ |
| 312 | f32 pow2(f32 x) |
| 313 | { |
| 314 | s32 frac_index = 0; |
| 315 | union { |
| 316 | s32 l; |
| 317 | f32 f; |
| 318 | } exponent; |
| 319 | exponent.l = (x >= 0.0f ? (s32)(x - 0.5f) : (s32)(x + 0.5f)); // Shift towards 0 and round |
| 320 | f32 pannedval = x - exponent.l; // strictly between 1.5 and -1.5 |
| 321 | |
| 322 | // 2^x will not fit in an IEEE-754 float |
| 323 | if(exponent.l > 128) { |
| 324 | return INFINITY; |
| 325 | } |
| 326 | |
| 327 | // convert to exponent of IEEE-754 float |
| 328 | exponent.l += 127; |
| 329 | exponent.l <<= 23; |
| 330 | |
| 331 | // Calculate the mantissa |
| 332 | |
| 333 | static const f32 scale_frac[] = { 0.0f, 0.5f }; |
| 334 | // { 1 , 1/sqrt2 } |
| 335 | static const f32 two_to_frac[] = {1.0f, 0.70710677f}; |
| 336 | // coefficients of Taylor polynomial of 2^x - 1 at 0: |
| 337 | // 2^x - 1 = (log2) * x + (log2)^2 / 2! * x^2 + ... |
| 338 | static const f32 __two_to_x[] = { |
| 339 | 0.6931472f, 0.24022661, |
| 340 | 0.055502914f, 0.009625022f, |
| 341 | 0.0013131053f, 1.8300806E-4f |
| 342 | }; |
| 343 | |
| 344 | if (pannedval < 0.0f) { |
| 345 | frac_index += 1; |
| 346 | } |
| 347 | |
| 348 | f32 ret = pannedval + scale_frac[frac_index]; |
| 349 | |
| 350 | // Evaluate Taylor polynomial using Horner's method |
| 351 | ret = ret * (ret * (ret * (ret * (ret * (ret * __two_to_x[5] + __two_to_x[4]) + |
| 352 | __two_to_x[3]) + __two_to_x[2]) + __two_to_x[1]) + __two_to_x[0]); |
| 353 | // 2^n * (corrected mantissa) |
| 354 | ret = exponent.f * (0.75f * two_to_frac[frac_index] + ((0.25f + ret) * two_to_frac[frac_index])); |
| 355 | |
| 356 | return ret; |
| 357 | } |
| 358 | } |
no outgoing calls
no test coverage detected