Browse Source

Removed reliance on sinf/cosf CRT functions.

Branimir Karadžić 8 years ago
parent
commit
14521c7406
4 changed files with 91 additions and 9 deletions
  1. 10 0
      include/bx/inline/math.inl
  2. 3 0
      include/bx/math.h
  3. 62 8
      src/math.cpp
  4. 16 1
      tests/math_test.cpp

+ 10 - 0
include/bx/inline/math.inl

@@ -122,6 +122,16 @@ namespace bx
 		return _a * _a;
 		return _a * _a;
 	}
 	}
 
 
+	inline float sin(float _a)
+	{
+		return cos(_a - kPiHalf);
+	}
+
+	inline float pow(float _a, float _b)
+	{
+		return exp(_b * log(_a) );
+	}
+
 	inline float exp2(float _a)
 	inline float exp2(float _a)
 	{
 	{
 		return pow(2.0f, _a);
 		return pow(2.0f, _a);

+ 3 - 0
include/bx/math.h

@@ -125,6 +125,9 @@ namespace bx
 	///
 	///
 	float pow(float _a, float _b);
 	float pow(float _a, float _b);
 
 
+	///
+	float exp(float _a);
+
 	///
 	///
 	float exp2(float _a);
 	float exp2(float _a);
 
 

+ 62 - 8
src/math.cpp

@@ -22,24 +22,78 @@ namespace bx
 	const float kHuge = HUGE_VALF;
 	const float kHuge = HUGE_VALF;
 #endif // BX_COMPILER_MSVC
 #endif // BX_COMPILER_MSVC
 
 
-	float sin(float _a)
-	{
-		return ::sinf(_a);
-	}
-
 	float asin(float _a)
 	float asin(float _a)
 	{
 	{
 		return ::asinf(_a);
 		return ::asinf(_a);
 	}
 	}
 
 
+	namespace
+	{
+		static const float kSinC2  = -0.16666667163372039794921875f;
+		static const float kSinC4  =  8.333347737789154052734375e-3f;
+		static const float kSinC6  = -1.9842604524455964565277099609375e-4f;
+		static const float kSinC8  =  2.760012648650445044040679931640625e-6f;
+		static const float kSinC10 = -2.50293279435709337121807038784027099609375e-8f;
+
+		static const float kCosC2  = -0.5f;
+		static const float kCosC4  =  4.166664183139801025390625e-2f;
+		static const float kCosC6  = -1.388833043165504932403564453125e-3f;
+		static const float kCosC8  =  2.47562347794882953166961669921875e-5f;
+		static const float kCosC10 = -2.59630184018533327616751194000244140625e-7f;
+
+	} // namespace
+
 	float cos(float _a)
 	float cos(float _a)
 	{
 	{
-		return ::cosf(_a);
+		const float scaled = _a * 2.0f*kInvPi;
+		const float real   = floor(scaled);
+		const float xx     = _a - real * kPiHalf;
+		const int32_t bits = int32_t(real) & 3;
+
+		float c0, c2, c4, c6, c8, c10;
+
+		if (bits == 0
+		||  bits == 2)
+		{
+			c0  = 1.0f;
+			c2  = kCosC2;
+			c4  = kCosC4;
+			c6  = kCosC6;
+			c8  = kCosC8;
+			c10 = kCosC10;
+		}
+		else
+		{
+			c0  = xx;
+			c2  = kSinC2;
+			c4  = kSinC4;
+			c6  = kSinC6;
+			c8  = kSinC8;
+			c10 = kSinC10;
+		}
+
+		const float xsq = square(xx);
+		float result;
+		result = xsq * c10    + c8;
+		result = xsq * result + c6;
+		result = xsq * result + c4;
+		result = xsq * result + c2;
+		result = xsq * result + 1.0f;
+		result *= c0;
+
+		return bits == 1 || bits == 2
+			? -result
+			:  result
+			;
 	}
 	}
 
 
 	float tan(float _a)
 	float tan(float _a)
 	{
 	{
+#if 0
+		return sin(_a) / cos(_a);
+#else
 		return ::tanf(_a);
 		return ::tanf(_a);
+#endif
 	}
 	}
 
 
 	float acos(float _a)
 	float acos(float _a)
@@ -52,9 +106,9 @@ namespace bx
 		return ::atan2f(_y, _x);
 		return ::atan2f(_y, _x);
 	}
 	}
 
 
-	float pow(float _a, float _b)
+	float exp(float _a)
 	{
 	{
-		return exp(_b * log(_a) );
+		return ::expf(_a);
 	}
 	}
 
 
 	float log(float _a)
 	float log(float _a)

+ 16 - 1
tests/math_test.cpp

@@ -52,10 +52,25 @@ TEST_CASE("libm", "")
 	REQUIRE(bx::equal( 0.89f, bx::fract( 13.89f), 0.000001f) );
 	REQUIRE(bx::equal( 0.89f, bx::fract( 13.89f), 0.000001f) );
 	REQUIRE(bx::equal(-0.89f, bx::fract(-13.89f), 0.000001f) );
 	REQUIRE(bx::equal(-0.89f, bx::fract(-13.89f), 0.000001f) );
 
 
-	for (float xx = 0.0f; xx < 100.0f; xx += 0.1f)
+	for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
 	{
 	{
 		REQUIRE(bx::equal(bx::pow(1.389f, xx), ::pow(1.389f, xx), 0.00001f) );
 		REQUIRE(bx::equal(bx::pow(1.389f, xx), ::pow(1.389f, xx), 0.00001f) );
 	}
 	}
+
+	for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
+	{
+		REQUIRE(bx::equal(bx::sin(xx), ::sin(xx), 0.00001f) );
+	}
+
+	for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
+	{
+		REQUIRE(bx::equal(bx::cos(xx), ::cos(xx), 0.00001f) );
+	}
+
+	for (float xx = -100.0f; xx < 100.0f; xx += 0.1f)
+	{
+		REQUIRE(bx::equal(bx::tan(xx), ::tan(xx), 0.00001f) );
+	}
 }
 }
 
 
 TEST_CASE("ToBits", "")
 TEST_CASE("ToBits", "")