Browse Source

Math: added convenience functions {Complex,DualComplex}::isNormalized().

pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
1790f37295
  1. 29
      src/Math/Complex.h
  2. 15
      src/Math/DualComplex.h
  3. 9
      src/Math/Test/ComplexTest.cpp
  4. 9
      src/Math/Test/DualComplexTest.cpp

29
src/Math/Complex.h

@ -75,10 +75,10 @@ template<class T> class Complex {
* Expects that both complex numbers are normalized. @f[ * Expects that both complex numbers are normalized. @f[
* \theta = acos \left( \frac{Re(c_0 \cdot c_1))}{|c_0| |c_1|} \right) = acos (a_0 a_1 + b_0 b_1) * \theta = acos \left( \frac{Re(c_0 \cdot c_1))}{|c_0| |c_1|} \right) = acos (a_0 a_1 + b_0 b_1)
* @f] * @f]
* @see Quaternion::angle(), Vector::angle() * @see isNormalized(), Quaternion::angle(), Vector::angle()
*/ */
inline static Rad<T> angle(const Complex<T>& normalizedA, const Complex<T>& normalizedB) { inline static Rad<T> angle(const Complex<T>& normalizedA, const Complex<T>& normalizedB) {
CORRADE_ASSERT(TypeTraits<T>::equals(normalizedA.dot(), T(1)) && TypeTraits<T>::equals(normalizedB.dot(), T(1)), CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(),
"Math::Complex::angle(): complex numbers must be normalized", Rad<T>(std::numeric_limits<T>::quiet_NaN())); "Math::Complex::angle(): complex numbers must be normalized", Rad<T>(std::numeric_limits<T>::quiet_NaN()));
return Rad<T>(std::acos(normalizedA._real*normalizedB._real + normalizedA._imaginary*normalizedB._imaginary)); return Rad<T>(std::acos(normalizedA._real*normalizedB._real + normalizedA._imaginary*normalizedB._imaginary));
} }
@ -147,6 +147,18 @@ template<class T> class Complex {
return !operator==(other); return !operator==(other);
} }
/**
* @brief Whether the complex number is normalized
*
* Complex number is normalized if it has unit length: @f[
* |c|^2 = |c| = 1
* @f]
* @see dot(), normalized()
*/
inline bool isNormalized() const {
return TypeTraits<T>::equals(dot(), T(1));
}
/** @brief Real part */ /** @brief Real part */
inline constexpr T real() const { return _real; } inline constexpr T real() const { return _real; }
@ -311,7 +323,7 @@ template<class T> class Complex {
* with other values, because it doesn't compute the square root. @f[ * with other values, because it doesn't compute the square root. @f[
* c \cdot c = a^2 + b^2 * c \cdot c = a^2 + b^2
* @f] * @f]
* @see dot(const Complex&, const Complex&) * @see dot(const Complex&, const Complex&), isNormalized()
*/ */
inline T dot() const { inline T dot() const {
return dot(*this, *this); return dot(*this, *this);
@ -324,12 +336,17 @@ template<class T> class Complex {
* values. @f[ * values. @f[
* |c| = \sqrt{c \cdot c} * |c| = \sqrt{c \cdot c}
* @f] * @f]
* @see isNormalized()
*/ */
inline T length() const { inline T length() const {
return std::hypot(_real, _imaginary); return std::hypot(_real, _imaginary);
} }
/** @brief Normalized complex number (of unit length) */ /**
* @brief Normalized complex number (of unit length)
*
* @see isNormalized()
*/
inline Complex<T> normalized() const { inline Complex<T> normalized() const {
return (*this)/length(); return (*this)/length();
} }
@ -364,10 +381,10 @@ template<class T> class Complex {
* normalized. @f[ * normalized. @f[
* c^{-1} = \frac{c^*}{c \cdot c} = c^* * c^{-1} = \frac{c^*}{c \cdot c} = c^*
* @f] * @f]
* @see inverted() * @see isNormalized(), inverted()
*/ */
inline Complex<T> invertedNormalized() const { inline Complex<T> invertedNormalized() const {
CORRADE_ASSERT(TypeTraits<T>::equals(dot(), T(1)), CORRADE_ASSERT(isNormalized(),
"Math::Complex::invertedNormalized(): complex number must be normalized", "Math::Complex::invertedNormalized(): complex number must be normalized",
Complex<T>(std::numeric_limits<T>::quiet_NaN(), {})); Complex<T>(std::numeric_limits<T>::quiet_NaN(), {}));
return conjugated(); return conjugated();

15
src/Math/DualComplex.h

@ -126,6 +126,18 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
inline constexpr explicit DualComplex(const Vector2<T>& vector): Dual<Complex<T>>({}, Complex<T>(vector)) {} inline constexpr explicit DualComplex(const Vector2<T>& vector): Dual<Complex<T>>({}, Complex<T>(vector)) {}
#endif #endif
/**
* @brief Whether the dual complex number is normalized
*
* Dual complex number is normalized if its real part has unit length: @f[
* |c_0|^2 = |c_0| = 1
* @f]
* @see Complex::dot(), normalized()
*/
inline bool isNormalized() const {
return TypeTraits<T>::equals(this->real().dot(), T(1));
}
/** /**
* @brief Rotation angle of dual complex number * @brief Rotation angle of dual complex number
* *
@ -240,6 +252,7 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* @f[ * @f[
* c' = \frac{c_0}{|c_0|} * c' = \frac{c_0}{|c_0|}
* @f] * @f]
* @see isNormalized()
* @todo can this be done similarly to dual quaternions? * @todo can this be done similarly to dual quaternions?
*/ */
inline DualComplex<T> normalized() const { inline DualComplex<T> normalized() const {
@ -265,7 +278,7 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* Expects that the complex number is normalized. @f[ * Expects that the complex number is normalized. @f[
* \hat c^{-1} = c_0^{-1} - \epsilon c_\epsilon = c_0^* - \epsilon c_\epsilon * \hat c^{-1} = c_0^{-1} - \epsilon c_\epsilon = c_0^* - \epsilon c_\epsilon
* @f] * @f]
* @see inverted() * @see isNormalized(), inverted()
* @todo can this be done similarly to dual quaternions? * @todo can this be done similarly to dual quaternions?
*/ */
inline DualComplex<T> invertedNormalized() const { inline DualComplex<T> invertedNormalized() const {

9
src/Math/Test/ComplexTest.cpp

@ -37,7 +37,9 @@ class ComplexTest: public Corrade::TestSuite::Tester {
void construct(); void construct();
void constructDefault(); void constructDefault();
void constructFromVector(); void constructFromVector();
void compare(); void compare();
void isNormalized();
void constExpressions(); void constExpressions();
@ -67,7 +69,9 @@ ComplexTest::ComplexTest() {
addTests({&ComplexTest::construct, addTests({&ComplexTest::construct,
&ComplexTest::constructDefault, &ComplexTest::constructDefault,
&ComplexTest::constructFromVector, &ComplexTest::constructFromVector,
&ComplexTest::compare, &ComplexTest::compare,
&ComplexTest::isNormalized,
&ComplexTest::constExpressions, &ComplexTest::constExpressions,
@ -126,6 +130,11 @@ void ComplexTest::compare() {
CORRADE_VERIFY(Complex(1.0f+TypeTraits<Float>::epsilon()*2, 3.7f) != Complex(1.0f, 3.7f)); CORRADE_VERIFY(Complex(1.0f+TypeTraits<Float>::epsilon()*2, 3.7f) != Complex(1.0f, 3.7f));
} }
void ComplexTest::isNormalized() {
CORRADE_VERIFY(!Complex(2.5f, -3.7f).isNormalized());
CORRADE_VERIFY(Complex::rotation(Deg(23.0f)).isNormalized());
}
void ComplexTest::constExpressions() { void ComplexTest::constExpressions() {
/* Default constructor */ /* Default constructor */
constexpr Complex a; constexpr Complex a;

9
src/Math/Test/DualComplexTest.cpp

@ -38,6 +38,8 @@ class DualComplexTest: public Corrade::TestSuite::Tester {
void constructDefault(); void constructDefault();
void constructFromVector(); void constructFromVector();
void isNormalized();
void constExpressions(); void constExpressions();
void multiply(); void multiply();
@ -74,6 +76,8 @@ DualComplexTest::DualComplexTest() {
&DualComplexTest::constructDefault, &DualComplexTest::constructDefault,
&DualComplexTest::constructFromVector, &DualComplexTest::constructFromVector,
&DualComplexTest::isNormalized,
&DualComplexTest::constExpressions, &DualComplexTest::constExpressions,
&DualComplexTest::multiply, &DualComplexTest::multiply,
@ -112,6 +116,11 @@ void DualComplexTest::constructFromVector() {
CORRADE_COMPARE(DualComplex(Vector2(1.5f, -3.0f)), DualComplex({1.0f, 0.0f}, {1.5f, -3.0f})); CORRADE_COMPARE(DualComplex(Vector2(1.5f, -3.0f)), DualComplex({1.0f, 0.0f}, {1.5f, -3.0f}));
} }
void DualComplexTest::isNormalized() {
CORRADE_VERIFY(!DualComplex({2.0f, 1.0f}, {}).isNormalized());
CORRADE_VERIFY((DualComplex::rotation(Deg(23.0f))*DualComplex::translation({6.0f, 3.0f})).isNormalized());
}
void DualComplexTest::constExpressions() { void DualComplexTest::constExpressions() {
/* Default constructor */ /* Default constructor */
constexpr DualComplex a; constexpr DualComplex a;

Loading…
Cancel
Save