Much more precise fastCos and fastSin

fastCos and fastSin had a max error of ~0.2 on [-pi pi].
The updated version is ~0.000007.
This commit is contained in:
Mathias Labeyrie 2014-11-05 10:55:42 +01:00
parent b0c1777b57
commit 710e13a8e6
2 changed files with 35 additions and 8 deletions

View File

@ -39,6 +39,7 @@
// Dependency: // Dependency:
#include "../glm.hpp" #include "../glm.hpp"
#include "../gtc/constants.hpp"
#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) #if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED))
# pragma message("GLM: GLM_GTX_fast_trigonometry extension included") # pragma message("GLM: GLM_GTX_fast_trigonometry extension included")
@ -49,14 +50,17 @@ namespace glm
/// @addtogroup gtx_fast_trigonometry /// @addtogroup gtx_fast_trigonometry
/// @{ /// @{
//! Wrap an angle to [0 2pi[
//! From GLM_GTX_fast_trigonometry extension.
template <typename T>
GLM_FUNC_DECL T wrapAngle(const T& angle);
//! Faster than the common sin function but less accurate. //! Faster than the common sin function but less accurate.
//! Defined between -2pi and 2pi.
//! From GLM_GTX_fast_trigonometry extension. //! From GLM_GTX_fast_trigonometry extension.
template <typename T> template <typename T>
GLM_FUNC_DECL T fastSin(const T& angle); GLM_FUNC_DECL T fastSin(const T& angle);
//! Faster than the common cos function but less accurate. //! Faster than the common cos function but less accurate.
//! Defined between -2pi and 2pi.
//! From GLM_GTX_fast_trigonometry extension. //! From GLM_GTX_fast_trigonometry extension.
template <typename T> template <typename T>
GLM_FUNC_DECL T fastCos(const T& angle); GLM_FUNC_DECL T fastCos(const T& angle);

View File

@ -9,24 +9,47 @@
namespace glm namespace glm
{ {
// sin
template <typename T> template <typename T>
GLM_FUNC_QUALIFIER T fastSin(T const & x) GLM_FUNC_QUALIFIER T wrapAngle(T const & angle)
{ {
return x - ((x * x * x) / T(6)) + ((x * x * x * x * x) / T(120)) - ((x * x * x * x * x * x * x) / T(5040)); T result = angle - floor<T>(angle * one_over_two_pi<T>()) * two_pi<T>();
result = result > T(0) ? result : -result;
return result;
} }
VECTORIZE_VEC(fastSin) VECTORIZE_VEC(wrapAngle)
template <typename T>
GLM_FUNC_QUALIFIER T cos_52s(T const & x)
{
T const xx(x * x);
return (T(0.9999932946) + xx * (T(-0.4999124376) + xx * (T(0.0414877472) + xx * T(-0.0012712095))));
}
VECTORIZE_VEC(cos_52s)
// cos // cos
template <typename T> template <typename T>
GLM_FUNC_QUALIFIER T fastCos(T const & x) GLM_FUNC_QUALIFIER T fastCos(T const & x)
{ {
return T(1) - (x * x * T(0.5)) + (x * x * x * x * T(0.041666666666)) - (x * x * x * x * x * x * T(0.00138888888888)); T const angle(wrapAngle<T>(x));
if(angle<half_pi<T>()) return cos_52s(angle);
if(angle<pi<T>()) return -cos_52s(pi<T>() - angle);
if(angle<(T(3) * half_pi<T>())) return -cos_52s(angle - pi<T>());
return cos_52s(two_pi<T>() - angle);
} }
VECTORIZE_VEC(fastCos) VECTORIZE_VEC(fastCos)
// sin
template <typename T>
GLM_FUNC_QUALIFIER T fastSin(T const & x)
{
return fastCos<T>(half_pi<T>() - x);
}
VECTORIZE_VEC(fastSin)
// tan // tan
template <typename T> template <typename T>
GLM_FUNC_QUALIFIER T fastTan(T const & x) GLM_FUNC_QUALIFIER T fastTan(T const & x)