Browse Source

Math: test iterative normalization of Complex/Quaternion transformations.

If the values are renormalized after every step, it shouldn't happen
that the value is denormalized even after calling `normalized()`.

The test fails for DualQuaternion with large values, as expected. Will
be fixed in the next commit.
pull/175/merge
Vladimír Vondruš 10 years ago
parent
commit
aef580ec62
  1. 21
      src/Magnum/Math/Test/ComplexTest.cpp
  2. 31
      src/Magnum/Math/Test/DualComplexTest.cpp
  3. 32
      src/Magnum/Math/Test/DualQuaternionTest.cpp
  4. 22
      src/Magnum/Math/Test/QuaternionTest.cpp

21
src/Magnum/Math/Test/ComplexTest.cpp

@ -79,6 +79,7 @@ struct ComplexTest: Corrade::TestSuite::Tester {
void dotSelf(); void dotSelf();
void length(); void length();
void normalized(); void normalized();
template<class T> void normalizedIterative();
void conjugated(); void conjugated();
void inverted(); void inverted();
@ -115,9 +116,13 @@ ComplexTest::ComplexTest() {
&ComplexTest::dot, &ComplexTest::dot,
&ComplexTest::dotSelf, &ComplexTest::dotSelf,
&ComplexTest::length, &ComplexTest::length,
&ComplexTest::normalized, &ComplexTest::normalized});
&ComplexTest::conjugated, addRepeatedTests<ComplexTest>({
&ComplexTest::normalizedIterative<Float>,
&ComplexTest::normalizedIterative<Double>}, 1000);
addTests({&ComplexTest::conjugated,
&ComplexTest::inverted, &ComplexTest::inverted,
&ComplexTest::invertedNormalized, &ComplexTest::invertedNormalized,
@ -312,6 +317,18 @@ void ComplexTest::normalized() {
CORRADE_COMPARE(a.normalized().length(), 1.0f); CORRADE_COMPARE(a.normalized().length(), 1.0f);
} }
template<class T> void ComplexTest::normalizedIterative() {
setTestCaseName(std::string{"normalizedIterative<"} + TypeTraits<T>::name() + ">");
auto a = Math::Complex<T>::rotation(Math::Deg<T>{T(36.7)});
for(std::size_t i = 0; i != testCaseRepeatId(); ++i) {
a = Math::Complex<T>::rotation(Math::Deg<T>{T(87.1)})*a;
a = a.normalized();
}
CORRADE_VERIFY(a.isNormalized());
}
void ComplexTest::conjugated() { void ComplexTest::conjugated() {
CORRADE_COMPARE(Complex(-3.0f, 4.5f).conjugated(), Complex(-3.0f, -4.5f)); CORRADE_COMPARE(Complex(-3.0f, 4.5f).conjugated(), Complex(-3.0f, -4.5f));
} }

31
src/Magnum/Math/Test/DualComplexTest.cpp

@ -75,6 +75,7 @@ struct DualComplexTest: Corrade::TestSuite::Tester {
void lengthSquared(); void lengthSquared();
void length(); void length();
void normalized(); void normalized();
template<class T> void normalizedIterative();
void complexConjugated(); void complexConjugated();
void dualConjugated(); void dualConjugated();
@ -119,9 +120,13 @@ DualComplexTest::DualComplexTest() {
&DualComplexTest::lengthSquared, &DualComplexTest::lengthSquared,
&DualComplexTest::length, &DualComplexTest::length,
&DualComplexTest::normalized, &DualComplexTest::normalized});
&DualComplexTest::complexConjugated, addRepeatedTests<DualComplexTest>({
&DualComplexTest::normalizedIterative<Float>,
&DualComplexTest::normalizedIterative<Double>}, 1000);
addTests({&DualComplexTest::complexConjugated,
&DualComplexTest::dualConjugated, &DualComplexTest::dualConjugated,
&DualComplexTest::conjugated, &DualComplexTest::conjugated,
&DualComplexTest::inverted, &DualComplexTest::inverted,
@ -281,6 +286,28 @@ void DualComplexTest::normalized() {
CORRADE_COMPARE(a.normalized(), b); CORRADE_COMPARE(a.normalized(), b);
} }
namespace {
template<class> struct NormalizedIterativeData;
template<> struct NormalizedIterativeData<Float> {
static Math::Vector2<Float> translation() { return {10000.0f, -50.0f}; }
};
template<> struct NormalizedIterativeData<Double> {
static Math::Vector2<Double> translation() { return {10000000.0, -500.0}; }
};
}
template<class T> void DualComplexTest::normalizedIterative() {
setTestCaseName(std::string{"normalizedIterative<"} + TypeTraits<T>::name() + ">");
auto a = Math::DualComplex<T>::rotation(Math::Deg<T>{T(36.7)})*Math::DualComplex<T>::translation(NormalizedIterativeData<T>::translation());
for(std::size_t i = 0; i != testCaseRepeatId(); ++i) {
a = Math::DualComplex<T>::rotation(Math::Deg<T>{T(87.1)})*a;
a = a.normalized();
}
CORRADE_VERIFY(a.isNormalized());
}
void DualComplexTest::complexConjugated() { void DualComplexTest::complexConjugated() {
DualComplex a({-1.0f, 2.5f}, {3.0f, -7.5f}); DualComplex a({-1.0f, 2.5f}, {3.0f, -7.5f});
DualComplex b({-1.0f, -2.5f}, {3.0f, 7.5f}); DualComplex b({-1.0f, -2.5f}, {3.0f, 7.5f});

32
src/Magnum/Math/Test/DualQuaternionTest.cpp

@ -76,6 +76,7 @@ struct DualQuaternionTest: Corrade::TestSuite::Tester {
void lengthSquared(); void lengthSquared();
void length(); void length();
void normalized(); void normalized();
template<class T> void normalizedIterative();
void quaternionConjugated(); void quaternionConjugated();
void dualConjugated(); void dualConjugated();
@ -124,9 +125,13 @@ DualQuaternionTest::DualQuaternionTest() {
&DualQuaternionTest::lengthSquared, &DualQuaternionTest::lengthSquared,
&DualQuaternionTest::length, &DualQuaternionTest::length,
&DualQuaternionTest::normalized, &DualQuaternionTest::normalized});
&DualQuaternionTest::quaternionConjugated, addRepeatedTests<DualQuaternionTest>({
&DualQuaternionTest::normalizedIterative<Float>,
&DualQuaternionTest::normalizedIterative<Double>}, 1000);
addTests({&DualQuaternionTest::quaternionConjugated,
&DualQuaternionTest::dualConjugated, &DualQuaternionTest::dualConjugated,
&DualQuaternionTest::conjugated, &DualQuaternionTest::conjugated,
&DualQuaternionTest::inverted, &DualQuaternionTest::inverted,
@ -304,6 +309,29 @@ void DualQuaternionTest::normalized() {
CORRADE_COMPARE(a.normalized(), b); CORRADE_COMPARE(a.normalized(), b);
} }
namespace {
template<class> struct NormalizedIterativeData;
template<> struct NormalizedIterativeData<Float> {
static Math::Vector3<Float> translation() { return {10000.0f, -50.0f, 20000.0f}; }
};
template<> struct NormalizedIterativeData<Double> {
static Math::Vector3<Double> translation() { return {10000000000000.0, -500.0, 20000000000000.0}; }
};
}
template<class T> void DualQuaternionTest::normalizedIterative() {
setTestCaseName(std::string{"normalizedIterative<"} + TypeTraits<T>::name() + ">");
const auto axis = Math::Vector3<T>{T(0.5), T(7.9), T(0.1)}.normalized();
auto a = Math::DualQuaternion<T>::rotation(Math::Deg<T>{T(36.7)}, Math::Vector3<T>{T(0.25), T(7.3), T(-1.1)}.normalized())*Math::DualQuaternion<T>::translation(NormalizedIterativeData<T>::translation());
for(std::size_t i = 0; i != testCaseRepeatId(); ++i) {
a = Math::DualQuaternion<T>::rotation(Math::Deg<T>{T(87.1)}, axis)*a;
a = a.normalized();
}
CORRADE_VERIFY(a.isNormalized());
}
void DualQuaternionTest::quaternionConjugated() { void DualQuaternionTest::quaternionConjugated() {
DualQuaternion a({{ 1.0f, 2.0f, 3.0f}, -4.0f}, {{ 0.5f, -3.1f, 3.3f}, 2.0f}); DualQuaternion a({{ 1.0f, 2.0f, 3.0f}, -4.0f}, {{ 0.5f, -3.1f, 3.3f}, 2.0f});
DualQuaternion b({{-1.0f, -2.0f, -3.0f}, -4.0f}, {{-0.5f, 3.1f, -3.3f}, 2.0f}); DualQuaternion b({{-1.0f, -2.0f, -3.0f}, -4.0f}, {{-0.5f, 3.1f, -3.3f}, 2.0f});

22
src/Magnum/Math/Test/QuaternionTest.cpp

@ -79,6 +79,7 @@ struct QuaternionTest: Corrade::TestSuite::Tester {
void dotSelf(); void dotSelf();
void length(); void length();
void normalized(); void normalized();
template<class T> void normalizedIterative();
void conjugated(); void conjugated();
void inverted(); void inverted();
@ -126,9 +127,13 @@ QuaternionTest::QuaternionTest() {
&QuaternionTest::dot, &QuaternionTest::dot,
&QuaternionTest::dotSelf, &QuaternionTest::dotSelf,
&QuaternionTest::length, &QuaternionTest::length,
&QuaternionTest::normalized, &QuaternionTest::normalized});
&QuaternionTest::conjugated, addRepeatedTests<QuaternionTest>({
&QuaternionTest::normalizedIterative<Float>,
&QuaternionTest::normalizedIterative<Double>}, 1000);
addTests({&QuaternionTest::conjugated,
&QuaternionTest::inverted, &QuaternionTest::inverted,
&QuaternionTest::invertedNormalized, &QuaternionTest::invertedNormalized,
@ -308,6 +313,19 @@ void QuaternionTest::normalized() {
CORRADE_COMPARE(normalized, Quaternion({1.0f, 3.0f, -2.0f}, -4.0f)/std::sqrt(30.0f)); CORRADE_COMPARE(normalized, Quaternion({1.0f, 3.0f, -2.0f}, -4.0f)/std::sqrt(30.0f));
} }
template<class T> void QuaternionTest::normalizedIterative() {
setTestCaseName(std::string{"normalizedIterative<"} + TypeTraits<T>::name() + ">");
const auto axis = Math::Vector3<T>{T(0.5), T(7.9), T(0.1)}.normalized();
auto a = Math::Quaternion<T>::rotation(Math::Deg<T>{T(36.7)}, Math::Vector3<T>{T(0.25), T(7.3), T(-1.1)}.normalized());
for(std::size_t i = 0; i != testCaseRepeatId(); ++i) {
a = Math::Quaternion<T>::rotation(Math::Deg<T>{T(87.1)}, axis)*a;
a = a.normalized();
}
CORRADE_VERIFY(a.isNormalized());
}
void QuaternionTest::conjugated() { void QuaternionTest::conjugated() {
CORRADE_COMPARE(Quaternion({ 1.0f, 3.0f, -2.0f}, -4.0f).conjugated(), CORRADE_COMPARE(Quaternion({ 1.0f, 3.0f, -2.0f}, -4.0f).conjugated(),
Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f)); Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f));

Loading…
Cancel
Save