diff --git a/glm/detail/func_integer.hpp b/glm/detail/func_integer.hpp
index 00f4e66f..ad808700 100644
--- a/glm/detail/func_integer.hpp
+++ b/glm/detail/func_integer.hpp
@@ -55,11 +55,11 @@ namespace glm
///
/// @see GLSL uaddCarry man page
/// @see GLSL 4.20.8 specification, section 8.8 Integer Functions
- template
- GLM_FUNC_DECL genUType uaddCarry(
- genUType const & x,
- genUType const & y,
- genUType & carry);
+ template class vecType>
+ GLM_FUNC_DECL vecType uaddCarry(
+ vecType const & x,
+ vecType const & y,
+ vecType & carry);
/// Subtracts the 32-bit unsigned integer y from x, returning
/// the difference if non-negative, or pow(2, 32) plus the difference
@@ -98,12 +98,12 @@ namespace glm
///
/// @see GLSL imulExtended man page
/// @see GLSL 4.20.8 specification, section 8.8 Integer Functions
- template
+ template class vecType>
GLM_FUNC_DECL void imulExtended(
- genIType const & x,
- genIType const & y,
- genIType & msb,
- genIType & lsb);
+ vecType const & x,
+ vecType const & y,
+ vecType & msb,
+ vecType & lsb);
/// Extracts bits [offset, offset + bits - 1] from value,
/// returning them in the least significant bits of the result.
diff --git a/glm/detail/func_integer.inl b/glm/detail/func_integer.inl
index 6ad5c46c..60c224c6 100644
--- a/glm/detail/func_integer.inl
+++ b/glm/detail/func_integer.inl
@@ -42,13 +42,7 @@
namespace glm
{
// uaddCarry
- template <>
- GLM_FUNC_QUALIFIER uint uaddCarry
- (
- uint const & x,
- uint const & y,
- uint & Carry
- )
+ GLM_FUNC_QUALIFIER uint uaddCarry(uint const & x, uint const & y, uint & Carry)
{
uint64 Value64 = static_cast(x) + static_cast(y);
uint32 Result = static_cast(Value64 % (static_cast(1) << static_cast(32)));
@@ -56,46 +50,16 @@ namespace glm
return Result;
}
- template <>
- GLM_FUNC_QUALIFIER uvec2 uaddCarry
- (
- uvec2 const & x,
- uvec2 const & y,
- uvec2 & Carry
- )
+ template class vecType>
+ GLM_FUNC_QUALIFIER vecType uaddCarry(vecType const & x, vecType const & y, vecType & Carry)
{
- return uvec2(
- uaddCarry(x[0], y[0], Carry[0]),
- uaddCarry(x[1], y[1], Carry[1]));
- }
+ vecType Value64(vecType(x) + vecType(y));
+ vecType Result(Value64 % (static_cast(1) << static_cast(32)));
- template <>
- GLM_FUNC_QUALIFIER uvec3 uaddCarry
- (
- uvec3 const & x,
- uvec3 const & y,
- uvec3 & Carry
- )
- {
- return uvec3(
- uaddCarry(x[0], y[0], Carry[0]),
- uaddCarry(x[1], y[1], Carry[1]),
- uaddCarry(x[2], y[2], Carry[2]));
- }
+ vecType DoCarry(greaterThan(Value64 % (static_cast(1) << static_cast(32)), vecType(1)));
+ Carry = mix(vecType(0), vecType(1), DoCarry);
- template <>
- GLM_FUNC_QUALIFIER uvec4 uaddCarry
- (
- uvec4 const & x,
- uvec4 const & y,
- uvec4 & Carry
- )
- {
- return uvec4(
- uaddCarry(x[0], y[0], Carry[0]),
- uaddCarry(x[1], y[1], Carry[1]),
- uaddCarry(x[2], y[2], Carry[2]),
- uaddCarry(x[3], y[3], Carry[3]));
+ return Result;
}
// usubBorrow
@@ -142,14 +106,7 @@ namespace glm
}
// imulExtended
- template <>
- GLM_FUNC_QUALIFIER void imulExtended
- (
- int const & x,
- int const & y,
- int & msb,
- int & lsb
- )
+ GLM_FUNC_QUALIFIER void imulExtended(int x, int y, int & msb, int & lsb)
{
GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch");
@@ -160,109 +117,40 @@ namespace glm
lsb = *PointerLSB;
}
- template <>
- GLM_FUNC_QUALIFIER void imulExtended
- (
- ivec2 const & x,
- ivec2 const & y,
- ivec2 & msb,
- ivec2 & lsb
- )
+ template class vecType>
+ GLM_FUNC_QUALIFIER void imulExtended(vecType const & x, vecType const & y, vecType & msb, vecType & lsb)
{
- imulExtended(x[0], y[0], msb[0], lsb[0]),
- imulExtended(x[1], y[1], msb[1], lsb[1]);
- }
+ GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch");
- template <>
- GLM_FUNC_QUALIFIER void imulExtended
- (
- ivec3 const & x,
- ivec3 const & y,
- ivec3 & msb,
- ivec3 & lsb
- )
- {
- imulExtended(x[0], y[0], msb[0], lsb[0]),
- imulExtended(x[1], y[1], msb[1], lsb[1]);
- imulExtended(x[2], y[2], msb[2], lsb[2]);
- }
-
- template <>
- GLM_FUNC_QUALIFIER void imulExtended
- (
- ivec4 const & x,
- ivec4 const & y,
- ivec4 & msb,
- ivec4 & lsb
- )
- {
- imulExtended(x[0], y[0], msb[0], lsb[0]),
- imulExtended(x[1], y[1], msb[1], lsb[1]);
- imulExtended(x[2], y[2], msb[2], lsb[2]);
- imulExtended(x[3], y[3], msb[3], lsb[3]);
+ vecType Value64(vecType(x) * vecType(y));
+ lsb = vecType(Value64 & static_cast(0xFFFFFFFF));
+ msb = vecType((Value64 >> static_cast(32)) & static_cast(0xFFFFFFFF));
}
// bitfieldExtract
template
- GLM_FUNC_QUALIFIER genIUType bitfieldExtract
- (
- genIUType const & Value,
- int const & Offset,
- int const & Bits
- )
+ GLM_FUNC_QUALIFIER genIUType bitfieldExtract(genIUType Value, int Offset, int Bits)
{
- int GenSize = int(sizeof(genIUType)) << int(3);
+ return bitfieldExtract(tvec1(Value), Offset, Bits).x;
+ }
+
+ template class vecType>
+ GLM_FUNC_QUALIFIER vecType bitfieldExtract(vecType const & Value, int const & Offset, int const & Bits)
+ {
+ GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldExtract' only accept integer inputs");
+
+ int GenSize = int(sizeof(T)) << int(3);
assert(Offset + Bits <= GenSize);
- genIUType ShiftLeft = Bits ? Value << (GenSize - (Bits + Offset)) : genIUType(0);
- genIUType ShiftBack = ShiftLeft >> genIUType(GenSize - Bits);
+ vecType ShiftLeft(0);
+ if(Bits)
+ ShiftLeft = Value << static_cast(GenSize - (Bits + Offset));
+ vecType const ShiftBack = ShiftLeft >> static_cast(GenSize - Bits);
return ShiftBack;
}
- template
- GLM_FUNC_QUALIFIER tvec2 bitfieldExtract
- (
- tvec2 const & Value,
- int const & Offset,
- int const & Bits
- )
- {
- return tvec2(
- bitfieldExtract(Value[0], Offset, Bits),
- bitfieldExtract(Value[1], Offset, Bits));
- }
-
- template
- GLM_FUNC_QUALIFIER tvec3 bitfieldExtract
- (
- tvec3 const & Value,
- int const & Offset,
- int const & Bits
- )
- {
- return tvec3(
- bitfieldExtract(Value[0], Offset, Bits),
- bitfieldExtract(Value[1], Offset, Bits),
- bitfieldExtract(Value[2], Offset, Bits));
- }
-
- template
- GLM_FUNC_QUALIFIER tvec4 bitfieldExtract
- (
- tvec4 const & Value,
- int const & Offset,
- int const & Bits
- )
- {
- return tvec4(
- bitfieldExtract(Value[0], Offset, Bits),
- bitfieldExtract(Value[1], Offset, Bits),
- bitfieldExtract(Value[2], Offset, Bits),
- bitfieldExtract(Value[3], Offset, Bits));
- }
-
// bitfieldInsert
template
GLM_FUNC_QUALIFIER genIUType bitfieldInsert
diff --git a/test/core/core_func_integer.cpp b/test/core/core_func_integer.cpp
index 044c8644..764e5341 100644
--- a/test/core/core_func_integer.cpp
+++ b/test/core/core_func_integer.cpp
@@ -220,6 +220,66 @@ namespace findLSB
}
}//findLSB
+namespace uaddCarry
+{
+ int test()
+ {
+ int Error(0);
+
+ {
+ glm::uint x = 16;
+ glm::uint y = 17;
+ glm::uint Carry = 0;
+ glm::uint Result = glm::uaddCarry(x, y, Carry);
+
+ Error += Carry == 1 ? 0 : 1;
+ Error += Result == 33 ? 0 : 1;
+ }
+
+ {
+ glm::uvec1 x(16);
+ glm::uvec1 y(17);
+ glm::uvec1 Carry(0);
+ glm::uvec1 Result(glm::uaddCarry(x, y, Carry));
+
+ Error += glm::all(glm::equal(Carry, glm::uvec1(1))) ? 0 : 1;
+ Error += glm::all(glm::equal(Result, glm::uvec1(33))) ? 0 : 1;
+ }
+
+ {
+ glm::uvec2 x(16);
+ glm::uvec2 y(17);
+ glm::uvec2 Carry(0);
+ glm::uvec2 Result(glm::uaddCarry(x, y, Carry));
+
+ Error += glm::all(glm::equal(Carry, glm::uvec2(1))) ? 0 : 1;
+ Error += glm::all(glm::equal(Result, glm::uvec2(33))) ? 0 : 1;
+ }
+
+ {
+ glm::uvec3 x(16);
+ glm::uvec3 y(17);
+ glm::uvec3 Carry(0);
+ glm::uvec3 Result(glm::uaddCarry(x, y, Carry));
+
+ Error += glm::all(glm::equal(Carry, glm::uvec3(1))) ? 0 : 1;
+ Error += glm::all(glm::equal(Result, glm::uvec3(33))) ? 0 : 1;
+ }
+
+ {
+ glm::uvec4 x(16);
+ glm::uvec4 y(17);
+ glm::uvec4 Carry(0);
+ glm::uvec4 Result(glm::uaddCarry(x, y, Carry));
+
+ Error += glm::all(glm::equal(Carry, glm::uvec4(1))) ? 0 : 1;
+ Error += glm::all(glm::equal(Result, glm::uvec4(33))) ? 0 : 1;
+ }
+
+ return Error;
+ }
+}//namespace uaddCarry
+
namespace usubBorrow
{
int test()
@@ -280,12 +340,145 @@ namespace usubBorrow
}
}//namespace usubBorrow
+namespace umulExtended
+{
+ int test()
+ {
+ int Error(0);
+
+ {
+ glm::uint x = 2;
+ glm::uint y = 3;
+ glm::uint msb = 0;
+ glm::uint lsb = 0;
+ glm::umulExtended(x, y, msb, lsb);
+
+ Error += msb == 0 ? 0 : 1;
+ Error += lsb == 6 ? 0 : 1;
+ }
+
+ {
+ glm::uvec1 x(2);
+ glm::uvec1 y(3);
+ glm::uvec1 msb(0);
+ glm::uvec1 lsb(0);
+ glm::umulExtended(x, y, msb, lsb);
+
+ Error += glm::all(glm::equal(msb, glm::uvec1(0))) ? 0 : 1;
+ Error += glm::all(glm::equal(lsb, glm::uvec1(6))) ? 0 : 1;
+ }
+
+ {
+ glm::uvec2 x(2);
+ glm::uvec2 y(3);
+ glm::uvec2 msb(0);
+ glm::uvec2 lsb(0);
+ glm::umulExtended(x, y, msb, lsb);
+
+ Error += glm::all(glm::equal(msb, glm::uvec2(0))) ? 0 : 1;
+ Error += glm::all(glm::equal(lsb, glm::uvec2(6))) ? 0 : 1;
+ }
+
+ {
+ glm::uvec3 x(2);
+ glm::uvec3 y(3);
+ glm::uvec3 msb(0);
+ glm::uvec3 lsb(0);
+ glm::umulExtended(x, y, msb, lsb);
+
+ Error += glm::all(glm::equal(msb, glm::uvec3(0))) ? 0 : 1;
+ Error += glm::all(glm::equal(lsb, glm::uvec3(6))) ? 0 : 1;
+ }
+
+ {
+ glm::uvec4 x(2);
+ glm::uvec4 y(3);
+ glm::uvec4 msb(0);
+ glm::uvec4 lsb(0);
+ glm::umulExtended(x, y, msb, lsb);
+
+ Error += glm::all(glm::equal(msb, glm::uvec4(0))) ? 0 : 1;
+ Error += glm::all(glm::equal(lsb, glm::uvec4(6))) ? 0 : 1;
+ }
+
+ return Error;
+ }
+}//namespace umulExtended
+
+namespace imulExtended
+{
+ int test()
+ {
+ int Error(0);
+
+ {
+ int x = 2;
+ int y = 3;
+ int msb = 0;
+ int lsb = 0;
+ glm::imulExtended(x, y, msb, lsb);
+
+ Error += msb == 0 ? 0 : 1;
+ Error += lsb == 6 ? 0 : 1;
+ }
+
+ {
+ glm::ivec1 x(2);
+ glm::ivec1 y(3);
+ glm::ivec1 msb(0);
+ glm::ivec1 lsb(0);
+ glm::imulExtended(x, y, msb, lsb);
+
+ Error += glm::all(glm::equal(msb, glm::ivec1(0))) ? 0 : 1;
+ Error += glm::all(glm::equal(lsb, glm::ivec1(6))) ? 0 : 1;
+ }
+
+ {
+ glm::ivec2 x(2);
+ glm::ivec2 y(3);
+ glm::ivec2 msb(0);
+ glm::ivec2 lsb(0);
+ glm::imulExtended(x, y, msb, lsb);
+
+ Error += glm::all(glm::equal(msb, glm::ivec2(0))) ? 0 : 1;
+ Error += glm::all(glm::equal(lsb, glm::ivec2(6))) ? 0 : 1;
+ }
+
+ {
+ glm::ivec3 x(2);
+ glm::ivec3 y(3);
+ glm::ivec3 msb(0);
+ glm::ivec3 lsb(0);
+ glm::imulExtended(x, y, msb, lsb);
+
+ Error += glm::all(glm::equal(msb, glm::ivec3(0))) ? 0 : 1;
+ Error += glm::all(glm::equal(lsb, glm::ivec3(6))) ? 0 : 1;
+ }
+
+ {
+ glm::ivec4 x(2);
+ glm::ivec4 y(3);
+ glm::ivec4 msb(0);
+ glm::ivec4 lsb(0);
+ glm::imulExtended(x, y, msb, lsb);
+
+ Error += glm::all(glm::equal(msb, glm::ivec4(0))) ? 0 : 1;
+ Error += glm::all(glm::equal(lsb, glm::ivec4(6))) ? 0 : 1;
+ }
+
+ return Error;
+ }
+}//namespace imulExtended
+
int main()
{
int Error = 0;
std::cout << "sizeof(glm::uint64): " << sizeof(glm::detail::uint64) << std::endl;
+ Error += ::umulExtended::test();
+ Error += ::imulExtended::test();
+ Error += ::uaddCarry::test();
Error += ::usubBorrow::test();
Error += ::bitfieldExtract::test();
Error += ::bitfieldReverse::test();