Browse Source

Math: initial complex number implementation.

pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
687bd37b81
  1. 1
      src/CMakeLists.txt
  2. 1
      src/Math/CMakeLists.txt
  3. 27
      src/Math/Complex.cpp
  4. 218
      src/Math/Complex.h
  5. 1
      src/Math/Test/CMakeLists.txt
  6. 129
      src/Math/Test/ComplexTest.cpp

1
src/CMakeLists.txt

@ -98,6 +98,7 @@ add_library(MagnumObjects OBJECT ${Magnum_SRCS})
# Files shared between main library and math unit test library
set(MagnumMath_SRCS
Math/Complex.cpp
Math/DualQuaternion.cpp
Math/Functions.cpp
Math/Quaternion.cpp

1
src/Math/CMakeLists.txt

@ -1,5 +1,6 @@
set(MagnumMath_HEADERS
BoolVector.h
Complex.h
Constants.h
Dual.h
DualQuaternion.h

27
src/Math/Complex.cpp

@ -0,0 +1,27 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include "Complex.h"
namespace Magnum { namespace Math {
#ifndef DOXYGEN_GENERATING_OUTPUT
template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Complex<float>&);
#ifndef MAGNUM_TARGET_GLES
template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Complex<double>&);
#endif
#endif
}}

218
src/Math/Complex.h

@ -0,0 +1,218 @@
#ifndef Magnum_Math_Complex_h
#define Magnum_Math_Complex_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
/** @file
* @brief Class Magnum::Math::Complex
*/
#include <Utility/Debug.h>
#include "Math/MathTypeTraits.h"
#include "magnumVisibility.h"
namespace Magnum { namespace Math {
/**
@brief %Complex number
@tparam T Data type
Represents 2D rotation.
*/
template<class T> class Complex {
public:
typedef T Type; /**< @brief Underlying data type */
/**
* @brief Default constructor
*
* @f[
* c = 0 + i0
* @f]
*/
inline constexpr /*implicit*/ Complex(): _real(T(0)), _imaginary(T(0)) {}
/**
* @brief Construct complex from real and imaginary part
*
* @f[
* c = a + ib
* @f]
*/
inline constexpr /*implicit*/ Complex(T real, T imaginary = T(0)): _real(real), _imaginary(imaginary) {}
/** @brief Equality comparison */
inline bool operator==(const Complex<T>& other) const {
return MathTypeTraits<T>::equals(_real, other._real) &&
MathTypeTraits<T>::equals(_imaginary, other._imaginary);
}
/** @brief Non-equality comparison */
inline bool operator!=(const Complex<T>& other) const {
return !operator==(other);
}
/** @brief Real part */
inline constexpr T real() const { return _real; }
/** @brief Imaginary part */
inline constexpr T imaginary() const { return _imaginary; }
/**
* @brief Add and assign complex
*
* The computation is done in-place. @f[
* c_0 + c_1 = a_0 + a_1 + i(b_0 + b_1)
* @f]
*/
inline Complex<T>& operator+=(const Complex<T>& other) {
_real += other._real;
_imaginary += other._imaginary;
return *this;
}
/**
* @brief Add complex
*
* @see operator+=()
*/
inline Complex<T> operator+(const Complex<T>& other) const {
return Complex<T>(*this) += other;
}
/**
* @brief Negated complex
*
* @f[
* -c = -a -ib
* @f]
*/
inline Complex<T> operator-() const {
return {-_real, -_imaginary};
}
/**
* @brief Subtract and assign complex
*
* The computation is done in-place. @f[
* c_0 - c_1 = a_0 - a_1 + i(b_0 - b_1)
* @f]
*/
inline Complex<T>& operator-=(const Complex<T>& other) {
_real -= other._real;
_imaginary -= other._imaginary;
return *this;
}
/**
* @brief Subtract complex
*
* @see operator-=()
*/
inline Complex<T> operator-(const Complex<T>& other) const {
return Complex<T>(*this) -= other;
}
/**
* @brief Multiply with scalar and assign
*
* The computation is done in-place. @f[
* c \cdot t = ta + itb
* @f]
*/
inline Complex<T>& operator*=(T scalar) {
_real *= scalar;
_imaginary *= scalar;
return *this;
}
/**
* @brief Multiply with scalar
*
* @see operator*=(T)
*/
inline Complex<T> operator*(T scalar) const {
return Complex<T>(*this) *= scalar;
}
/**
* @brief Divide with scalar and assign
*
* The computation is done in-place. @f[
* \frac c t = \frac a t + i \frac b t
* @f]
*/
inline Complex<T>& operator/=(T scalar) {
_real /= scalar;
_imaginary /= scalar;
return *this;
}
/**
* @brief Divide with scalar
*
* @see operator/=(T)
*/
inline Complex<T> operator/(T scalar) const {
return Complex<T>(*this) /= scalar;
}
private:
T _real, _imaginary;
};
/** @relates Complex
@brief Multiply scalar with complex
Same as Complex::operator*(T) const.
*/
template<class T> inline Complex<T> operator*(T scalar, const Complex<T>& complex) {
return complex*scalar;
}
/** @relates Complex
@brief Divide complex with number and invert
@f[
\frac t c = \frac t a + i \frac t b
@f]
@see Complex::operator/()
*/
template<class T> inline Complex<T> operator/(T scalar, const Complex<T>& complex) {
return {scalar/complex.real(), scalar/complex.imaginary()};
}
/** @debugoperator{Magnum::Math::Complex} */
template<class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Complex<T>& value) {
debug << "Complex(";
debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false);
debug << value.real() << ", " << value.imaginary() << ")";
debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, true);
return debug;
}
/* Explicit instantiation for commonly used types */
#ifndef DOXYGEN_GENERATING_OUTPUT
extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Complex<float>&);
#ifndef MAGNUM_TARGET_GLES
extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Complex<double>&);
#endif
#endif
}}
#endif

1
src/Math/Test/CMakeLists.txt

@ -17,6 +17,7 @@ corrade_add_test(MathMatrix4Test Matrix4Test.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathSwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathComplexTest ComplexTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathDualTest DualTest.cpp)
corrade_add_test(MathQuaternionTest QuaternionTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathDualQuaternionTest DualQuaternionTest.cpp LIBRARIES MagnumMathTestLib)

129
src/Math/Test/ComplexTest.cpp

@ -0,0 +1,129 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include <sstream>
#include <TestSuite/Tester.h>
#include "Math/Complex.h"
namespace Magnum { namespace Math { namespace Test {
class ComplexTest: public Corrade::TestSuite::Tester {
public:
explicit ComplexTest();
void construct();
void constructDefault();
void compare();
void constExpressions();
void addSubtract();
void negated();
void multiplyDivideScalar();
void debug();
};
ComplexTest::ComplexTest() {
addTests(&ComplexTest::construct,
&ComplexTest::constructDefault,
&ComplexTest::compare,
&ComplexTest::constExpressions,
&ComplexTest::addSubtract,
&ComplexTest::negated,
&ComplexTest::multiplyDivideScalar,
&ComplexTest::debug);
}
typedef Math::Complex<float> Complex;
void ComplexTest::construct() {
Complex c(0.5f, -3.7f);
CORRADE_COMPARE(c.real(), 0.5f);
CORRADE_COMPARE(c.imaginary(), -3.7f);
CORRADE_COMPARE(Complex(2.0f), Complex(2.0f, 0.0f));
}
void ComplexTest::constructDefault() {
CORRADE_COMPARE(Complex(), Complex(0.0f, 0.0f));
}
void ComplexTest::compare() {
CORRADE_VERIFY(Complex(3.7f, -1.0f+MathTypeTraits<float>::epsilon()/2) == Complex(3.7f, -1.0f));
CORRADE_VERIFY(Complex(3.7f, -1.0f+MathTypeTraits<float>::epsilon()*2) != Complex(3.7f, -1.0f));
CORRADE_VERIFY(Complex(1.0f+MathTypeTraits<float>::epsilon()/2, 3.7f) == Complex(1.0f, 3.7f));
CORRADE_VERIFY(Complex(1.0f+MathTypeTraits<float>::epsilon()*2, 3.7f) != Complex(1.0f, 3.7f));
}
void ComplexTest::constExpressions() {
/* Default constructor */
constexpr Complex a;
CORRADE_COMPARE(a, Complex(0.0f, 0.0f));
/* Value constructor */
constexpr Complex b(2.5f, -5.0f);
CORRADE_COMPARE(b, Complex(2.5f, -5.0f));
/* Copy constructor */
constexpr Complex c(b);
CORRADE_COMPARE(c, Complex(2.5f, -5.0f));
/* Data access */
constexpr float d = b.real();
constexpr float e = c.imaginary();
CORRADE_COMPARE(d, 2.5f);
CORRADE_COMPARE(e, -5.0f);
}
void ComplexTest::addSubtract() {
Complex a( 1.7f, -3.7f);
Complex b(-3.6f, 0.2f);
Complex c(-1.9f, -3.5f);
CORRADE_COMPARE(a + b, c);
CORRADE_COMPARE(c - b, a);
}
void ComplexTest::negated() {
CORRADE_COMPARE(-Complex(2.5f, -7.4f), Complex(-2.5f, 7.4f));
}
void ComplexTest::multiplyDivideScalar() {
Complex a( 2.5f, -0.5f);
Complex b(-7.5f, 1.5f);
CORRADE_COMPARE(a*-3.0f, b);
CORRADE_COMPARE(-3.0f*a, b);
CORRADE_COMPARE(b/-3.0f, a);
Complex c(-0.8f, 4.0f);
CORRADE_COMPARE(-2.0f/a, c);
}
void ComplexTest::debug() {
std::ostringstream o;
Debug(&o) << Complex(2.5f, -7.5f);
CORRADE_COMPARE(o.str(), "Complex(2.5, -7.5)\n");
}
}}}
CORRADE_TEST_MAIN(Magnum::Math::Test::ComplexTest)
Loading…
Cancel
Save