| @@ -107,6 +107,11 @@ template<> void ivec2::printf() const | |||||
| Log::Debug("[ %i %i ]\n", x, y); | 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 | template<> void vec3::printf() const | ||||
| { | { | ||||
| Log::Debug("[ %6.6f %6.6f %6.6f ]\n", x, y, z); | 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 << ")"; | 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) | template<> std::ostream &operator<<(std::ostream &stream, ivec3 const &v) | ||||
| { | { | ||||
| return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")"; | 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 << ")"; | 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) | template<> std::ostream &operator<<(std::ostream &stream, vec3 const &v) | ||||
| { | { | ||||
| return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")"; | return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")"; | ||||
| @@ -38,6 +38,7 @@ namespace lol | |||||
| typedef tname<uint64_t> u64##suffix; | typedef tname<uint64_t> u64##suffix; | ||||
| VECTOR_TYPES(Vec2, vec2) | VECTOR_TYPES(Vec2, vec2) | ||||
| VECTOR_TYPES(Cmplx, cmplx) | |||||
| VECTOR_TYPES(Vec3, vec3) | VECTOR_TYPES(Vec3, vec3) | ||||
| VECTOR_TYPES(Vec4, vec4) | VECTOR_TYPES(Vec4, vec4) | ||||
| VECTOR_TYPES(Quat, quat) | VECTOR_TYPES(Quat, quat) | ||||
| @@ -117,6 +118,24 @@ VECTOR_TYPES(Mat4, mat4) | |||||
| \ | \ | ||||
| void printf() const; | 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() \ | #define QUATERNION_OPS() \ | ||||
| inline type_t operator *(type_t const &val) const \ | 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; }; | 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 | * 3-element vectors | ||||
| */ | */ | ||||
| @@ -399,6 +459,7 @@ static inline Quat<T> operator /(Quat<T> x, Quat<T> const &y) | |||||
| } | } | ||||
| GLOBALS(Vec2) | GLOBALS(Vec2) | ||||
| GLOBALS(Cmplx) | |||||
| GLOBALS(Vec3) | GLOBALS(Vec3) | ||||
| GLOBALS(Vec4) | GLOBALS(Vec4) | ||||
| GLOBALS(Quat) | GLOBALS(Quat) | ||||
| @@ -24,7 +24,7 @@ TESTS = testsuite | |||||
| testsuite_SOURCES = testsuite.cpp \ | testsuite_SOURCES = testsuite.cpp \ | ||||
| unit/matrix.cpp unit/half.cpp unit/trig.cpp unit/build.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_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ | ||||
| testsuite_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ | testsuite_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ | ||||
| testsuite_DEPENDENCIES = $(top_builddir)/src/liblol.a | testsuite_DEPENDENCIES = $(top_builddir)/src/liblol.a | ||||
| @@ -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 */ | |||||