Browse Source

Completed GTX_multiple for negative values, issue #79

Christophe Riccio 12 years ago
parent
commit
13f27821b9
2 changed files with 97 additions and 40 deletions
  1. 44 36
      glm/gtx/multiple.inl
  2. 53 4
      test/gtx/gtx_multiple.cpp

+ 44 - 36
glm/gtx/multiple.inl

@@ -41,14 +41,13 @@ namespace glm
 		float Source = SourceH.toFloat();
 		float Source = SourceH.toFloat();
 		float Multiple = MultipleH.toFloat();
 		float Multiple = MultipleH.toFloat();
 
 
-		assert(float(0) <= Multiple);
-
-		float SourceSign = sign(Source);
-		float SourceAbs = abs(Source);
-
-		int Tmp = int(float(SourceAbs)) % int(Multiple);
-		return detail::half(
-			(Tmp ? SourceAbs + Multiple - float(Tmp) : SourceAbs) * SourceSign);
+		if (Source > float(0))
+		{
+			float Tmp = Source - float(1);
+			return detail::half(Tmp + (Multiple - std::fmod(Tmp, Multiple)));
+		}
+		else
+			return detail::half(Source + std::fmod(-Source, Multiple));
 	}
 	}
 
 
 	template <>
 	template <>
@@ -58,13 +57,13 @@ namespace glm
 		float const & Multiple
 		float const & Multiple
 	)
 	)
 	{
 	{
-		assert(float(0) <= Multiple);
-	
-		float SourceSign = sign(Source);
-		float SourceAbs = abs(Source);
-				
-		int Tmp = int(SourceAbs) % int(Multiple);
-		return (Tmp ? SourceAbs + Multiple - float(Tmp) : SourceAbs) * SourceSign;
+		if (Source > float(0))
+		{
+			float Tmp = Source - float(1);
+			return Tmp + (Multiple - std::fmod(Tmp, Multiple));
+		}
+		else
+			return Source + std::fmod(-Source, Multiple);
 	}
 	}
 
 
 	template <>
 	template <>
@@ -74,13 +73,13 @@ namespace glm
 		double const & Multiple
 		double const & Multiple
 	)
 	)
 	{
 	{
-		assert(double(0) <= Multiple);
-
-		double SourceSign = sign(Source);
-		double SourceAbs = abs(Source);
-
-		long Tmp = long(SourceAbs) % long(Multiple);
-		return (Tmp ? SourceAbs + Multiple - double(Tmp) : SourceAbs) * SourceSign;
+		if (Source > double(0))
+		{
+			double Tmp = Source - double(1);
+			return Tmp + (Multiple - std::fmod(Tmp, Multiple));
+		}
+		else
+			return Source + std::fmod(-Source, Multiple);
 	}
 	}
 
 
 	VECTORIZE_VEC_VEC(higherMultiple)
 	VECTORIZE_VEC_VEC(higherMultiple)
@@ -95,11 +94,11 @@ namespace glm
 		genType const & Multiple
 		genType const & Multiple
 	)
 	)
 	{
 	{
-		if (Source >= 0)
+		if (Source >= genType(0))
 			return Source - Source % Multiple;
 			return Source - Source % Multiple;
 		else
 		else
 		{
 		{
-			genType Tmp = Source + 1;
+			genType Tmp = Source + genType(1);
 			return Tmp - Tmp % Multiple - Multiple;
 			return Tmp - Tmp % Multiple - Multiple;
 		}
 		}
 	}
 	}
@@ -114,10 +113,13 @@ namespace glm
 		float Source = SourceH.toFloat();
 		float Source = SourceH.toFloat();
 		float Multiple = MultipleH.toFloat();
 		float Multiple = MultipleH.toFloat();
 
 
-		assert(float(0) <= Multiple);
-
-		int Tmp = int(float(Source)) % int(float(Multiple));
-		return detail::half(Tmp ? Source - float(Tmp) : Source);
+		if (Source >= float(0))
+			return detail::half(Source - std::fmod(Source, Multiple));
+		else
+		{
+			float Tmp = Source + float(1);
+			return detail::half(Tmp - std::fmod(Tmp, Multiple) - Multiple);
+		}
 	}
 	}
 
 
 	template <>
 	template <>
@@ -127,10 +129,13 @@ namespace glm
 		float const & Multiple
 		float const & Multiple
 	)
 	)
 	{
 	{
-		assert(float(0) <= Multiple);
-	
-		int Tmp = int(Source) % int(Multiple);
-		return Tmp ? Source - float(Tmp) : Source;
+		if (Source >= float(0))
+			return Source - std::fmod(Source, Multiple);
+		else
+		{
+			float Tmp = Source + float(1);
+			return Tmp - std::fmod(Tmp, Multiple) - Multiple;
+		}
 	}
 	}
 
 
 	template <>
 	template <>
@@ -140,10 +145,13 @@ namespace glm
 		double const & Multiple
 		double const & Multiple
 	)
 	)
 	{
 	{
-		assert(double(0) <= Multiple);
-	
-		long Tmp = long(Source) % long(Multiple);
-		return Tmp ? Source - double(Tmp) : Source;
+		if (Source >= double(0))
+			return Source - std::fmod(Source, Multiple);
+		else
+		{
+			double Tmp = Source + double(1);
+			return Tmp - std::fmod(Tmp, Multiple) - Multiple;
+		}
 	}
 	}
 
 
 	VECTORIZE_VEC_VEC(lowerMultiple)
 	VECTORIZE_VEC_VEC(lowerMultiple)

+ 53 - 4
test/gtx/gtx_multiple.cpp

@@ -10,7 +10,7 @@
 #include <glm/glm.hpp>
 #include <glm/glm.hpp>
 #include <glm/gtx/multiple.hpp>
 #include <glm/gtx/multiple.hpp>
 
 
-int test_higher()
+int test_higher_int()
 {
 {
 	int Error(0);
 	int Error(0);
 
 
@@ -33,7 +33,7 @@ int test_higher()
 	return Error;
 	return Error;
 }
 }
 
 
-int test_Lower()
+int test_Lower_int()
 {
 {
 	int Error(0);
 	int Error(0);
 
 
@@ -56,12 +56,61 @@ int test_Lower()
 	return Error;
 	return Error;
 }
 }
 
 
+int test_higher_double()
+{
+	int Error(0);
+
+	Error += glm::higherMultiple(-9.0, 4.0) == -8.0 ? 0 : 1;
+	Error += glm::higherMultiple(-5.0, 4.0) == -4.0 ? 0 : 1;
+	Error += glm::higherMultiple(-4.0, 4.0) == -4.0 ? 0 : 1;
+	Error += glm::higherMultiple(-3.0, 4.0) == 0.0 ? 0 : 1;
+	Error += glm::higherMultiple(-2.0, 4.0) == 0.0 ? 0 : 1;
+	Error += glm::higherMultiple(-1.0, 4.0) == 0.0 ? 0 : 1;
+	Error += glm::higherMultiple(0.0, 4.0) == 0.0 ? 0 : 1;
+	Error += glm::higherMultiple(1.0, 4.0) == 4.0 ? 0 : 1;
+	Error += glm::higherMultiple(2.0, 4.0) == 4.0 ? 0 : 1;
+	Error += glm::higherMultiple(3.0, 4.0) == 4.0 ? 0 : 1;
+	Error += glm::higherMultiple(4.0, 4.0) == 4.0 ? 0 : 1;
+	Error += glm::higherMultiple(5.0, 4.0) == 8.0 ? 0 : 1;
+	Error += glm::higherMultiple(6.0, 4.0) == 8.0 ? 0 : 1;
+	Error += glm::higherMultiple(7.0, 4.0) == 8.0 ? 0 : 1;
+	Error += glm::higherMultiple(8.0, 4.0) == 8.0 ? 0 : 1;
+	Error += glm::higherMultiple(9.0, 4.0) == 12.0 ? 0 : 1;
+
+	return Error;
+}
+
+int test_Lower_double()
+{
+	int Error(0);
+
+	Error += glm::lowerMultiple(-5.0, 4.0) == -8.0 ? 0 : 1;
+	Error += glm::lowerMultiple(-4.0, 4.0) == -4.0 ? 0 : 1;
+	Error += glm::lowerMultiple(-3.0, 4.0) == -4.0 ? 0 : 1;
+	Error += glm::lowerMultiple(-2.0, 4.0) == -4.0 ? 0 : 1;
+	Error += glm::lowerMultiple(-1.0, 4.0) == -4.0 ? 0 : 1;
+	Error += glm::lowerMultiple(0.0, 4.0) == 0.0 ? 0 : 1;
+	Error += glm::lowerMultiple(1.0, 4.0) == 0.0 ? 0 : 1;
+	Error += glm::lowerMultiple(2.0, 4.0) == 0.0 ? 0 : 1;
+	Error += glm::lowerMultiple(3.0, 4.0) == 0.0 ? 0 : 1;
+	Error += glm::lowerMultiple(4.0, 4.0) == 4.0 ? 0 : 1;
+	Error += glm::lowerMultiple(5.0, 4.0) == 4.0 ? 0 : 1;
+	Error += glm::lowerMultiple(6.0, 4.0) == 4.0 ? 0 : 1;
+	Error += glm::lowerMultiple(7.0, 4.0) == 4.0 ? 0 : 1;
+	Error += glm::lowerMultiple(8.0, 4.0) == 8.0 ? 0 : 1;
+	Error += glm::lowerMultiple(9.0, 4.0) == 8.0 ? 0 : 1;
+
+	return Error;
+}
+
 int main()
 int main()
 {
 {
 	int Error(0);
 	int Error(0);
 
 
-	Error += test_higher();
-	Error += test_Lower();
+	Error += test_higher_int();
+	Error += test_Lower_int();
+	Error += test_higher_double();
+	Error += test_Lower_double();
 
 
 	return Error;
 	return Error;
 }
 }