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 length();
void normalized();
template<class T> void normalizedIterative();
void conjugated();
void inverted();
@ -115,9 +116,13 @@ ComplexTest::ComplexTest() {
&ComplexTest::dot,
&ComplexTest::dotSelf,
&ComplexTest::length,
&ComplexTest::normalized,
&ComplexTest::normalized});
&ComplexTest::conjugated,
addRepeatedTests<ComplexTest>({
&ComplexTest::normalizedIterative<Float>,
&ComplexTest::normalizedIterative<Double>}, 1000);
addTests({&ComplexTest::conjugated,
&ComplexTest::inverted,
&ComplexTest::invertedNormalized,
@ -312,6 +317,18 @@ void ComplexTest::normalized() {
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() {
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 length();
void normalized();
template<class T> void normalizedIterative();
void complexConjugated();
void dualConjugated();
@ -119,9 +120,13 @@ DualComplexTest::DualComplexTest() {
&DualComplexTest::lengthSquared,
&DualComplexTest::length,
&DualComplexTest::normalized,
&DualComplexTest::normalized});
&DualComplexTest::complexConjugated,
addRepeatedTests<DualComplexTest>({
&DualComplexTest::normalizedIterative<Float>,
&DualComplexTest::normalizedIterative<Double>}, 1000);
addTests({&DualComplexTest::complexConjugated,
&DualComplexTest::dualConjugated,
&DualComplexTest::conjugated,
&DualComplexTest::inverted,
@ -281,6 +286,28 @@ void DualComplexTest::normalized() {
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() {
DualComplex a({-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 length();
void normalized();
template<class T> void normalizedIterative();
void quaternionConjugated();
void dualConjugated();
@ -124,9 +125,13 @@ DualQuaternionTest::DualQuaternionTest() {
&DualQuaternionTest::lengthSquared,
&DualQuaternionTest::length,
&DualQuaternionTest::normalized,
&DualQuaternionTest::normalized});
&DualQuaternionTest::quaternionConjugated,
addRepeatedTests<DualQuaternionTest>({
&DualQuaternionTest::normalizedIterative<Float>,
&DualQuaternionTest::normalizedIterative<Double>}, 1000);
addTests({&DualQuaternionTest::quaternionConjugated,
&DualQuaternionTest::dualConjugated,
&DualQuaternionTest::conjugated,
&DualQuaternionTest::inverted,
@ -304,6 +309,29 @@ void DualQuaternionTest::normalized() {
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() {
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});

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

@ -79,6 +79,7 @@ struct QuaternionTest: Corrade::TestSuite::Tester {
void dotSelf();
void length();
void normalized();
template<class T> void normalizedIterative();
void conjugated();
void inverted();
@ -126,9 +127,13 @@ QuaternionTest::QuaternionTest() {
&QuaternionTest::dot,
&QuaternionTest::dotSelf,
&QuaternionTest::length,
&QuaternionTest::normalized,
&QuaternionTest::normalized});
&QuaternionTest::conjugated,
addRepeatedTests<QuaternionTest>({
&QuaternionTest::normalizedIterative<Float>,
&QuaternionTest::normalizedIterative<Double>}, 1000);
addTests({&QuaternionTest::conjugated,
&QuaternionTest::inverted,
&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));
}
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() {
CORRADE_COMPARE(Quaternion({ 1.0f, 3.0f, -2.0f}, -4.0f).conjugated(),
Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f));

Loading…
Cancel
Save