Sine and Cosine function The function sincos() is evaluated by computing the cosine of the angle, then computing the sine based on the cosine using a simplified formula. The sign of the sine as well as a better approximation for the sine when the input angle is close to zero is done using some of the temporary values determined during the cosine computation. [in] x the input angle [out] sin_x the
| 621 | // [out] sin_x the sine of the angle |
| 622 | // [out] cos_x the cosine of the angle |
| 623 | inline void sseSinCos(const __m128 x, __m128& sin_x, __m128& cos_x) |
| 624 | { |
| 625 | // Using a threshold of 2^-7 for the reduced angle seems to provide |
| 626 | // a fairly decent precision (16 bits) to the final result. |
| 627 | static const __m128 SINE_THRESHOLD_SQUARED = _mm_set1_ps( (float) 0.00006103515625 ); |
| 628 | |
| 629 | __m128 xr, xr2, flip_sign_cos_x; |
| 630 | __sse_cos__(x, cos_x, xr, xr2, flip_sign_cos_x); |
| 631 | |
| 632 | // When cos(x) becomes too close to 1, the sin(x) evaluation contains too |
| 633 | // much error. However, in this case, sin(x) ~ x, and we can use xr to |
| 634 | // approximate sin(x) instead. |
| 635 | __m128 sin_x2 = _mm_sub_ps(EONE, _mm_mul_ps(cos_x, cos_x)); |
| 636 | sin_x2 = sseSelect(_mm_cmpgt_ps(xr2, SINE_THRESHOLD_SQUARED), sin_x2, xr2); |
| 637 | sin_x = _mm_sqrt_ps(sin_x2); |
| 638 | |
| 639 | // Flip the sign of sin(x) if the angle was in quadrants 3 or 4. |
| 640 | __m128 xr_sign = _mm_and_ps(xr, ESIGN_MASK); |
| 641 | __m128 flip_sign_sin_x = _mm_xor_ps(flip_sign_cos_x, xr_sign); |
| 642 | sin_x = _mm_xor_ps(sin_x, flip_sign_sin_x); |
| 643 | } |
| 644 | |
| 645 | // Scalar version of sseSinCos |
| 646 | inline void sseSinCos(const float x, float& sin_x, float& cos_x) |