From 7bd282517ca6f4eaa2679a21629e36e3acdebebd Mon Sep 17 00:00:00 2001 From: apradhana Date: Wed, 5 Mar 2025 10:34:06 -0800 Subject: [PATCH 1/4] Add more test in TestMath.cc. Signed-off-by: apradhana --- openvdb/openvdb/unittest/TestMath.cc | 180 +++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) diff --git a/openvdb/openvdb/unittest/TestMath.cc b/openvdb/openvdb/unittest/TestMath.cc index e7e721e7a1..a9565edc23 100644 --- a/openvdb/openvdb/unittest/TestMath.cc +++ b/openvdb/openvdb/unittest/TestMath.cc @@ -13,6 +13,185 @@ class TestMath: public ::testing::Test { }; +// Testing the operators within the member functions of Vec3 +template +void testMemberOperatorsImpl() +{ + using namespace openvdb; + using Vec3T = math::Vec3; + + { + Vec3T vecA(3.14,2.18,ValueT(-299792458.f)); + + // Alternative indexed the elements + EXPECT_EQ(vecA(0), ValueT(3.14)); + EXPECT_EQ(vecA(1), ValueT(2.18)); + EXPECT_EQ(vecA(2), ValueT(-299792458.f)); + + // Assignment operator + Vec3T vecB = vecA; + EXPECT_EQ(vecB(0), vecA(0)); + EXPECT_EQ(vecB(1), vecA(1)); + EXPECT_EQ(vecB(2), vecA(2)); + + // Negation operator + Vec3T vecC = -vecA; + EXPECT_EQ(vecC(0), -vecA(0)); + EXPECT_EQ(vecC(1), -vecA(1)); + EXPECT_EQ(vecC(2), -vecA(2)); + + // Multiply each element of the vector by a scalar + Vec3T vecD = vecA; + const ValueT gr = ValueT(1.6180339887); + vecD *= gr; + EXPECT_EQ(vecD(0), ValueT(gr * vecA(0))); + EXPECT_EQ(vecD(1), ValueT(gr * vecA(1))); + EXPECT_EQ(vecD(2), ValueT(gr * vecA(2))); + + // Multiply each element of the vector by the corresponding element + Vec3T vecE = vecA; + Vec3T vecF(-2.5, 1.2, 3.14159); + vecE *= vecF; + EXPECT_EQ(vecE(0), ValueT(vecA(0) * vecF(0))); + EXPECT_EQ(vecE(1), ValueT(vecA(1) * vecF(1))); + EXPECT_EQ(vecE(2), ValueT(vecA(2) * vecF(2))); + + // Divide each element of the vector by a scalar + Vec3T vecG = vecA; + vecG /= gr; + EXPECT_EQ(vecG(0), ValueT(vecA(0) / gr)); + EXPECT_EQ(vecG(1), ValueT(vecA(1) / gr)); + EXPECT_EQ(vecG(2), ValueT(vecA(2) / gr)); + + // Divide each element of the vector by the corresponding element of the given vector + Vec3T vecH = vecA; + vecH /= vecF; + EXPECT_EQ(vecH(0), ValueT(vecA(0) / vecF(0))); + EXPECT_EQ(vecH(1), ValueT(vecA(1) / vecF(1))); + EXPECT_EQ(vecH(2), ValueT(vecA(2) / vecF(2))); + + // Add a scalar to each element of the vector + Vec3T vecI = vecA; + vecI += gr; + EXPECT_EQ(vecI(0), ValueT(vecA(0) + gr)); + EXPECT_EQ(vecI(1), ValueT(vecA(1) + gr)); + EXPECT_EQ(vecI(2), ValueT(vecA(2) + gr)); + + // Add each element of the given vector to the corresponding element of this vector + Vec3T vecJ = vecA; + vecJ += vecF; + EXPECT_EQ(vecJ(0), ValueT(vecA(0) + vecF(0))); + EXPECT_EQ(vecJ(1), ValueT(vecA(1) + vecF(1))); + EXPECT_EQ(vecJ(2), ValueT(vecA(2) + vecF(2))); + + // Subtract a scalar from each element of this vector + Vec3T vecK = vecA; + vecK -= gr; + EXPECT_EQ(vecK(0), ValueT(vecA(0) - gr)); + EXPECT_EQ(vecK(1), ValueT(vecA(1) - gr)); + EXPECT_EQ(vecK(2), ValueT(vecA(2) - gr)); + + // Subtract each element of the given vector from the corresponding element of this vector + Vec3T vecL = vecA; + vecL -= vecF; + EXPECT_EQ(vecL(0), ValueT(vecA(0) - vecF(0))); + EXPECT_EQ(vecL(1), ValueT(vecA(1) - vecF(1))); + EXPECT_EQ(vecL(2), ValueT(vecA(2) - vecF(2))); + } +} + +TEST_F(TestMath, testMemberOperators) +{ + using namespace openvdb; + + testMemberOperatorsImpl(); + testMemberOperatorsImpl(); + testMemberOperatorsImpl(); +} + +template +void testFreeFunctionOperatorsImpl() +{ + using namespace openvdb; + using Vec3T = math::Vec3; + + { + // Vec3T vecA(3.14,2.18,ValueT(-299792458.f)); + Vec3T vecA(1,2,3); + Vec3T vecB(3,4,5); + const ValueT gr = ValueT(1.6180339887); + + /// Equality operator, does exact floating point comparisons == + bool eqRes = vecA == vecB; + EXPECT_FALSE(eqRes); + + /// Inequality operator, does exact floating point comparisons != + bool ineqRes = vecA != vecB; + EXPECT_TRUE(ineqRes); + + /// Multiply each element of the given vector by @a scalar and return the result. scalar * vec + Vec3T scalarMultiplyA = gr * vecA; + EXPECT_EQ(scalarMultiplyA(0), ValueT(vecA(0) * gr)); + EXPECT_EQ(scalarMultiplyA(1), ValueT(vecA(1) * gr)); + EXPECT_EQ(scalarMultiplyA(2), ValueT(vecA(2) * gr)); + + /// Multiply each element of the given vector by @a scalar and return the result. vec * scalar + Vec3T scalarMultiplyB = vecA * gr; + EXPECT_EQ(scalarMultiplyB(0), ValueT(vecA(0) * gr)); + EXPECT_EQ(scalarMultiplyB(1), ValueT(vecA(1) * gr)); + EXPECT_EQ(scalarMultiplyB(2), ValueT(vecA(2) * gr)); + + /// Multiply corresponding elements of @a v0 and @a v1 and return the result. vec0 * vec1 + Vec3T multiplyRes = vecA * vecB; + EXPECT_EQ(multiplyRes, Vec3T(3, 8, 15)); + + /// Divide @a scalar by each element of the given vector and return the result. a / vec + Vec3T scalarDivA = gr / vecA; + EXPECT_EQ(scalarDivA(0), ValueT(gr / vecA(0))); + EXPECT_EQ(scalarDivA(1), ValueT(gr / vecA(1))); + EXPECT_EQ(scalarDivA(2), ValueT(gr / vecA(2))); + + /// Divide each element of the given vector by @a scalar and return the result. vec / scalar + Vec3T scalarDivB = vecA / gr; + EXPECT_EQ(scalarDivB(0), ValueT(vecA(0) / gr)); + EXPECT_EQ(scalarDivB(1), ValueT(vecA(1) / gr)); + EXPECT_EQ(scalarDivB(2), ValueT(vecA(2) / gr)); + + /// Divide corresponding elements of @a v0 and @a v1 and return the result. vec0 / vec1 + Vec3T divRes = vecA / vecB; + EXPECT_EQ(divRes(0), ValueT(ValueT(vecA(0)) / ValueT(vecB(0)))); + EXPECT_EQ(divRes(1), ValueT(ValueT(vecA(1)) / ValueT(vecB(1)))); + EXPECT_EQ(divRes(2), ValueT(ValueT(vecA(2)) / ValueT(vecB(2)))); + + /// Add corresponding elements of @a v0 and @a v1 and return the result. vec0 + vec1 + Vec3T addRes = vecA + vecB; + EXPECT_EQ(addRes, Vec3T(4, 6, 8)); + + /// Add @a scalar to each element of the given vector and return the result. a + vec + Vec3T addScalarRes = vecA + gr; + EXPECT_EQ(addScalarRes(0), ValueT(vecA(0) + gr)); + EXPECT_EQ(addScalarRes(1), ValueT(vecA(1) + gr)); + EXPECT_EQ(addScalarRes(2), ValueT(vecA(2) + gr)); + + /// Subtract corresponding elements of @a v0 and @a v1 and return the result. vec0 - vec1 + Vec3T subtractRes = vecA - vecB; + EXPECT_EQ(subtractRes, Vec3T(-2, -2, -2)); + + /// Subtract @a scalar from each element of the given vector and return the result. vec0 - a + Vec3T subScalarRes = vecA - gr; + EXPECT_EQ(subScalarRes(0), ValueT(vecA(0) - gr)); + EXPECT_EQ(subScalarRes(1), ValueT(vecA(1) - gr)); + EXPECT_EQ(subScalarRes(2), ValueT(vecA(2) - gr)); + } +} + +TEST_F(TestMath, testFreeFunctionOperators) +{ + using namespace openvdb; + testFreeFunctionOperatorsImpl(); + +} + // This suite of tests obviously needs to be expanded! TEST_F(TestMath, testAll) @@ -23,6 +202,7 @@ TEST_F(TestMath, testAll) EXPECT_EQ(math::Sign( 3 ), 1); EXPECT_EQ(math::Sign(-1.0 ),-1); EXPECT_EQ(math::Sign( 0.0f), 0); + EXPECT_EQ(math::Sign(math::half(0.)), 0); } {// SignChange EXPECT_TRUE( math::SignChange( -1, 1)); From fe4248979d9bcd3b6eaab8c4a61475c2528bddf7 Mon Sep 17 00:00:00 2001 From: apradhana Date: Wed, 5 Mar 2025 10:34:31 -0800 Subject: [PATCH 2/4] Add things to Math.h and Vec3.h. Signed-off-by: apradhana --- openvdb/openvdb/math/Math.h | 13 ++++++++++++- openvdb/openvdb/math/Vec3.h | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/openvdb/openvdb/math/Math.h b/openvdb/openvdb/math/Math.h index 578ebc2c3b..f0a3376fce 100644 --- a/openvdb/openvdb/math/Math.h +++ b/openvdb/openvdb/math/Math.h @@ -74,6 +74,16 @@ template<> inline std::string zeroVal() { return ""; } /// Return the @c bool value that corresponds to zero. template<> inline constexpr bool zeroVal() { return false; } + +/// @note Extends the implementation of std::is_arithmetic to support math::half +template +struct is_arithmetic : std::is_arithmetic {}; +template<> +struct is_arithmetic : std::true_type {}; +// Helper variable template (equivalent to std::is_arithmetic_v) +template +inline constexpr bool is_arithmetic_v = is_arithmetic::value; + namespace math { /// @todo These won't be needed if we eliminate StringGrids. @@ -986,11 +996,12 @@ enum RotationOrder { ZXZ_ROTATION }; -template && std::is_arithmetic_v>> +template && openvdb::is_arithmetic_v>> struct promote { using type = typename std::common_type_t; }; + /// @brief Return the index [0,1,2] of the smallest value in a 3D vector. /// @note This methods assumes operator[] exists. /// @details The return value corresponds to the largest index of the of diff --git a/openvdb/openvdb/math/Vec3.h b/openvdb/openvdb/math/Vec3.h index 76759fbbbc..d9fb48a805 100644 --- a/openvdb/openvdb/math/Vec3.h +++ b/openvdb/openvdb/math/Vec3.h @@ -663,11 +663,13 @@ using Vec3i = Vec3; using Vec3ui = Vec3; using Vec3s = Vec3; using Vec3d = Vec3; +using Vec3h = Vec3; OPENVDB_IS_POD(Vec3i) OPENVDB_IS_POD(Vec3ui) OPENVDB_IS_POD(Vec3s) OPENVDB_IS_POD(Vec3d) +OPENVDB_IS_POD(Vec3h) } // namespace math } // namespace OPENVDB_VERSION_NAME From 665a528fea657c8bb8fe5520ee8986c15e71308c Mon Sep 17 00:00:00 2001 From: apradhana Date: Mon, 24 Mar 2025 09:45:38 -0700 Subject: [PATCH 3/4] Impose explicit conversion when creating vectors. Signed-off-by: apradhana --- openvdb/openvdb/unittest/TestMath.cc | 101 ++++++++++++++------------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/openvdb/openvdb/unittest/TestMath.cc b/openvdb/openvdb/unittest/TestMath.cc index a9565edc23..b32793aa5d 100644 --- a/openvdb/openvdb/unittest/TestMath.cc +++ b/openvdb/openvdb/unittest/TestMath.cc @@ -21,7 +21,7 @@ void testMemberOperatorsImpl() using Vec3T = math::Vec3; { - Vec3T vecA(3.14,2.18,ValueT(-299792458.f)); + Vec3T vecA(ValueT(3.14), ValueT(2.18), ValueT(-299792458.f)); // Alternative indexed the elements EXPECT_EQ(vecA(0), ValueT(3.14)); @@ -42,7 +42,7 @@ void testMemberOperatorsImpl() // Multiply each element of the vector by a scalar Vec3T vecD = vecA; - const ValueT gr = ValueT(1.6180339887); + const ValueT gr = ValueT(1.6180339887); // golden ratio vecD *= gr; EXPECT_EQ(vecD(0), ValueT(gr * vecA(0))); EXPECT_EQ(vecD(1), ValueT(gr * vecA(1))); @@ -50,7 +50,7 @@ void testMemberOperatorsImpl() // Multiply each element of the vector by the corresponding element Vec3T vecE = vecA; - Vec3T vecF(-2.5, 1.2, 3.14159); + Vec3T vecF(ValueT(-2.5), ValueT(1.2), ValueT(3.14159)); vecE *= vecF; EXPECT_EQ(vecE(0), ValueT(vecA(0) * vecF(0))); EXPECT_EQ(vecE(1), ValueT(vecA(1) * vecF(1))); @@ -109,87 +109,88 @@ TEST_F(TestMath, testMemberOperators) testMemberOperatorsImpl(); } + template -void testFreeFunctionOperatorsImpl() +void testFreeFunctionsOperatorsImpl() { using namespace openvdb; using Vec3T = math::Vec3; { - // Vec3T vecA(3.14,2.18,ValueT(-299792458.f)); - Vec3T vecA(1,2,3); - Vec3T vecB(3,4,5); - const ValueT gr = ValueT(1.6180339887); + Vec3T vecA(ValueT(1),ValueT(2),ValueT(3)); + Vec3T vecB(ValueT(3),ValueT(4),ValueT(5)); + const ValueT gr = ValueT(1.6180339887); // golden ratio - /// Equality operator, does exact floating point comparisons == + /// Check equality operator, does exact floating point comparisons == bool eqRes = vecA == vecB; EXPECT_FALSE(eqRes); - /// Inequality operator, does exact floating point comparisons != + /// Check inequality operator, does exact floating point comparisons != bool ineqRes = vecA != vecB; EXPECT_TRUE(ineqRes); - /// Multiply each element of the given vector by @a scalar and return the result. scalar * vec - Vec3T scalarMultiplyA = gr * vecA; - EXPECT_EQ(scalarMultiplyA(0), ValueT(vecA(0) * gr)); - EXPECT_EQ(scalarMultiplyA(1), ValueT(vecA(1) * gr)); - EXPECT_EQ(scalarMultiplyA(2), ValueT(vecA(2) * gr)); - - /// Multiply each element of the given vector by @a scalar and return the result. vec * scalar - Vec3T scalarMultiplyB = vecA * gr; - EXPECT_EQ(scalarMultiplyB(0), ValueT(vecA(0) * gr)); - EXPECT_EQ(scalarMultiplyB(1), ValueT(vecA(1) * gr)); - EXPECT_EQ(scalarMultiplyB(2), ValueT(vecA(2) * gr)); - - /// Multiply corresponding elements of @a v0 and @a v1 and return the result. vec0 * vec1 - Vec3T multiplyRes = vecA * vecB; - EXPECT_EQ(multiplyRes, Vec3T(3, 8, 15)); - - /// Divide @a scalar by each element of the given vector and return the result. a / vec - Vec3T scalarDivA = gr / vecA; - EXPECT_EQ(scalarDivA(0), ValueT(gr / vecA(0))); - EXPECT_EQ(scalarDivA(1), ValueT(gr / vecA(1))); - EXPECT_EQ(scalarDivA(2), ValueT(gr / vecA(2))); - - /// Divide each element of the given vector by @a scalar and return the result. vec / scalar + /// Check multiplication: scalar * vec + Vec3T sclrMultA = gr * vecA; + EXPECT_EQ(sclrMultA(0), ValueT(vecA(0) * gr)); + EXPECT_EQ(sclrMultA(1), ValueT(vecA(1) * gr)); + EXPECT_EQ(sclrMultA(2), ValueT(vecA(2) * gr)); + + /// Check multiplication: vec * scalar + Vec3T sclrMultB = vecA * gr; + EXPECT_EQ(sclrMultB(0), ValueT(vecA(0) * gr)); + EXPECT_EQ(sclrMultB(1), ValueT(vecA(1) * gr)); + EXPECT_EQ(sclrMultB(2), ValueT(vecA(2) * gr)); + + /// Check multiplication vec0 * vec1 + Vec3T multRes = vecA * vecB; + EXPECT_EQ(multRes, Vec3T(ValueT(3), ValueT(8), ValueT(15))); + + /// Check: scalar / vec + Vec3T sclrDivA = gr / vecA; + EXPECT_EQ(sclrDivA(0), ValueT(gr / vecA(0))); + EXPECT_EQ(sclrDivA(1), ValueT(gr / vecA(1))); + EXPECT_EQ(sclrDivA(2), ValueT(gr / vecA(2))); + + /// Check: vec / scalar Vec3T scalarDivB = vecA / gr; EXPECT_EQ(scalarDivB(0), ValueT(vecA(0) / gr)); EXPECT_EQ(scalarDivB(1), ValueT(vecA(1) / gr)); EXPECT_EQ(scalarDivB(2), ValueT(vecA(2) / gr)); - /// Divide corresponding elements of @a v0 and @a v1 and return the result. vec0 / vec1 + /// Check element-wise div: vec0 / vec1 Vec3T divRes = vecA / vecB; EXPECT_EQ(divRes(0), ValueT(ValueT(vecA(0)) / ValueT(vecB(0)))); EXPECT_EQ(divRes(1), ValueT(ValueT(vecA(1)) / ValueT(vecB(1)))); EXPECT_EQ(divRes(2), ValueT(ValueT(vecA(2)) / ValueT(vecB(2)))); - /// Add corresponding elements of @a v0 and @a v1 and return the result. vec0 + vec1 + /// Check addition: vec0 + vec1 Vec3T addRes = vecA + vecB; - EXPECT_EQ(addRes, Vec3T(4, 6, 8)); + EXPECT_EQ(addRes, Vec3T(ValueT(4), ValueT(6), ValueT(8))); - /// Add @a scalar to each element of the given vector and return the result. a + vec - Vec3T addScalarRes = vecA + gr; - EXPECT_EQ(addScalarRes(0), ValueT(vecA(0) + gr)); - EXPECT_EQ(addScalarRes(1), ValueT(vecA(1) + gr)); - EXPECT_EQ(addScalarRes(2), ValueT(vecA(2) + gr)); + /// Check scalar addition: a + vec + Vec3T addSclrRes = vecA + gr; + EXPECT_EQ(addSclrRes(0), ValueT(vecA(0) + gr)); + EXPECT_EQ(addSclrRes(1), ValueT(vecA(1) + gr)); + EXPECT_EQ(addSclrRes(2), ValueT(vecA(2) + gr)); - /// Subtract corresponding elements of @a v0 and @a v1 and return the result. vec0 - vec1 + /// Check element-wise subtraction: vec0 - vec1 Vec3T subtractRes = vecA - vecB; - EXPECT_EQ(subtractRes, Vec3T(-2, -2, -2)); + EXPECT_EQ(subtractRes, Vec3T(ValueT(-2), ValueT(-2), ValueT(-2))); - /// Subtract @a scalar from each element of the given vector and return the result. vec0 - a - Vec3T subScalarRes = vecA - gr; - EXPECT_EQ(subScalarRes(0), ValueT(vecA(0) - gr)); - EXPECT_EQ(subScalarRes(1), ValueT(vecA(1) - gr)); - EXPECT_EQ(subScalarRes(2), ValueT(vecA(2) - gr)); + /// Check scalar subtraction: vec0 - a + Vec3T subSclrRes = vecA - gr; + EXPECT_EQ(subSclrRes(0), ValueT(vecA(0) - gr)); + EXPECT_EQ(subSclrRes(1), ValueT(vecA(1) - gr)); + EXPECT_EQ(subSclrRes(2), ValueT(vecA(2) - gr)); } } TEST_F(TestMath, testFreeFunctionOperators) { using namespace openvdb; - testFreeFunctionOperatorsImpl(); - + testFreeFunctionsOperatorsImpl(); + testFreeFunctionsOperatorsImpl(); + testFreeFunctionsOperatorsImpl(); } From 7fc95f5afff19ba2043300d7208e4c64e12a6b28 Mon Sep 17 00:00:00 2001 From: apradhana Date: Tue, 25 Mar 2025 17:47:59 -0700 Subject: [PATCH 4/4] Explicitly using float. Signed-off-by: apradhana --- openvdb/openvdb/unittest/TestMath.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openvdb/openvdb/unittest/TestMath.cc b/openvdb/openvdb/unittest/TestMath.cc index b32793aa5d..a64c16ccc3 100644 --- a/openvdb/openvdb/unittest/TestMath.cc +++ b/openvdb/openvdb/unittest/TestMath.cc @@ -21,11 +21,11 @@ void testMemberOperatorsImpl() using Vec3T = math::Vec3; { - Vec3T vecA(ValueT(3.14), ValueT(2.18), ValueT(-299792458.f)); + Vec3T vecA(ValueT(3.14f), ValueT(2.18f), ValueT(-299792458.f)); // Alternative indexed the elements - EXPECT_EQ(vecA(0), ValueT(3.14)); - EXPECT_EQ(vecA(1), ValueT(2.18)); + EXPECT_EQ(vecA(0), ValueT(3.14f)); + EXPECT_EQ(vecA(1), ValueT(2.18f)); EXPECT_EQ(vecA(2), ValueT(-299792458.f)); // Assignment operator @@ -42,7 +42,7 @@ void testMemberOperatorsImpl() // Multiply each element of the vector by a scalar Vec3T vecD = vecA; - const ValueT gr = ValueT(1.6180339887); // golden ratio + const ValueT gr = ValueT(1.618034f); // golden ratio vecD *= gr; EXPECT_EQ(vecD(0), ValueT(gr * vecA(0))); EXPECT_EQ(vecD(1), ValueT(gr * vecA(1))); @@ -50,7 +50,7 @@ void testMemberOperatorsImpl() // Multiply each element of the vector by the corresponding element Vec3T vecE = vecA; - Vec3T vecF(ValueT(-2.5), ValueT(1.2), ValueT(3.14159)); + Vec3T vecF(ValueT(-2.5f), ValueT(1.2f), ValueT(3.14159f)); vecE *= vecF; EXPECT_EQ(vecE(0), ValueT(vecA(0) * vecF(0))); EXPECT_EQ(vecE(1), ValueT(vecA(1) * vecF(1))); @@ -119,7 +119,7 @@ void testFreeFunctionsOperatorsImpl() { Vec3T vecA(ValueT(1),ValueT(2),ValueT(3)); Vec3T vecB(ValueT(3),ValueT(4),ValueT(5)); - const ValueT gr = ValueT(1.6180339887); // golden ratio + const ValueT gr = ValueT(1.618034f); // golden ratio /// Check equality operator, does exact floating point comparisons == bool eqRes = vecA == vecB;