ProtoTank/Engine/Utils/3DMaths_sc.inl

199 lines
6.4 KiB
C++

#pragma once
inline float M3D_ScalarSin(float Value) noexcept {
// Map Value to y in [-pi,pi], x = 2*pi*quotient + remainder.
float quotient = M3D_1DIV2PI * Value;
if (Value >= 0.0f)
quotient = static_cast<float>(static_cast<int>(quotient + 0.5f));
else
quotient = static_cast<float>(static_cast<int>(quotient - 0.5f));
float y = Value - M3D_2PI * quotient;
// Map y to [-pi/2,pi/2] with sin(y) = sin(Value).
if (y > M3D_PIDIV2)
y = M3D_PI - y;
else if (y < -M3D_PIDIV2)
y = -M3D_PI - y;
// 11-degree minimax approximation
float y2 = y * y;
return (((((-2.3889859e-08f * y2 + 2.7525562e-06f) * y2 - 0.00019840874f) * y2 + 0.0083333310f) * y2 - 0.16666667f) * y2 + 1.0f) * y;
}
inline float M3D_ScalarSinEst(float Value) noexcept {
// Map Value to y in [-pi,pi], x = 2*pi*quotient + remainder.
float quotient = M3D_1DIV2PI * Value;
if (Value >= 0.0f)
quotient = static_cast<float>(static_cast<int>(quotient + 0.5f));
else
quotient = static_cast<float>(static_cast<int>(quotient - 0.5f));
float y = Value - M3D_2PI * quotient;
// Map y to [-pi/2,pi/2] with sin(y) = sin(Value).
if (y > M3D_PIDIV2)
y = M3D_PI - y;
else if (y < -M3D_PIDIV2)
y = -M3D_PI - y;
// 7-degree minimax approximation
float y2 = y * y;
return (((-0.00018524670f * y2 + 0.0083139502f) * y2 - 0.16665852f) * y2 + 1.0f) * y;
}
inline float M3D_ScalarCos(float Value) noexcept {
// Map Value to y in [-pi,pi], x = 2*pi*quotient + remainder.
float quotient = M3D_1DIV2PI * Value;
if (Value >= 0.0f)
quotient = static_cast<float>(static_cast<int>(quotient + 0.5f));
else
quotient = static_cast<float>(static_cast<int>(quotient - 0.5f));
float y = Value - M3D_2PI * quotient;
// Map y to [-pi/2,pi/2] with cos(y) = sign*cos(x).
float sign;
if (y > M3D_PIDIV2) {
y = M3D_PI - y;
sign = -1.0f;
} else if (y < -M3D_PIDIV2) {
y = -M3D_PI - y;
sign = -1.0f;
} else {
sign = +1.0f;
}
// 10-degree minimax approximation
float y2 = y * y;
float p = ((((-2.6051615e-07f * y2 + 2.4760495e-05f) * y2 - 0.0013888378f) * y2 + 0.041666638f) * y2 - 0.5f) * y2 + 1.0f;
return sign * p;
}
inline float M3D_ScalarCosEst(float Value) noexcept {
// Map Value to y in [-pi,pi], x = 2*pi*quotient + remainder.
float quotient = M3D_1DIV2PI * Value;
if (Value >= 0.0f)
quotient = static_cast<float>(static_cast<int>(quotient + 0.5f));
else
quotient = static_cast<float>(static_cast<int>(quotient - 0.5f));
float y = Value - M3D_2PI * quotient;
// Map y to [-pi/2,pi/2] with cos(y) = sign*cos(x).
float sign;
if (y > M3D_PIDIV2) {
y = M3D_PI - y;
sign = -1.0f;
} else if (y < -M3D_PIDIV2) {
y = -M3D_PI - y;
sign = -1.0f;
} else {
sign = +1.0f;
}
// 6-degree minimax approximation
float y2 = y * y;
float p = ((-0.0012712436f * y2 + 0.041493919f) * y2 - 0.49992746f) * y2 + 1.0f;
return sign * p;
}
inline float M3D_ScalarASin(float Value) noexcept {
// Clamp input to [-1,1].
bool nonnegative = (Value >= 0.0f);
float x = std::fabs(Value);
float omx = 1.0f - x;
if (omx < 0.0f)
omx = 0.0f;
float root = std::sqrt(omx);
// 7-degree minimax approximation
float result = ((((((-0.0012624911f * x + 0.0066700901f) * x - 0.0170881256f) * x + 0.0308918810f) * x - 0.0501743046f) * x + 0.0889789874f) * x - 0.2145988016f) * x + 1.5707963050f;
result *= root; // acos(|x|)
// acos(x) = pi - acos(-x) when x < 0, asin(x) = pi/2 - acos(x)
return (nonnegative ? M3D_PIDIV2 - result : result - M3D_PIDIV2);
}
inline float M3D_ScalarASinEst(float Value) noexcept {
// Clamp input to [-1,1].
bool nonnegative = (Value >= 0.0f);
float x = std::fabs(Value);
float omx = 1.0f - x;
if (omx < 0.0f)
{
omx = 0.0f;
}
float root = std::sqrt(omx);
// 3-degree minimax approximation
float result = ((-0.0187293f * x + 0.0742610f) * x - 0.2121144f) * x + 1.5707288f;
result *= root; // acos(|x|)
// acos(x) = pi - acos(-x) when x < 0, asin(x) = pi/2 - acos(x)
return (nonnegative ? M3D_PIDIV2 - result : result - M3D_PIDIV2);
}
inline float M3D_ScalarACos(float Value) noexcept {
// Clamp input to [-1,1].
bool nonnegative = (Value >= 0.0f);
float x = std::fabs(Value);
float omx = 1.0f - x;
if (omx < 0.0f)
omx = 0.0f;
float root = std::sqrt(omx);
// 7-degree minimax approximation
float result = ((((((-0.0012624911f * x + 0.0066700901f) * x - 0.0170881256f) * x + 0.0308918810f) * x - 0.0501743046f) * x + 0.0889789874f) * x - 0.2145988016f) * x + 1.5707963050f;
result *= root;
// acos(x) = pi - acos(-x) when x < 0
return (nonnegative ? result : M3D_PI - result);
}
inline float M3D_ScalarACosEst(float Value) noexcept {
// Clamp input to [-1,1].
bool nonnegative = (Value >= 0.0f);
float x = std::fabs(Value);
float omx = 1.0f - x;
if (omx < 0.0f)
omx = 0.0f;
float root = std::sqrt(omx);
// 3-degree minimax approximation
float result = ((-0.0187293f * x + 0.0742610f) * x - 0.2121144f) * x + 1.5707288f;
result *= root;
// acos(x) = pi - acos(-x) when x < 0
return (nonnegative ? result : M3D_PI - result);
}
inline void M3D_ScalarSinCos(float* pSin, float* pCos, float Value) noexcept {
// Map Value to y in [-pi,pi], x = 2*pi*quotient + remainder.
float quotient = M3D_1DIV2PI * Value;
if (Value >= 0.0f)
quotient = static_cast<float>(static_cast<int>(quotient + 0.5f));
else
quotient = static_cast<float>(static_cast<int>(quotient - 0.5f));
float y = Value - M3D_2PI * quotient;
// Map y to [-pi/2,pi/2] with sin(y) = sin(Value).
float sign;
if (y > M3D_PIDIV2) {
y = M3D_PI - y;
sign = -1.0f;
} else if (y < -M3D_PIDIV2) {
y = -M3D_PI - y;
sign = -1.0f;
} else {
sign = +1.0f;
}
float y2 = y * y;
// 11-degree minimax approximation
*pSin = (((((-2.3889859e-08f * y2 + 2.7525562e-06f) * y2 - 0.00019840874f) * y2 + 0.0083333310f) * y2 - 0.16666667f) * y2 + 1.0f) * y;
// 10-degree minimax approximation
float p = ((((-2.6051615e-07f * y2 + 2.4760495e-05f) * y2 - 0.0013888378f) * y2 + 0.041666638f) * y2 - 0.5f) * y2 + 1.0f;
*pCos = sign * p;
}