瀏覽代碼

Fixed GTX_multiple for negative values, issue #51

Christophe Riccio 12 年之前
父節點
當前提交
e72f18997c
共有 4 個文件被更改,包括 82 次插入37 次删除
  1. 18 8
      glm/gtx/multiple.hpp
  2. 51 24
      glm/gtx/multiple.inl
  3. 1 0
      readme.txt
  4. 12 5
      test/gtx/gtx_multiple.cpp

+ 18 - 8
glm/gtx/multiple.hpp

@@ -51,18 +51,28 @@ namespace glm
 	/// @addtogroup gtx_multiple
 	/// @{
 
-	//! Higher Multiple number of Source.
-	//! From GLM_GTX_multiple extension.
-	template <typename genType> 
+	/// Higher multiple number of Source.
+	///
+	/// @tparam genType Floating-point or integer scalar or vector types.
+	/// @param Source 
+	/// @param Multiple Must be a null or positive value
+	///
+	/// @see gtx_multiple
+	template <typename genType>
 	genType higherMultiple(
-		genType const & Source, 
+		genType const & Source,
 		genType const & Multiple);
 
-	//! Lower Multiple number of Source.
-	//! From GLM_GTX_multiple extension.
-	template <typename genType> 
+	/// Lower multiple number of Source.
+	///
+	/// @tparam genType Floating-point or integer scalar or vector types.
+	/// @param Source 
+	/// @param Multiple Must be a null or positive value
+	///
+	/// @see gtx_multiple
+	template <typename genType>
 	genType lowerMultiple(
-		genType const & Source, 
+		genType const & Source,
 		genType const & Multiple);
 
 	/// @}

+ 51 - 24
glm/gtx/multiple.inl

@@ -15,51 +15,72 @@ namespace glm
 	//////////////////////
 	// higherMultiple
 
-	template <typename genType> 
+	template <typename genType>
 	GLM_FUNC_QUALIFIER genType higherMultiple
 	(
-		genType const & Source, 
+		genType const & Source,
 		genType const & Multiple
 	)
 	{
-		genType Tmp = Source % Multiple;
-		return Tmp ? Source + Multiple - Tmp : Source;
+		assert(genType(0) <= Multiple);
+	
+		genType SourceSign = sign(Source);
+		genType SourceAbs = abs(Source);
+	
+		genType Tmp = SourceAbs % Multiple;
+		return (Tmp ? SourceAbs + Multiple - Tmp : SourceAbs) * SourceSign;
 	}
 
-	template <> 
+	template <>
 	GLM_FUNC_QUALIFIER detail::half higherMultiple
 	(
-		detail::half const & SourceH, 
+		detail::half const & SourceH,
 		detail::half const & MultipleH
 	)
 	{
 		float Source = SourceH.toFloat();
 		float Multiple = MultipleH.toFloat();
 
-		int Tmp = int(float(Source)) % int(Multiple);
-		return detail::half(Tmp ? Source + Multiple - float(Tmp) : Source);
+		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);
 	}
 
-	template <> 
+	template <>
 	GLM_FUNC_QUALIFIER float higherMultiple
 	(	
-		float const & Source, 
+		float const & Source,
 		float const & Multiple
 	)
 	{
-		int Tmp = int(Source) % int(Multiple);
-		return Tmp ? Source + Multiple - float(Tmp) : Source;
+		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;
 	}
 
-	template <> 
+	template <>
 	GLM_FUNC_QUALIFIER double higherMultiple
 	(
-		double const & Source, 
+		double const & Source,
 		double const & Multiple
 	)
 	{
-		long Tmp = long(Source) % long(Multiple);
-		return Tmp ? Source + Multiple - double(Tmp) : Source;
+		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;
 	}
 
 	VECTORIZE_VEC_VEC(higherMultiple)
@@ -67,10 +88,10 @@ namespace glm
 	//////////////////////
 	// lowerMultiple
 
-	template <typename genType> 
+	template <typename genType>
 	GLM_FUNC_QUALIFIER genType lowerMultiple
 	(
-		genType const & Source, 
+		genType const & Source,
 		genType const & Multiple
 	)
 	{
@@ -78,38 +99,44 @@ namespace glm
 		return Tmp ? Source - Tmp : Source;
 	}
 
-	template <> 
+	template <>
 	GLM_FUNC_QUALIFIER detail::half lowerMultiple
 	(
-		detail::half const & SourceH, 
+		detail::half const & SourceH,
 		detail::half const & MultipleH
 	)
 	{
 		float Source = SourceH.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);
 	}
 
-	template <> 
+	template <>
 	GLM_FUNC_QUALIFIER float lowerMultiple
 	(
-		float const & Source, 
+		float const & Source,
 		float const & Multiple
 	)
 	{
+		assert(float(0) <= Multiple);
+	
 		int Tmp = int(Source) % int(Multiple);
 		return Tmp ? Source - float(Tmp) : Source;
 	}
 
-	template <> 
+	template <>
 	GLM_FUNC_QUALIFIER double lowerMultiple
 	(
-		double const & Source, 
+		double const & Source,
 		double const & Multiple
 	)
 	{
+		assert(double(0) <= Multiple);
+	
 		long Tmp = long(Source) % long(Multiple);
 		return Tmp ? Source - double(Tmp) : Source;
 	}

+ 1 - 0
readme.txt

@@ -47,6 +47,7 @@ GLM 0.9.5.0: 2013-XX-XX
 - Added rotation function to GTX_quaternion (#22)
 - Added precision variation of each type
 - Added quaternion comparison functions
+- Fixed GTX_multiple for negative value
 
 ================================================================================
 GLM 0.9.4.3: 2013-03-20

+ 12 - 5
test/gtx/gtx_multiple.cpp

@@ -15,12 +15,19 @@ int test_higher()
 	int Error(0);
 
 	int Higher0 = glm::higherMultiple(-5, 4);
-	Error += Higher0 == -4 ? 0 : 1;
-	Error += glm::higherMultiple(-4, 4) == -4 ? 0 : 1;
-	Error += glm::higherMultiple(-3, 4) == -4 ? 0 : 1;
-	Error += glm::higherMultiple(-2, 4) == -4 ? 0 : 1;
-	Error += glm::higherMultiple(-1, 4) == -4 ? 0 : 1;
+	Error += Higher0 == -8 ? 0 : 1;
+	int Higher1 = glm::higherMultiple(-4, 4);
+	Error += Higher1 == -4 ? 0 : 1;
+	int Higher2 = glm::higherMultiple(-3, 4);
+	Error += Higher2 == -4 ? 0 : 1;
+	int Higher3 = glm::higherMultiple(-2, 4);
+	Error += Higher3 == -4 ? 0 : 1;
+	int Higher4 = glm::higherMultiple(-1, 4);
+	Error += Higher4 == -4 ? 0 : 1;
 	Error += glm::higherMultiple(0, 4) == 0 ? 0 : 1;
+	Error += glm::higherMultiple(1, 4) == 4 ? 0 : 1;
+	Error += glm::higherMultiple(2, 4) == 4 ? 0 : 1;
+	Error += glm::higherMultiple(3, 4) == 4 ? 0 : 1;
 	Error += glm::higherMultiple(4, 4) == 4 ? 0 : 1;
 	Error += glm::higherMultiple(5, 4) == 8 ? 0 : 1;
 	Error += glm::higherMultiple(6, 4) == 8 ? 0 : 1;