Browse Source

core: implement complex numbers and add unit tests for these.

legacy
Sam Hocevar sam 13 years ago
parent
commit
433d05964c
4 changed files with 187 additions and 1 deletions
  1. +15
    -0
      src/matrix.cpp
  2. +61
    -0
      src/matrix.h
  3. +1
    -1
      test/Makefile.am
  4. +110
    -0
      test/unit/cmplx.cpp

+ 15
- 0
src/matrix.cpp View File

@@ -107,6 +107,11 @@ template<> void ivec2::printf() const
Log::Debug("[ %i %i ]\n", x, y);
}

template<> void cmplx::printf() const
{
Log::Debug("[ %6.6f %6.6f ]\n", x, y);
}

template<> void vec3::printf() const
{
Log::Debug("[ %6.6f %6.6f %6.6f ]\n", x, y, z);
@@ -152,6 +157,11 @@ template<> std::ostream &operator<<(std::ostream &stream, ivec2 const &v)
return stream << "(" << v.x << ", " << v.y << ")";
}

template<> std::ostream &operator<<(std::ostream &stream, icmplx const &v)
{
return stream << "(" << v.x << ", " << v.y << ")";
}

template<> std::ostream &operator<<(std::ostream &stream, ivec3 const &v)
{
return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
@@ -174,6 +184,11 @@ template<> std::ostream &operator<<(std::ostream &stream, vec2 const &v)
return stream << "(" << v.x << ", " << v.y << ")";
}

template<> std::ostream &operator<<(std::ostream &stream, cmplx const &v)
{
return stream << "(" << v.x << ", " << v.y << ")";
}

template<> std::ostream &operator<<(std::ostream &stream, vec3 const &v)
{
return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";


+ 61
- 0
src/matrix.h View File

@@ -38,6 +38,7 @@ namespace lol
typedef tname<uint64_t> u64##suffix;

VECTOR_TYPES(Vec2, vec2)
VECTOR_TYPES(Cmplx, cmplx)
VECTOR_TYPES(Vec3, vec3)
VECTOR_TYPES(Vec4, vec4)
VECTOR_TYPES(Quat, quat)
@@ -117,6 +118,24 @@ VECTOR_TYPES(Mat4, mat4)
\
void printf() const;

#define COMPLEX_OPS() \
inline type_t operator *(type_t const &val) const \
{ \
return type_t(x * val.x - y * val.y, x * val.y + y * val.x); \
} \
\
inline type_t operator *=(type_t const &val) \
{ \
return *this = (*this) * val; \
} \
\
inline type_t operator ~() const \
{ \
return type_t(x, -y); \
} \
\
inline T norm() const { return len(); }

#define QUATERNION_OPS() \
inline type_t operator *(type_t const &val) const \
{ \
@@ -257,6 +276,47 @@ template <typename T> struct Vec2
union { T y; T b; T j; };
};

/*
* 2-element complexes
*/

template <typename T> struct Cmplx
{
typedef Cmplx<T> type_t;

inline Cmplx() { }
inline Cmplx(T val) : x(val), y(0) { }
inline Cmplx(T _x, T _y) : x(_x), y(_y) { }

LINEAR_OPS()
COMPLEX_OPS()

#if !defined __ANDROID__
template<typename U>
friend std::ostream &operator<<(std::ostream &stream, Cmplx<U> const &v);
#endif

T x, y;
};

template<typename T>
static inline Cmplx<T> re(Cmplx<T> const &val)
{
return ~val / val.sqlen();
}

template<typename T>
static inline Cmplx<T> operator /(T x, Cmplx<T> const &y)
{
return x * re(y);
}

template<typename T>
static inline Cmplx<T> operator /(Cmplx<T> x, Cmplx<T> const &y)
{
return x * re(y);
}

/*
* 3-element vectors
*/
@@ -399,6 +459,7 @@ static inline Quat<T> operator /(Quat<T> x, Quat<T> const &y)
}

GLOBALS(Vec2)
GLOBALS(Cmplx)
GLOBALS(Vec3)
GLOBALS(Vec4)
GLOBALS(Quat)


+ 1
- 1
test/Makefile.am View File

@@ -24,7 +24,7 @@ TESTS = testsuite

testsuite_SOURCES = testsuite.cpp \
unit/matrix.cpp unit/half.cpp unit/trig.cpp unit/build.cpp \
unit/real.cpp unit/image.cpp unit/quat.cpp
unit/real.cpp unit/image.cpp unit/quat.cpp unit/cmplx.cpp
testsuite_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@
testsuite_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@
testsuite_DEPENDENCIES = $(top_builddir)/src/liblol.a


+ 110
- 0
test/unit/cmplx.cpp View File

@@ -0,0 +1,110 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/projects/COPYING.WTFPL for more details.
//

#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#include "core.h"
#include "lol/unit.h"

namespace lol
{

LOLUNIT_FIXTURE(ComplexTest)
{
void SetUp() {}

void TearDown() {}

LOLUNIT_TEST(Equality)
{
cmplx a2(1.0f, 2.0f);
cmplx b2(0.0f, 2.0f);
cmplx c2(1.0f, 0.0f);

LOLUNIT_ASSERT_EQUAL(a2, a2);
LOLUNIT_ASSERT_NOT_DIFFERENT(a2, a2);

LOLUNIT_ASSERT_DIFFERENT(a2, b2);
LOLUNIT_ASSERT_NOT_EQUAL(a2, b2);
LOLUNIT_ASSERT_DIFFERENT(a2, c2);
LOLUNIT_ASSERT_NOT_EQUAL(a2, c2);
}

LOLUNIT_TEST(UnaryMinus)
{
cmplx a(1.0f, 3.0f);
cmplx b(-1.0f, -3.0f);

LOLUNIT_ASSERT_EQUAL(a, -b);
LOLUNIT_ASSERT_EQUAL(-a, b);
}

LOLUNIT_TEST(Conjugate)
{
cmplx a(1.0f, 3.0f);
cmplx b(1.0f, -3.0f);

LOLUNIT_ASSERT_EQUAL(a, ~b);
LOLUNIT_ASSERT_EQUAL(~a, b);
}

LOLUNIT_TEST(Norm)
{
cmplx a(3.0f, -4.0f);

LOLUNIT_ASSERT_EQUAL(a.norm(), 5.0f);

cmplx b = a * ~a;
cmplx c = a.norm() * a.norm();

LOLUNIT_ASSERT_EQUAL(b, c);

cmplx d(5.0f, 12.0f);

LOLUNIT_ASSERT_EQUAL(d.norm(), 13.0f);
LOLUNIT_ASSERT_EQUAL((a * d).norm(), a.norm() * d.norm());
}

LOLUNIT_TEST(Base)
{
cmplx one(1.0f, 0.0f);
cmplx i(0.0f, 1.0f);

LOLUNIT_ASSERT_EQUAL(one.norm(), 1.0f);
LOLUNIT_ASSERT_EQUAL(i.norm(), 1.0f);

LOLUNIT_ASSERT_EQUAL(i * i, -one);
}

LOLUNIT_TEST(Normalize)
{
cmplx a(3.0f, -4.0f);
cmplx b = normalize(a);

LOLUNIT_ASSERT_DOUBLES_EQUAL(b.norm(), 1.0, 1e-8);
}

LOLUNIT_TEST(Reciprocal)
{
cmplx a(3.0f, -4.0f);
cmplx b = re(a);

LOLUNIT_ASSERT_EQUAL(a * b, b * a);

cmplx c = 1.0f;

LOLUNIT_ASSERT_EQUAL(a * b, c);
}
};

} /* namespace lol */


Loading…
Cancel
Save