Moved Eule to its own repository

This commit is contained in:
Leonetienne
2021-11-15 11:32:27 +01:00
commit ba102c8389
48 changed files with 11528 additions and 0 deletions

39
Test/Math_Abs.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "CppUnitTest.h"
#include "../Eule/Math.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
/** Equivalence classes:
* -- value > 0
* -- value < 0
* -- value == 0
*/
namespace _Math
{
TEST_CLASS(_Abs)
{
public:
// Checks with a positive input
TEST_METHOD(Positive_Value)
{
Assert::AreEqual(45.0, Math::Abs(45.0));
return;
}
// Checks with a negative input
TEST_METHOD(Negative_Value)
{
Assert::AreEqual(45.0, Math::Abs(-45.0));
return;
}
// Checks with a zero input
TEST_METHOD(Zero_Value)
{
Assert::AreEqual(0.0, Math::Abs(0.0));
return;
}
};
}

87
Test/Math_Clamp.cpp Normal file
View File

@@ -0,0 +1,87 @@
#include "CppUnitTest.h"
#include "../Eule/Math.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
/** Equivalence classes:
* -- min < v < max -> v
* -- v < min < max -> min
* -- min < max < v -> max
* -- v == min < max -> min
* -- min < v == max -> max
* -- v < max == min -> max
* -- max == min < v -> max
* -- min == v == max -> max
* -- max < v < min -> min
*/
namespace _Math
{
TEST_CLASS(_Clamp)
{
public:
// min < v < max -> v
TEST_METHOD(min_lt_v_lt_max)
{
Assert::AreEqual(6.0, Math::Clamp(6.0, 4.0, 9.0));
return;
}
// v < min < max -> min
TEST_METHOD(v_lt_min_max)
{
Assert::AreEqual(6.0, Math::Clamp(4.0, 6.0, 9.0));
return;
}
// min < max < v -> max
TEST_METHOD(min_lt_max_lt_v)
{
Assert::AreEqual(9.0, Math::Clamp(12.0, 6.0, 9.0));
return;
}
// v == min < max -> min
TEST_METHOD(v_eq_min_lt_max)
{
Assert::AreEqual(6.0, Math::Clamp(6.0, 6.0, 9.0));
return;
}
// min < v == max -> max
TEST_METHOD(min_lt_v_eq_max)
{
Assert::AreEqual(9.0, Math::Clamp(9.0, 6.0, 9.0));
return;
}
// v < max == min -> max
TEST_METHOD(v_lt_max_eq_min)
{
Assert::AreEqual(9.0, Math::Clamp(9.0, 6.0, 9.0));
return;
}
// max == min < v -> max
TEST_METHOD(max_eq_min_lt_v)
{
Assert::AreEqual(9.0, Math::Clamp(15.0, 9.0, 9.0));
return;
}
// min == v == max -> max
TEST_METHOD(min_eq_v_eq_max)
{
Assert::AreEqual(15.0, Math::Clamp(15.0, 15.0, 15.0));
return;
}
// max < v < min -> min
TEST_METHOD(max_lt_v_lt_min)
{
Assert::AreEqual(7.0, Math::Clamp(4.0, 7.0, 3.0));
return;
}
};
}

115
Test/Math_Lerp.cpp Normal file
View File

@@ -0,0 +1,115 @@
#include "CppUnitTest.h"
#include "../Eule/Math.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
/** Equivalence classes:
* -- a < b, 0 < t < 1 -> a < result < b
* -- a > b, 0 < t < 1 -> b < result < a
* -- a == b, 0 < t < 1 -> result == b
*
* -- a < b, t < 0 -> result < a
* -- a > b, t < 0 -> result > a
* -- a == b, t < 0 -> result == b
*
* -- a < b, t > 1 -> result > b
* -- a > b, t > 1 -> result < b
* -- a == b, t > 1 -> result == b
*
* -- a == 0
* -- b == 0
* -- a == b == 0
*/
namespace _Math
{
TEST_CLASS(_Lerp)
{
public:
// -- a < b, 0 < t < 1 -> a < result < b
TEST_METHOD(a_lt_b___0_lt_t_lt_1)
{
Assert::AreEqual(1.75, Math::Lerp(1, 2, 0.75));
return;
}
// -- a > b, 0 < t < 1 -> b < result < a
TEST_METHOD(a_gt_b___0_lt_t_lt_1)
{
Assert::AreEqual(1.25, Math::Lerp(2, 1, 0.75));
return;
}
// -- a == b, 0 < t < 1 -> result == b
TEST_METHOD(a_eq_b___0_lt_t_lt_1)
{
Assert::AreEqual(2.0, Math::Lerp(2, 2, 0.75));
return;
}
// -- a < b, t < 0 -> result < a
TEST_METHOD(a_lt_b___t_lt_0)
{
Assert::AreEqual(0.25, Math::Lerp(1, 2, -0.75));
return;
}
// -- a > b, t < 0 -> result > a
TEST_METHOD(a_gt_b___t_lt_0)
{
Assert::AreEqual(2.75, Math::Lerp(2, 1, -0.75));
return;
}
// -- a == b, t < 0 -> result == b
TEST_METHOD(a_eq_b___t_lt_0)
{
Assert::AreEqual(2.0, Math::Lerp(2, 2, -0.75));
return;
}
// -- a < b, t > 1 -> result > b
TEST_METHOD(a_lt_b___t_gt_1)
{
Assert::AreEqual(2.5, Math::Lerp(1, 2, 1.5));
return;
}
// -- a > b, t > 1 -> result < b
TEST_METHOD(a_gt_b___t_gt_1)
{
Assert::AreEqual(0.5, Math::Lerp(2, 1, 1.5));
return;
}
// -- a == b, t > 1 -> result == b
TEST_METHOD(a_eq_b___t_gt_1)
{
Assert::AreEqual(1.0, Math::Lerp(1, 1, 1.5));
return;
}
// -- a == 0
TEST_METHOD(a_eq_0)
{
Assert::AreEqual(2.25, Math::Lerp(0, 3, 0.75));
return;
}
// -- b == 0
TEST_METHOD(b_eq_0)
{
Assert::AreEqual(0.75, Math::Lerp(3, 0, 0.75));
return;
}
// -- a == b == 0
TEST_METHOD(a_eq_b_eq_0)
{
Assert::AreEqual(0.0, Math::Lerp(0, 0, 0.75));
return;
}
};
}

40
Test/Math_Max.cpp Normal file
View File

@@ -0,0 +1,40 @@
#include "CppUnitTest.h"
#include "../Eule/Math.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
/** Equivalence classes:
* -- a < b
* -- a > b
* -- a == b
*/
namespace _Math
{
TEST_CLASS(_Max)
{
public:
// a < b
TEST_METHOD(a_lt_b)
{
Assert::AreEqual(12.0, Math::Max(4.0, 12.0));
return;
}
// a > b
TEST_METHOD(a_gt_b)
{
Assert::AreEqual(12.0, Math::Max(12.0, 4.0));
return;
}
// a == b
TEST_METHOD(a_eq_b)
{
Assert::AreEqual(9.0, Math::Max(9.0, 9.0));
return;
}
};
}

52
Test/Math_Min.cpp Normal file
View File

@@ -0,0 +1,52 @@
#include "CppUnitTest.h"
#include "../Eule/Math.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
/** Equivalence classes:
* -- min < v < max
* -- v < min < max
* -- min < max < v
* -- v == min < max
* -- min < v == max
* -- v < max == min
* -- max == min < v
* -- max == min == v
* -- max < v < min
*/
/** Equivalence classes:
* -- a < b
* -- a > b
* -- a == b
*/
namespace _Math
{
TEST_CLASS(_Min)
{
public:
// a < b
TEST_METHOD(a_lt_b)
{
Assert::AreEqual(4.0, Math::Min(4.0, 9.0));
return;
}
// a > b
TEST_METHOD(a_gt_b)
{
Assert::AreEqual(4.0, Math::Min(9.0, 4.0));
return;
}
// a == b
TEST_METHOD(a_eq_b)
{
Assert::AreEqual(9.0, Math::Min(9.0, 9.0));
return;
}
};
}

26
Test/Math_Random.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include "CppUnitTest.h"
#include "../Eule/Math.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace _Math
{
TEST_CLASS(_Random)
{
public:
// Checks that all values are always 0 <= v <= 1
TEST_METHOD(Always_Satisfies_0_lt_v_lt_1)
{
// Test 1000 random values
for (std::size_t i = 0; i < 1e3; i++)
{
const double rnd = Math::Random();
Assert::IsTrue(rnd >= 0.0, L"rnd < 0");
Assert::IsTrue(rnd <= 1.0, L"rnd > 1");
}
return;
}
};
}

View File

@@ -0,0 +1,100 @@
#include "CppUnitTest.h"
#include "../_TestingUtilities/Testutil.h"
#include "../Eule/Math.h"
#include <array>
#include <sstream>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace _Math
{
TEST_CLASS(_RandomIntRange)
{
public:
// Checks that a random integer is never outside the specification, two positive values
TEST_METHOD(Never_Outside_Specification__pos__pos)
{
// Test 1000 random integers
for (std::size_t i = 0; i < 1000; i++)
{
int rnd = Math::RandomIntRange(49, 99);
Assert::IsTrue(rnd >= 49, L"rnd too small");
Assert::IsTrue(rnd <= 99, L"rnd too big");
}
return;
}
// Checks that a random integer is never outside the specification, negative minimum
TEST_METHOD(Never_Outside_Specification__neg__pos)
{
// Test 1000 random integers
for (std::size_t i = 0; i < 1000; i++)
{
int rnd = Math::RandomIntRange(-39, 99);
Assert::IsTrue(rnd >= -39, L"rnd too small");
Assert::IsTrue(rnd <= 99, L"rnd too big");
}
return;
}
// Checks that a random integer is never outside the specification, two negative values
TEST_METHOD(Never_Outside_Specification__neg__neg)
{
// Test 1000 random integers
for (std::size_t i = 0; i < 1000; i++)
{
int rnd = Math::RandomIntRange(-39, -10);
Assert::IsTrue(rnd >= -39, L"rnd too small");
Assert::IsTrue(rnd <= -10, L"rnd too big");
}
return;
}
// Checks that the random intrange method also returns the supplied limits
TEST_METHOD(Inclusivity)
{
// Test 1000 random integers
// The chance that any number [0,9] will not drop at least once is basically 0
std::array<bool, 10> foundDigits;
foundDigits.fill(false);
for (std::size_t i = 0; i < 1000; i++)
{
int randomVal = Math::RandomIntRange(0, 9);
foundDigits[randomVal] = true;
}
// Check that each value has been rolled at least once
for (const bool& b : foundDigits)
Assert::IsTrue(b);
return;
}
// Checks that the produced integer distribution shows a big standard deviation
TEST_METHOD(Big_Standard_Deviation)
{
// Setup
std::vector<int> rands;
rands.resize(1000);
// Exercise
// Create 1000 random values
std::generate_n(rands.data(), rands.size(), []()->int { return Math::RandomIntRange(100, (int)4e9); });
// Verify
const double stddev = Testutil::Stddev(rands);
Assert::IsTrue(stddev >= 1000000, (std::wstringstream() << stddev).str().c_str());
return;
}
};
}

View File

@@ -0,0 +1,51 @@
#include "CppUnitTest.h"
#include "../_TestingUtilities/Testutil.h"
#include "../Eule/Math.h"
#include <array>
#include <sstream>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace _Math
{
TEST_CLASS(_RandomInteger)
{
public:
// Checks that the produced unsigned-integer distribution shows a big standard deviation
TEST_METHOD(Uint_Big_Standard_Deviation)
{
// Setup
std::vector<unsigned int> rands;
rands.resize(1000);
// Exercise
// Create 1000 random values
std::generate_n(rands.data(), rands.size(), []()->unsigned int { return Math::RandomUint(); });
// Verify
const double stddev = Testutil::Stddev<unsigned int>(rands);
Assert::IsTrue(stddev >= 1000000, (std::wstringstream() << stddev).str().c_str());
return;
}
// Checks that the produced integer distribution shows a big standard deviation
TEST_METHOD(Int_Big_Standard_Deviation)
{
// Setup
std::vector<int> rands;
rands.resize(1000);
// Exercise
// Create 1000 random values
std::generate_n(rands.data(), rands.size(), []()->int { return Math::RandomInt(); });
// Verify
const double stddev = Testutil::Stddev<int>(rands);
Assert::IsTrue(stddev >= 1000000, (std::wstringstream() << stddev).str().c_str());
return;
}
};
}

61
Test/Math_Similar.cpp Normal file
View File

@@ -0,0 +1,61 @@
#include "CppUnitTest.h"
#include "../Eule/Math.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace _Math
{
TEST_CLASS(_Similar)
{
public:
// Checks that the similar function works with an exact comparison -> true
TEST_METHOD(Exact_Comparison_True)
{
Assert::IsTrue(Math::Similar(100, 100, 0));
return;
}
// Checks that the similar function works with an exact comparison -> false
TEST_METHOD(Exact_Comparison_False)
{
Assert::IsFalse(Math::Similar(100, 100.001, 0));
return;
}
// Checks that the similar function works with an exact comparison -> false
TEST_METHOD(Exact_Comparison_False2)
{
Assert::IsFalse(Math::Similar(100, 99.999, 0));
return;
}
// Checks that the similar function works with a loose comparison -> true
TEST_METHOD(Loose_Comparison_True)
{
Assert::IsTrue(Math::Similar(100, 100.001, 0.01));
return;
}
// Checks that the similar function works with a loose comparison -> true
TEST_METHOD(Loose_Comparison_True2)
{
Assert::IsTrue(Math::Similar(100, 99.999, 0.01));
return;
}
// Checks that the similar function works with a loose comparison -> false
TEST_METHOD(Loose_Comparison_False)
{
Assert::IsFalse(Math::Similar(100, 100.1, 0.01));
return;
}
// Checks that the similar function works with a loose comparison -> false
TEST_METHOD(Loose_Comparison_False2)
{
Assert::IsFalse(Math::Similar(100, 99.9, 0.01));
return;
}
};
}

231
Test/Math__Oscillate.cpp Normal file
View File

@@ -0,0 +1,231 @@
#include "CppUnitTest.h"
#include "../_TestingUtilities/Testutil.h"
#include "../Eule/Math.h"
#include "../Eule/Constants.h"
#include <array>
#include <sstream>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace _Math
{
TEST_CLASS(_Oscillate)
{
public:
// Checks that an oscillation of speed 1 between -1 and 1 is just equal to sin(counter*pi-pi/2)
TEST_METHOD(Oracle_Sin)
{
// Test 1000 random floats
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
const double rnd = Math::RandomRange(-1000, 1000);
// Exercise
const double result = Math::Oscillate(-1, 1, rnd, 1);
// Verify
const double expected = sin(rnd * PI - HALF_PI);
Assert::IsTrue(Math::Similar(expected, result));
}
return;
}
// Tests that the result is a, if the counter is 0 or a whole, even integer
TEST_METHOD(Returns_a_For_Counter_0)
{
// Test 1000 random floats
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
const double a = Math::RandomRange(-1000, 1000);
const double b = Math::RandomRange(-1000, 1000);
const int even = Math::RandomIntRange(-1000, 1000) & ~1;
// Exercise
const double result = Math::Oscillate(a, b, even, 1);
// Verify
const double expected = a;
std::wstringstream wss;
wss << std::endl
<< "a: " << a << std::endl
<< "b: " << b << std::endl
<< "expected: " << expected << std::endl
<< "result: " << result << std::endl
<< std::endl;
Assert::IsTrue(Math::Similar(expected, result), wss.str().c_str());
}
}
// Tests that the result is b, if the counter is a whole, uneven integer
TEST_METHOD(Returns_b_For_Uneven_Whole_Counter)
{
// Test 1000 random floats
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
const double a = Math::RandomRange(-1000, 1000);
const double b = Math::RandomRange(-1000, 1000);
const int uneven = Math::RandomIntRange(-1000, 1000) | 1;
// Exercise
const double result = Math::Oscillate(a, b, uneven, 1);
// Verify
const double expected = b;
Assert::IsTrue(Math::Similar(expected, result));
}
}
// Tests that the result is (a+b)/2, when counter satisfies (int)x + 0.5
TEST_METHOD(Returns_ab_mean_for_intx_plus_0p5)
{
// Test 1000 random floats
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
const double a = Math::RandomRange(-1000, 1000);
const double b = Math::RandomRange(-1000, 1000);
const int anInt = Math::RandomIntRange(-1000, 1000);
// Exercise
const double result = Math::Oscillate(a, b, anInt + 0.5, 1);
// Verify
const double expected = (a+b) / 2.0;
std::wstringstream wss;
wss << std::endl
<< "a: " << a << std::endl
<< "b: " << b << std::endl
<< "expected: " << expected << std::endl
<< "result: " << result << std::endl
<< std::endl;
Assert::IsTrue(Math::Similar(expected, result), wss.str().c_str());
}
}
// Tests that the result is (3a+b)/4, when counter satisfies 2(int)x + 0.25
TEST_METHOD(Returns_3ab_mean_for_intx_plus_0p25_counterbase_even)
{
// Test 1000 random floats
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
const double a = Math::RandomRange(-1, 1);
const double b = Math::RandomRange(-1, 1);
const int even = Math::RandomIntRange(-1000, 1000) & ~1;
// Exercise
const double result = Math::Oscillate(a, b, even + 0.25, 1);
// Verify
const double expected = (3*a + b) / 4.0;
std::wstringstream wss;
wss << std::endl
<< "a: " << a << std::endl
<< "b: " << b << std::endl
<< "expected: " << expected << std::endl
<< "result: " << result << std::endl
<< std::endl;
// Oscillate is not linear, we just want a really rough approximation
Assert::IsTrue(Math::Similar(expected, result, 0.4), wss.str().c_str());
}
}
// Tests that the result is (a+3b)/4, when counter satisfies 2(int)x + 0.75
TEST_METHOD(Returns_a3b_mean_for_intx_plus_0p75_counterbase_even)
{
// Test 1000 random floats
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
const double a = Math::RandomRange(-1, 1);
const double b = Math::RandomRange(-1, 1);
const int even = Math::RandomIntRange(-1000, 1000) & ~1;
// Exercise
const double result = Math::Oscillate(a, b, even + 0.75, 1);
// Verify
const double expected = (a + 3*b) / 4.0;
// Oscillate is not linear, we just want a really rough approximation
Assert::IsTrue(Math::Similar(expected, result, 0.4)); // Oscillate is not linear
}
}
// Tests that the result is (a+3b)/4, when counter satisfies 2(int)x+1 + 0.25
TEST_METHOD(Returns_3ab_mean_for_intx_plus_0p25_counterbase_uneven)
{
// Test 1000 random floats
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
const double a = Math::RandomRange(-1, 1);
const double b = Math::RandomRange(-1, 1);
const int uneven = Math::RandomIntRange(-1000, 1000) | 1;
// Exercise
const double result = Math::Oscillate(a, b, uneven + 0.25, 1);
// Verify
const double expected = (a + 3*b) / 4.0;
// Oscillate is not linear, we just want a really rough approximation
Assert::IsTrue(Math::Similar(expected, result, 0.4));
}
}
// Tests that the result is (3a+b)/4, when counter satisfies 2(int)x+1 + 0.75
TEST_METHOD(Returns_a3b_mean_for_intx_plus_0p75_counterbase_uneven)
{
// Test 1000 random floats
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
const double a = Math::RandomRange(-1, 1);
const double b = Math::RandomRange(-1, 1);
const int uneven = Math::RandomIntRange(-1000, 1000) | 1;
// Exercise
const double result = Math::Oscillate(a, b, uneven + 0.75, 1);
// Verify
const double expected = (3*a + b) / 4.0;
// Oscillate is not linear, we just want a really rough approximation
Assert::IsTrue(Math::Similar(expected, result, 0.4)); // Oscillate is not linear
}
}
// Tests that doubling the speed will double the frequency
TEST_METHOD(Doubling_Speed_Doubles_Frequency)
{
// Test 1000 random floats
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
const double a = Math::RandomRange(-1000, 1000);
const double b = Math::RandomRange(-1000, 1000);
// Exercise
const double result = Math::Oscillate(a, b, 0.5, 2);
// Verify
const double expected = b;
Assert::IsTrue(Math::Similar(expected, result));
}
return;
}
};
}

View File

@@ -0,0 +1,79 @@
#include "CppUnitTest.h"
#include "../_TestingUtilities/Testutil.h"
#include "../Eule/Math.h"
#include <array>
#include <sstream>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace _Math
{
TEST_CLASS(_RandomRange)
{
public:
// Checks that a random double is never outside the specification, two positive values
TEST_METHOD(Random_Doublerange_Never_Outside_Specification__pos__pos)
{
// Test 1000 random integers
for (std::size_t i = 0; i < 1000; i++)
{
double rnd = Math::RandomRange(49.0, 99.0);
Assert::IsTrue(rnd >= 49.0, L"rnd too small");
Assert::IsTrue(rnd <= 99.0, L"rnd too big");
}
return;
}
// Checks that a random double is never outside the specification, negative minimum
TEST_METHOD(Random_Doublerange_Never_Outside_Specification__neg__pos)
{
// Test 1000 random integers
for (std::size_t i = 0; i < 1000; i++)
{
double rnd = Math::RandomRange(-39.0, 99.0);
Assert::IsTrue(rnd >= -39.0, L"rnd too small");
Assert::IsTrue(rnd <= 99.0, L"rnd too big");
}
return;
}
// Checks that a random double is never outside the specification, two negative values
TEST_METHOD(Random_Doublerange_Never_Outside_Specification__neg__neg)
{
// Test 1000 random integers
for (std::size_t i = 0; i < 1000; i++)
{
double rnd = Math::RandomRange(-39.0, -10.0);
Assert::IsTrue(rnd >= -39.0, L"rnd too small");
Assert::IsTrue(rnd <= -10.0, L"rnd too big");
}
return;
}
// Checks that the produced double-precision floating point distribution shows a big standard deviation
TEST_METHOD(Double_Big_Standard_Deviation)
{
// Setup
std::vector<double> rands;
rands.resize(100);
// Exercise
// Create 1000 random values
std::generate_n(rands.data(), rands.size(), []()->double { return Math::RandomRange(100, 4e9); });
// Verify
const double stddev = Testutil::Stddev(rands);
Assert::IsTrue(stddev >= 1000000, (std::wstringstream() << stddev).str().c_str());
return;
}
};
}

984
Test/Matrix4x4.cpp Normal file
View File

@@ -0,0 +1,984 @@
#include "CppUnitTest.h"
#include "../Eule/Matrix4x4.h"
#include "../Eule/Vector3.h"
#include "../_TestingUtilities/HandyMacros.h"
#include <random>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace Matrices
{
TEST_CLASS(_Matrix4x4)
{
private:
std::mt19937 rng;
public:
// Constructor
_Matrix4x4()
{
rng = std::mt19937((std::random_device())());
return;
}
// Tests that a freshly created matrix is an identity matrix
TEST_METHOD(New_Matrix_Is_Identity)
{
Matrix4x4 mat;
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
if (i == j)
Assert::AreEqual(1.0, mat[i][j]);
else
Assert::AreEqual(0.0, mat[i][j]);
return;
}
// Test if setting values via array descriptors works
TEST_METHOD(Can_Set_Values_ArrayDescriptor)
{
Matrix4x4 mat;
mat[0][0] = 1;
mat[0][1] = 2;
mat[0][2] = 3;
mat[0][3] = 4;
mat[1][0] = 5;
mat[1][1] = 6;
mat[1][2] = 7;
mat[1][3] = 8;
mat[2][0] = 9;
mat[2][1] = 10;
mat[2][2] = 11;
mat[2][3] = 12;
mat[3][0] = 13;
mat[3][1] = 14;
mat[3][2] = 15;
mat[3][3] = 16;
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
Assert::AreEqual((double)(i * 4 + j + 1), mat[i][j]);
return;
}
// Tests if setting values via letters works
TEST_METHOD(Can_Set_Values_Letters)
{
Matrix4x4 mat;
mat.a = 1;
mat.b = 2;
mat.c = 3;
mat.d = 4;
mat.e = 5;
mat.f = 6;
mat.g = 7;
mat.h = 8;
mat.i = 9;
mat.j = 10;
mat.k = 11;
mat.l = 12;
mat.m = 13;
mat.n = 14;
mat.o = 15;
mat.p = 16;
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
Assert::AreEqual((double)(i * 4 + j + 1), mat[i][j]);
return;
}
// Tests if setting values via multiple initializer lists works
TEST_METHOD(Can_Set_Values_Multiple_Initializer_Lists)
{
Matrix4x4 mat;
mat[0] = { 1, 2, 3, 4 };
mat[1] = { 5, 6, 7, 8 };
mat[2] = { 9, 10, 11, 12 };
mat[3] = { 13, 14, 15, 16 };
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
Assert::AreEqual((double)(i * 4 + j + 1), mat[i][j]);
return;
}
// Tests if values can be read correctly from the reference variables
TEST_METHOD(Can_Read_Letters)
{
Matrix4x4 mat;
// Populate matrix
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
mat[i][j] = (double)(i * 4 + j + 1);
// Check if values can be read
Assert::AreEqual( 1.0, mat.a);
Assert::AreEqual( 2.0, mat.b);
Assert::AreEqual( 3.0, mat.c);
Assert::AreEqual( 4.0, mat.d);
Assert::AreEqual( 5.0, mat.e);
Assert::AreEqual( 6.0, mat.f);
Assert::AreEqual( 7.0, mat.g);
Assert::AreEqual( 8.0, mat.h);
Assert::AreEqual( 9.0, mat.i);
Assert::AreEqual(10.0, mat.j);
Assert::AreEqual(11.0, mat.k);
Assert::AreEqual(12.0, mat.l);
Assert::AreEqual(13.0, mat.m);
Assert::AreEqual(14.0, mat.n);
Assert::AreEqual(15.0, mat.o);
Assert::AreEqual(16.0, mat.p);
return;
}
// Tests if the copy constructor results in the same values as the reference given
TEST_METHOD(CopyConstructor_Equal_Values)
{
Matrix4x4 mat1;
// Fill with values
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
mat1[i][j] = i * 4.0 + j;
// Copy
Matrix4x4 mat2(mat1);
// Both equal?
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
Assert::AreEqual(mat1[i][j], mat2[i][j]);
return;
}
// Tests if the equals operator results in the same values as the reference given
TEST_METHOD(Copy_Via_Equals_Operator)
{
Matrix4x4 mat1;
// Fill with values
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
mat1[i][j] = i * 4.0 + j;
// Copy
Matrix4x4 mat2 = mat1;
// Both equal?
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
Assert::AreEqual(mat1[i][j], mat2[i][j]);
return;
}
// Tests if the values of a matrix constructed via a copy constructor can be changed without modifying the object copied from
TEST_METHOD(Copy_Is_Independent_CopyConstructor)
{
Matrix4x4 mat1;
// Fill with values
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
mat1[i][j] = i * 4.0 + j;
// Copy
Matrix4x4 mat2(mat1);
// Change values in mat2
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
mat2[i][j] *= -99;
// Is mat1 untouched?
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
Assert::AreEqual((double)(i * 4 + j), mat1[i][j]);
// Are the values of mat2 correct?
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
Assert::AreEqual((double)(i * 4 + j) * -99, mat2[i][j]);
return;
}
// Tests if the values of a matrix constructed copied via the equals operator can be changed without modifying the object copied from
TEST_METHOD(Copy_Is_Independent_EqualOperator)
{
Matrix4x4 mat1;
// Fill with values
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
mat1[i][j] = i * 4.0 + j;
// Copy
Matrix4x4 mat2 = mat1;
// Change values in mat2
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
mat2[i][j] *= -99;
// Is mat1 untouched?
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
Assert::AreEqual((double)(i * 4 + j), mat1[i][j]);
// Are the values of mat2 correct?
for (std::size_t i = 0; i < 4; i++)
for (std::size_t j = 0; j < 4; j++)
Assert::AreEqual((double)(i * 4 + j) * -99, mat2[i][j]);
return;
}
// Tests that copying via operator= works
TEST_METHOD(Copy_Operator)
{
// Setup
Matrix4x4 a;
a[0] = { 1, 0, 0, 5 };
a[1] = { 2, 0, 0, 6 };
a[2] = { 3, 0, 0, 7 };
a[3] = { 4, 0, 0, 8 };
Matrix4x4 a_toCopy;
a_toCopy[0] = { 1, 0, 0, 5 };
a_toCopy[1] = { 2, 0, 0, 6 };
a_toCopy[2] = { 3, 0, 0, 7 };
a_toCopy[3] = { 4, 0, 0, 8 };
// Exercise
Matrix4x4 b = a_toCopy;
// Verify
Assert::IsTrue(a == a_toCopy, L"a got destroyed!");
Assert::IsTrue(b == a, L"a does not match b!");
return;
}
// Tests that moving via operator= works
TEST_METHOD(Move_Operator)
{
// Setup
Matrix4x4 a;
a[0] = { 1, 0, 0, 5 };
a[1] = { 2, 0, 0, 6 };
a[2] = { 3, 0, 0, 7 };
a[3] = { 4, 0, 0, 8 };
Matrix4x4 a_backup = a;
// Exercise
Matrix4x4 b = std::move(a);
// Verify
Assert::IsTrue(b == a_backup, L"Values don't match!");
return;
}
// Tests if the multiply-equals (*=) operator works as intended
TEST_METHOD(Multiplication_Equals)
{
// Populate 1
Matrix4x4 mat1;
mat1[0] = { 12, 33, 43, 34 };
mat1[1] = { 0, 4, 3, 11 };
mat1[2] = { 76, 5, 42, 4 };
mat1[3] = { 0, 0, 0, 1 };
// Populate 2
Matrix4x4 mat2;
mat2[0] = { 32, 11, 23, 6 };
mat2[1] = { 54, 23, 64, 9 };
mat2[2] = { 64, 43, 12, 16 };
mat2[3] = { 0, 0, 0, 1 };
// Multiply
mat1 *= mat2;
// Check
Matrix4x4 expected;
expected[0] = { 4918.0, 2740.0, 2904.0, 40 };
expected[1] = { 408.0, 221.0, 292.0, 20 };
expected[2] = { 5390.0, 2757.0, 2572.0, 20 };
expected[3] = { 0, 0, 0, 1 };
Assert::IsTrue(mat1.v == expected.v);
return;
}
// Tests if the multiplication operator works as intended
TEST_METHOD(Multiplication)
{
// Populate 1
Matrix4x4 mat1;
mat1[0] = { 12, 33, 43, 34 };
mat1[1] = { 0, 4, 3, 11 };
mat1[2] = { 76, 5, 42, 4 };
mat1[3] = { 0, 0, 0, 1 };
// Populate 2
Matrix4x4 mat2;
mat2[0] = { 32, 11, 23, 6 };
mat2[1] = { 54, 23, 64, 9 };
mat2[2] = { 64, 43, 12, 16 };
mat2[3] = { 0, 0, 0, 1 };
// Multiply
Matrix4x4 mat3 = mat1 * mat2;
// Check
Matrix4x4 expected;
expected[0] = { 4918.0, 2740.0, 2904.0, 40 };
expected[1] = { 408.0, 221.0, 292.0, 20 };
expected[2] = { 5390.0, 2757.0, 2572.0, 20 };
expected[3] = { 0, 0, 0, 1 };
Assert::IsTrue(mat3.v == expected.v);
return;
}
// Tests if GetTranslationComponent returns the correct values
TEST_METHOD(GetTranslationComponent)
{
// Create and populate mat
Matrix4x4 mat;
mat.d = 69;
mat.h = 32;
mat.l = 16;
// Get translation component
Vector3d translation = mat.GetTranslationComponent();
// Check
Assert::AreEqual(69.0, translation.x);
Assert::AreEqual(32.0, translation.y);
Assert::AreEqual(16.0, translation.z);
return;
}
// Tests if SetTranslationComponent returns the correct values
TEST_METHOD(SetTranslationComponent)
{
// Create and populate mat
Vector3d translation(69, 32, 16);
// Set translation component
Matrix4x4 mat;
mat.SetTranslationComponent(translation);
// Check
Assert::AreEqual(69.0, mat.d);
Assert::AreEqual(32.0, mat.h);
Assert::AreEqual(16.0, mat.l);
return;
}
// Tests that transpose3x3 works
TEST_METHOD(Transpose3x3)
{
Matrix4x4 m;
m[0] = { 0, 0, 0, 0 };
m[1] = { 3, 0, 4, 0 };
m[2] = { 0, 0, 2, 5 };
m[3] = { 9, 0, 6, 0 };
Matrix4x4 target;
target[0] = { 0, 3, 0, 0 };
target[1] = { 0, 0, 0, 0 };
target[2] = { 0, 4, 2, 5 };
target[3] = { 9, 0, 6, 0 };
// Create debug output
std::wstringstream wss;
wss << std::endl
<< "Actual: " << m.Transpose3x3() << std::endl
<< "Target: " << target << std::endl;
Assert::IsTrue(target == m.Transpose3x3(), wss.str().c_str());
return;
}
// Tests that transpose4x4 works
TEST_METHOD(Transpose4x4)
{
Matrix4x4 m;
m[0] = { 0, 0, 0, 0 };
m[1] = { 3, 0, 4, 0 };
m[2] = { 0, 0, 2, 5 };
m[3] = { 9, 0, 6, 0 };
Matrix4x4 target;
target[0] = { 0, 3, 0, 9 };
target[1] = { 0, 0, 0, 0 };
target[2] = { 0, 4, 2, 6 };
target[3] = { 0, 0, 5, 0 };
// Create debug output
std::wstringstream wss;
wss << std::endl
<< "Actual: " << m.Transpose4x4() << std::endl
<< "Target: " << target << std::endl;
Assert::IsTrue(target == m.Transpose4x4(), wss.str().c_str());
return;
}
// Tests that IsInvertible3x3 works -> true
TEST_METHOD(Is_Invertible_3x3_True)
{
Matrix4x4 m;
m[0] = { 0.56601, -0.87207, 0.52783, 488.00000 };
m[1] = { -0.55281, 0.41590, 0.85470, 500.00000 };
m[2] = { -1.09497, -0.66076, -0.15866, -155.09390 };
m[3] = { 0.00000, 0.00000, 0.00000, 0.00000 };
Assert::IsTrue(m.IsInversible3x3());
return;
}
// Tests that IsInvertible3x3 works -> false
TEST_METHOD(Is_Invertible_3x3_False)
{
Matrix4x4 m;
m[0] = { 0, 0, 1, 0 };
m[1] = { 0, 0, 0, 0 };
m[2] = { 0, 0, 0, 0 };
m[3] = { 0, 0, 0, 0 };
Assert::IsFalse(m.IsInversible3x3());
return;
}
// Tests that IsInvertible4x4 works -> true
TEST_METHOD(Is_Invertible_4x4_True)
{
Matrix4x4 m;
m[0] = { 0.56601, -0.87207, 0.52783, 488.00000 };
m[1] = { -0.55281, 0.41590, 0.85470, 500.00000 };
m[2] = { -1.09497, -0.66076, -0.15866, -155.09390 };
m[3] = { 0.00000, 0.00000, 0.00000, 1.00000 };
Assert::IsTrue(m.IsInversible4x4());
return;
}
// Tests that IsInvertible4x4 works -> false
TEST_METHOD(Is_Invertible_4x4_False)
{
Matrix4x4 m;
m[0] = { 0.56601, -0.87207, 0.52783, 488.00000 };
m[1] = { -0.55281, 0.41590, 0.85470, 500.00000 };
m[2] = { -1.09497, -0.66076, -0.15866, -155.09390 };
m[3] = { 0.00000, 0.00000, 0.00000, 0.00000 };
Assert::IsFalse(m.IsInversible4x4());
return;
}
// Tests that inverting a 3x3 matrix (scale, rotation, translation) works
TEST_METHOD(Inverse3x3)
{
// Invert 50 randomly generated matrices
for (std::size_t i = 0; i < 50;)
{
Matrix4x4 m;
m[0] = { LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE };
m[1] = { LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE };
m[2] = { LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE };
m[3] = { LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE };
if (m.IsInversible3x3())
{
Matrix4x4 inv_m = m.Inverse3x3();
Matrix4x4 result = m * inv_m;
// Create debug output
std::wstringstream wss;
wss << std::endl
<< "i: " << i << std::endl
<< "Actual: " << result << std::endl
<< "Target: " << Matrix4x4() << std::endl;
Assert::IsTrue(result.Similar(Matrix4x4()), wss.str().c_str()); // Default constructor is identity matrix
i++;
}
}
return;
}
// Tests that inverting a 4x4 matrix works
TEST_METHOD(Inverse4x4)
{
// Invert 50 randomly generated matrices
for (std::size_t i = 0; i < 50;)
{
Matrix4x4 m;
m[0] = { LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE };
m[1] = { LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE };
m[2] = { LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE };
m[3] = { LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE };
if (m.IsInversible4x4())
{
Matrix4x4 inv_m = m.Inverse4x4();
// Create debug output
std::wstringstream wss;
wss << std::endl
<< "i: " << i << std::endl
<< "Actual: " << m.Multiply4x4(inv_m) << std::endl
<< "Target: " << Matrix4x4() << std::endl;
Assert::IsTrue((m.Multiply4x4(inv_m)).Similar(Matrix4x4(), 0.0001), wss.str().c_str()); // Default constructor is identity matrix
i++;
}
}
return;
}
// Tests the Multiply4x4 method, which does an actual 4x4 multiplication
TEST_METHOD(Multiply4x4)
{
Matrix4x4 a;
a[0] = { 0, 1, 2, 3 };
a[1] = { 4, 5, 6, 7 };
a[2] = { 8, 9, 0, 1 };
a[3] = { 2, 3, 4, 5 };
Matrix4x4 b;
b[0] = { 9, 8, 7, 6 };
b[1] = { 5, 4, 3, 2 };
b[2] = { 1, 0, 9, 8 };
b[3] = { 7, 6, 5, 4 };
Matrix4x4 e; // Expected
e[0] = { 28, 22, 36, 30 };
e[1] = { 116, 94, 132, 110 };
e[2] = { 124, 106, 88, 70 };
e[3] = { 72, 58, 84, 70 };
// Create debug output
std::wstringstream wss;
wss << std::endl
<< "Actual: " << a.Multiply4x4(b) << std::endl
<< "Target: " << e << std::endl;
Assert::IsTrue(a.Multiply4x4(b).Similar(e), wss.str().c_str());
}
// Tests the DropTranslationComponents method. It should return itself, with d,h,l = 0,0,0
TEST_METHOD(DropTranslationComponents)
{
// Setup
Matrix4x4 a;
a[0] = { 0, 1, 2, 3 };
a[1] = { 4, 5, 6, 7 };
a[2] = { 8, 9, 0, 1 };
a[3] = { 2, 3, 4, 5 };
Matrix4x4 e; // Expected
e[0] = { 0, 1, 2, 0 };
e[1] = { 4, 5, 6, 0 };
e[2] = { 8, 9, 0, 0 };
e[3] = { 2, 3, 4, 5 };
// Exercise, Verify
Assert::IsTrue(e == a.DropTranslationComponents());
return;
}
//! Tests that adding two matrices works as intended
TEST_METHOD(Operator_Add)
{
// Setup
Matrix4x4 a;
a[0] = { -9, 5, 6, 7 };
a[1] = { 1, 2, 5, 0 };
a[2] = { 2, -2, 7, 5 };
a[3] = { 3, 0, 3, 0 };
Matrix4x4 b;
b[0] = { 6, 0, 5, 0 };
b[1] = { 3, 0, 1, 1 };
b[2] = { 1, 7, 2, 7 };
b[3] = { 0, 2, 0, 0 };
Matrix4x4 exp; // Expected
exp[0] = { -3, 5, 11, 7 };
exp[1] = { 4, 2, 6, 1 };
exp[2] = { 3, 5, 9, 12 };
exp[3] = { 3, 2, 3, 0 };
// Exercise
Matrix4x4 result = a + b;
// Verify
Assert::IsTrue(exp == result);
return;
}
//! Tests that adding two matrices works as intended
TEST_METHOD(Operator_AddEquals)
{
// Setup
Matrix4x4 a;
a[0] = { -9, 5, 6, 7 };
a[1] = { 1, 2, 5, 0 };
a[2] = { 2, -2, 7, 5 };
a[3] = { 3, 0, 3, 0 };
Matrix4x4 b;
b[0] = { 6, 0, 5, 0 };
b[1] = { 3, 0, 1, 1 };
b[2] = { 1, 7, 2, 7 };
b[3] = { 0, 2, 0, 0 };
Matrix4x4 exp; // Expected
exp[0] = { -3, 5, 11, 7 };
exp[1] = { 4, 2, 6, 1 };
exp[2] = { 3, 5, 9, 12 };
exp[3] = { 3, 2, 3, 0 };
// Exercise
a += b;
// Verify
Assert::IsTrue(exp == a);
return;
}
//! Tests that subtracting two matrices works as intended
TEST_METHOD(Operator_Sub)
{
// Setup
Matrix4x4 a;
a[0] = { -9, 5, 6, 7 };
a[1] = { 1, 2, 5, 0 };
a[2] = { 2, -2, 7, 5 };
a[3] = { 3, 0, 3, 0 };
Matrix4x4 b;
b[0] = { -6, -0, -5, -0 };
b[1] = { -3, -0, -1, -1 };
b[2] = { -1, -7, -2, -7 };
b[3] = { -0, -2, -0, -0 };
Matrix4x4 exp; // Expected
exp[0] = { -3, 5, 11, 7 };
exp[1] = { 4, 2, 6, 1 };
exp[2] = { 3, 5, 9, 12 };
exp[3] = { 3, 2, 3, 0 };
// Exercise
Matrix4x4 result = a - b;
// Verify
Assert::IsTrue(exp == result);
return;
}
//! Tests that subtracting two matrices works as intended
TEST_METHOD(Operator_SubEuqals)
{
// Setup
Matrix4x4 a;
a[0] = { -9, 5, 6, 7 };
a[1] = { 1, 2, 5, 0 };
a[2] = { 2, -2, 7, 5 };
a[3] = { 3, 0, 3, 0 };
Matrix4x4 b;
b[0] = { -6, -0, -5, -0 };
b[1] = { -3, -0, -1, -1 };
b[2] = { -1, -7, -2, -7 };
b[3] = { -0, -2, -0, -0 };
Matrix4x4 exp; // Expected
exp[0] = { -3, 5, 11, 7 };
exp[1] = { 4, 2, 6, 1 };
exp[2] = { 3, 5, 9, 12 };
exp[3] = { 3, 2, 3, 0 };
// Exercise
a -= b;
// Verify
Assert::IsTrue(exp == a);
return;
}
// Tests that the multiplication operator for a double parameter works
TEST_METHOD(Operator_MultiplyDouble)
{
// Setup
Matrix4x4 a;
a[0] = { -9, 5, 6, 7 };
a[1] = { 1, 2, 5, 0 };
a[2] = { 2,-2, 7, 5 };
a[3] = { 3, 0, 3, 0 };
double s = LARGE_RAND_DOUBLE;
Matrix4x4 exp; // Expected
exp[0] = { -9*s, 5*s, 6*s, 7*s };
exp[1] = { 1*s, 2*s, 5*s, 0*s };
exp[2] = { 2*s,-2*s, 7*s, 5*s };
exp[3] = { 3*s, 0*s, 3*s, 0*s };
// Exercise
Matrix4x4 result = a * s;
// Verify
Assert::IsTrue(exp.Similar(result));
return;
}
// Tests that the multiplication operator for a double parameter works
TEST_METHOD(Operator_MultiplyEqualsDouble)
{
// Setup
Matrix4x4 a;
a[0] = { -9, 5, 6, 7 };
a[1] = { 1, 2, 5, 0 };
a[2] = { 2,-2, 7, 5 };
a[3] = { 3, 0, 3, 0 };
double s = LARGE_RAND_DOUBLE;
Matrix4x4 exp; // Expected
exp[0] = { -9*s, 5*s, 6*s, 7*s };
exp[1] = { 1*s, 2*s, 5*s, 0*s };
exp[2] = { 2*s,-2*s, 7*s, 5*s };
exp[3] = { 3*s, 0*s, 3*s, 0*s };
// Exercise
a *= s;
// Verify
Assert::IsTrue(exp.Similar(a));
return;
}
// Tests that the division operator for a double parameter works
TEST_METHOD(Operator_DivideDouble)
{
// Setup
Matrix4x4 a;
a[0] = { -9, 5, 6, 7 };
a[1] = { 1, 2, 5, 0 };
a[2] = { 2,-2, 7, 5 };
a[3] = { 3, 0, 3, 0 };
double s = LARGE_RAND_DOUBLE;
Matrix4x4 exp; // Expected
exp[0] = { -9/s, 5/s, 6/s, 7/s };
exp[1] = { 1/s, 2/s, 5/s, 0/s };
exp[2] = { 2/s,-2/s, 7/s, 5/s };
exp[3] = { 3/s, 0/s, 3/s, 0/s };
// Exercise
Matrix4x4 result = a / s;
// Verify
Assert::IsTrue(exp.Similar(result));
return;
}
// Tests that the division operator for a double parameter works
TEST_METHOD(Operator_DivideEqualsDouble)
{
// Setup
Matrix4x4 a;
a[0] = { -9, 5, 6, 7 };
a[1] = { 1, 2, 5, 0 };
a[2] = { 2,-2, 7, 5 };
a[3] = { 3, 0, 3, 0 };
double s = LARGE_RAND_DOUBLE;
Matrix4x4 exp; // Expected
exp[0] = { -9/s, 5/s, 6/s, 7/s };
exp[1] = { 1/s, 2/s, 5/s, 0/s };
exp[2] = { 2/s,-2/s, 7/s, 5/s };
exp[3] = { 3/s, 0/s, 3/s, 0/s };
// Exercise
a /= s;
// Verify
Assert::IsTrue(exp.Similar(a));
return;
}
// Tests that matrix division (multiplication with inverse) works
TEST_METHOD(Operator_DivideMatrix)
{
// Setup
Matrix4x4 a;
a[0] = { 0.0503814, 0.3314391, 0.9421304, 33 };
a[1] = { 0.4941404, 0.8115034, -0.3119095, 44 };
a[2] = { -0.8679211, 0.4812591, -0.1228928 , 55 };
a[3] = { 0, 0, 0, 1 };
Matrix4x4 b;
b[0] = { -0.3980391, -0.5301175, -0.7486925, 3 };
b[1] = { 0.3352839, 0.6756021, -0.6566175, 4 };
b[2] = { 0.8539026, -0.5123839, -0.0911762 , 5 };
b[3] = { 0, 0, 0, 1 };
Matrix4x4 expected = a * b.Inverse3x3();
// Just to be sure, but should already be set
expected.SetTranslationComponent(Vector3d(30, 40, 50));
// Exercise
Matrix4x4 actual = a / b;
// Verify
Assert::IsTrue(expected.Similar(actual));
return;
}
// Tests that matrix division (multiplication with inverse) works
TEST_METHOD(Operator_DivideEqualsMatrix)
{
// Setup
Matrix4x4 a;
a[0] = { 0.0503814, 0.3314391, 0.9421304, 33 };
a[1] = { 0.4941404, 0.8115034, -0.3119095, 44 };
a[2] = { -0.8679211, 0.4812591, -0.1228928 , 55 };
a[3] = { 0, 0, 0, 1 };
Matrix4x4 b;
b[0] = { -0.3980391, -0.5301175, -0.7486925, 3 };
b[1] = { 0.3352839, 0.6756021, -0.6566175, 4 };
b[2] = { 0.8539026, -0.5123839, -0.0911762 , 5 };
b[3] = { 0, 0, 0, 1 };
Matrix4x4 expected = a * b.Inverse3x3();
// Just to be sure, but should already be set
expected.SetTranslationComponent(Vector3d(30, 40, 50));
// Exercise
a /= b;
// Verify
Assert::IsTrue(expected.Similar(a));
return;
}
// Tests that Math::Similar() works -> true
TEST_METHOD(Similar_True)
{
Matrix4x4 a;
a[0] = { 1, 0, 0, 0 };
a[1] = { 0, 1, 0, 0 };
a[2] = { 0, 0, 1, 0 };
a[3] = { 0, 0, 0, 1 };
Matrix4x4 b;
b[0] = { 1, -9e-20, 2e-8, 9e-19 };
b[1] = { 12e-19, 1, -20e-15, -6.9e-29 };
b[2] = { -69e-25, 13e-23, 1, 4.301e-15 };
b[3] = { -23e-19, 23e-19, 25e-7, 1 };
Assert::IsTrue(a.Similar(b));
}
// Tests that Math::Similar() works -> false
TEST_METHOD(Similar_False)
{
Matrix4x4 a;
a[0] = { 1, 0, 0, 0 };
a[1] = { 0, 1, 0, 0 };
a[2] = { 0, 0, 1, 0 };
a[3] = { 0, 0, 0, 1 };
Matrix4x4 b;
b[0] = { 1, -9e-20, 2e-8, 9e-19 };
b[1] = { 12e-19, 1, -20e-15, 0.05 }; // <--
b[2] = { -69e-25, 13e-23, 1, 4.301e-15 };
b[3] = { -23e-19, 23e-19, 25e-7, 1 };
Assert::IsFalse(a.Similar(b));
}
// Tests if the equal operator (==) and not-equals operator (!=) work (equal: false)
TEST_METHOD(Operator_Equals_NotEquals_False)
{
Matrix4x4 a;
a[0] = { 0x0, 0x1, 0x2, 0x3 };
a[1] = { 0x4, 0x5, 0x6, 0x7 };
a[2] = { 0x8, 0x9, 0xA, 0xB };
a[3] = { 0xC, 0xD, 0xE, 0xF };
Matrix4x4 b;
b[3] = { 0xF ,0xD, 0xE, 0xC };
b[2] = { 0xB ,0x9, 0xA, 0x8 };
b[1] = { 0x7 ,0x5, 0x6, 0x4 };
b[0] = { 0x3 ,0x1, 0x2, 0x0 };
Assert::IsFalse(a == b);
Assert::IsTrue(a != b);
return;
}
// Tests if the equal operator (==) and not-equals operator (!=) work (equal: true)
TEST_METHOD(Operator_Equals_False)
{
Matrix4x4 a;
a[0] = { 0x0, 0x1, 0x2, 0x3 };
a[1] = { 0x4, 0x5, 0x6, 0x7 };
a[2] = { 0x8, 0x9, 0xA, 0xB };
a[3] = { 0xC, 0xD, 0xE, 0xF };
Matrix4x4 b;
b[0] = { 0x0, 0x1, 0x2, 0x3 };
b[1] = { 0x4, 0x5, 0x6, 0x7 };
b[2] = { 0x8, 0x9, 0xA, 0xB };
b[3] = { 0xC, 0xD, 0xE, 0xF };
Assert::IsTrue(a == b);
Assert::IsFalse(a != b);
return;
}
};
}

305
Test/Quaternion.cpp Normal file
View File

@@ -0,0 +1,305 @@
#include "CppUnitTest.h"
#include "../Eule/Quaternion.h"
#include "../Eule/Math.h"
#include "../_TestingUtilities/HandyMacros.h"
#include <random>
#include <sstream>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace TransformRelated
{
TEST_CLASS(_Quaternion)
{
private:
std::mt19937 rng;
public:
// Constructor
_Quaternion()
{
rng = std::mt19937((std::random_device())());
return;
}
// Tests that if constructed with the default constructor, that all values are 0 (but w should be 1)
TEST_METHOD(Default_Constructor_All_0)
{
Quaternion q;
Assert::IsTrue(Vector4d(0, 0, 0, 1) == q.GetRawValues());
return;
}
// Tests that getting and setting raw values works
TEST_METHOD(Can_Set_Get_Raw_Values)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
Vector4d v(
rng() % 90,
rng() % 90,
rng() % 90,
rng() % 90
);
Quaternion q(Vector4d(0, 0, 0, 0)); // Garbage values
q.SetRawValues(v);
Assert::IsTrue(v.Similar(q.GetRawValues()));
}
return;
}
// Tests that retreiving euler angles (without gimbal lock) results in the same values as put in
TEST_METHOD(To_Euler_From_Euler)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// Create vector
Vector3d eul(
rng() % 90,
rng() % 90,
rng() % 90
);
// Create quaternion from vector
Quaternion q(eul);
// Create debug output
std::wstringstream wss;
wss << std::endl
<< "Actual vals: " << q.ToEulerAngles() << std::endl
<< "Target vals: " << eul << std::endl;
// Assertion
Assert::IsTrue(eul.Similar(q.ToEulerAngles()), wss.str().c_str());
}
return;
}
// Tests that adding angles (0,0,0) does not modify the quaternion
TEST_METHOD(Add_Angles_0_Does_Nothing)
{
Quaternion a(Vector3d(0, -45, 45));
Quaternion b(Vector3d(0, 0, 0));
Assert::IsTrue(Vector3d(0, -45, 45).Similar((a * b).ToEulerAngles()));
return;
}
// Tests that subtracting angles (0,0,0) does not modify the quaternion
TEST_METHOD(Sub_Angles_0_Does_Nothing)
{
Quaternion a(Vector3d(0, -45, 45));
Quaternion b(Vector3d(0, 0, 0));
Assert::IsTrue(Vector3d(0, -45, 45).Similar((a / b).ToEulerAngles()));
return;
}
// Tests that subtracting by itself always returns (0,0,0)
TEST_METHOD(Sub_Itself_Is_0)
{
// Run test 100 times
for (std::size_t i = 0; i < 100; i++)
{
Quaternion a(Vector3d(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE));
Assert::IsTrue(Vector3d(0,0,0).Similar((a / a).ToEulerAngles()));
}
return;
}
// Tests that rotating a vector is equal to multiplying it with the inverted rotation matrix
TEST_METHOD(RotateVector_Equal_to_RotationMatrix)
{
// Run test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
Quaternion a(Vector3d(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE));
Vector3d point(32, 19, -14);
Assert::IsTrue((point * a.ToRotationMatrix()).Similar(a * point));
}
return;
}
// Tests that a *= b will result in the exact same outcome as a = a * b
TEST_METHOD(MultiplyEquals_Operator_Same_Result_As_Multiply_Operator)
{
// Run tests 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
Quaternion a(Vector3d(rng() % 360, rng() % 360, rng() % 360));
Quaternion b(Vector3d(rng() % 360, rng() % 360, rng() % 360));
// Exercise
Quaternion ref = a * b;
a *= b;
// Verify
Assert::IsTrue(a.GetRawValues().Similar(ref.GetRawValues()));
}
return;
}
// Tests that a /= b will result in the exact same outcome as a = a / b
TEST_METHOD(DivideEquals_Operator_Same_Result_As_Divide_Operator)
{
// Run tests 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
Quaternion a(Vector3d(rng() % 360, rng() % 360, rng() % 360));
Quaternion b(Vector3d(rng() % 360, rng() % 360, rng() % 360));
// Exercise
Quaternion ref = a / b;
a /= b;
// Verify
Assert::IsTrue(a.GetRawValues().Similar(ref.GetRawValues()));
}
return;
}
// Tests basic equals comparison -> true
TEST_METHOD(Basic_EqualsComparison_True)
{
// Run tests 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
Vector3d e(rng() % 360, rng() % 360, rng() % 360);
Quaternion a(e);
Quaternion b(e);
// Exercise and verify
Assert::IsTrue(a == b);
}
return;
}
// Tests basic equals comparison -> true
TEST_METHOD(Basic_EqualsComparison_False)
{
// Run tests 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
Vector3d ae(rng() % 360, rng() % 360, rng() % 360);
Vector3d be(rng() % 360, rng() % 360, rng() % 360);
// Abort if both vectors are equal
if (ae == be)
{
i--;
continue;
}
Quaternion a(ae);
Quaternion b(be);
// Exercise and verify
Assert::IsFalse(a == b);
}
return;
}
// Tests that different euler angles return true, if the angle is the same.
// Like [30, -10, 59] == [390, 350, 419]
TEST_METHOD(Equals_Comparison_Same_Rotation_Different_EulerAngles)
{
// Run tests 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
// Create random rotation
Vector3d ae(rng() % 360, rng() % 360, rng() % 360);
// add or subtract a random multiple of 360
#define keep_rot_change_values (360.0 * (double)(rng() % 20) * ((rng()%2) ? 1.0 : -1.0))
Vector3d be(ae.x + keep_rot_change_values, ae.y + keep_rot_change_values, ae.z + keep_rot_change_values);
#undef keep_rot_change_values
// Create quaternions
Quaternion a(ae);
Quaternion b(be);
// Exercise & Verify
// Create debug output
std::wstringstream wss;
wss << "ae: " << ae << std::endl
<< "be: " << be << std::endl
<< "a: " << a << std::endl
<< "b: " << b << std::endl;
// Assertion
Assert::IsTrue(a == b, wss.str().c_str());
}
return;
}
// Tests basic not-equals comparison -> false
TEST_METHOD(Basic_NotEqualsComparison_False)
{
// Run tests 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
Vector3d e(rng() % 360, rng() % 360, rng() % 360);
Quaternion a(e);
Quaternion b(e);
// Exercise and verify
Assert::IsFalse(a != b);
}
return;
}
// Tests basic not-equals comparison -> true
TEST_METHOD(Basic_NotEqualsComparison_True)
{
// Run tests 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// Setup
Vector3d ae(rng() % 360, rng() % 360, rng() % 360);
Vector3d be(rng() % 360, rng() % 360, rng() % 360);
// Abort if both vectors are equal
if (ae == be)
{
i--;
continue;
}
Quaternion a(ae);
Quaternion b(be);
// Exercise and verify
Assert::IsTrue(a != b);
}
return;
}
};
}

View File

@@ -0,0 +1,166 @@
#include "CppUnitTest.h"
#include "../Eule/TrapazoidalPrismCollider.h"
#include "../Eule/Quaternion.h"
#include "../_TestingUtilities/HandyMacros.h"
#include <random>
#include <array>
#include <sstream>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
using TPC = TrapazoidalPrismCollider;
namespace Colliders
{
TEST_CLASS(_TrapazoidalPrismCollider)
{
private:
std::mt19937 rng;
public:
// Constructor
_TrapazoidalPrismCollider()
{
rng = std::mt19937((std::random_device())());
return;
}
// Tests that all vertices can be set individually, and at once
TEST_METHOD(Can_Set_Each_Vertex)
{
// All vertex values are unique
TPC tpc;
tpc.SetVertex(TPC::FRONT | TPC::LEFT | TPC::BOTTOM, Vector3d(-1, -1, 1) * 1);
tpc.SetVertex(TPC::FRONT | TPC::LEFT | TPC::TOP, Vector3d(-1, 1, 1) * 2);
tpc.SetVertex(TPC::BACK | TPC::LEFT | TPC::BOTTOM, Vector3d(-1, -1, -1) * 3);
tpc.SetVertex(TPC::BACK | TPC::LEFT | TPC::TOP, Vector3d(-1, 1, -1) * 4);
tpc.SetVertex(TPC::FRONT | TPC::RIGHT | TPC::BOTTOM, Vector3d(1, -1, 1) * 5);
tpc.SetVertex(TPC::FRONT | TPC::RIGHT | TPC::TOP, Vector3d(1, 1, 1) * 6);
tpc.SetVertex(TPC::BACK | TPC::RIGHT | TPC::BOTTOM, Vector3d(1, -1, -1) * 7);
tpc.SetVertex(TPC::BACK | TPC::RIGHT | TPC::TOP, Vector3d(1, 1, -1) * 8);
Assert::IsTrue(tpc.GetVertex(TPC::FRONT | TPC::LEFT | TPC::BOTTOM) == (Vector3d(-1, -1, 1) * 1), L"FRONT|LEFT|BOTTOM");
Assert::IsTrue(tpc.GetVertex(TPC::FRONT | TPC::LEFT | TPC::TOP) == (Vector3d(-1, 1, 1) * 2), L"FRONT|LEFT|TOP");
Assert::IsTrue(tpc.GetVertex(TPC::BACK | TPC::LEFT | TPC::BOTTOM) == (Vector3d(-1, -1, -1) * 3), L"BACK|LEFT|BOTTOM");
Assert::IsTrue(tpc.GetVertex(TPC::BACK | TPC::LEFT | TPC::TOP) == (Vector3d(-1, 1, -1) * 4), L"BACK|LEFT|TOP");
Assert::IsTrue(tpc.GetVertex(TPC::FRONT | TPC::RIGHT | TPC::BOTTOM) == (Vector3d(1, -1, 1) * 5), L"FRONT|RIGHT|BOTTOM");
Assert::IsTrue(tpc.GetVertex(TPC::FRONT | TPC::RIGHT | TPC::TOP) == (Vector3d(1, 1, 1) * 6), L"FRONT|RIGHT|TOP");
Assert::IsTrue(tpc.GetVertex(TPC::BACK | TPC::RIGHT | TPC::BOTTOM) == (Vector3d(1, -1, -1) * 7), L"BACK|RIGHT|BOTTOM");
Assert::IsTrue(tpc.GetVertex(TPC::BACK | TPC::RIGHT | TPC::TOP) == (Vector3d(1, 1, -1) * 8), L"BACK|RIGHT|TOP");
return;
}
// Tests that points inside work.
// For this, we define a few points around [0,0,0] and check if they are contained.
// We then rotate the collider, and check again
// Gets repeated for every possible rotation with a min-distance per axis of 2 deg
TEST_METHOD(Points_Inside)
{
// Setup
// Define known-inside points
std::array<Vector3d, 9> knownInsides = {
Vector3d( 1,-1, 1),
Vector3d(-1,-1, 1),
Vector3d( 1, 1, 1),
Vector3d(-1, 1, 1),
Vector3d( 1,-1,-1),
Vector3d(-1,-1,-1),
Vector3d( 1, 1,-1),
Vector3d(-1, 1,-1),
Vector3d( 0, 0, 0),
};
// Create collider, a cube of size 10^3 around the center
TPC tpc;
// Exercise
// Now check that these points are inside for all these possible angles
#ifndef _DEBUG
constexpr double stepSize = 2;
#else
constexpr double stepSize = 32;
#endif
for (double theta = 0; theta < 360.01; theta += stepSize)
for (double phi = 0; phi < 360.01; phi += 2)
for (double alpha = 0; alpha < 360.01; alpha += stepSize)
{
// Rotate box
tpc.SetVertex(TPC::FRONT | TPC::LEFT | TPC::BOTTOM, Quaternion({theta, phi, alpha}) * (Vector3d(-1, -1, 1) * 10));
tpc.SetVertex(TPC::FRONT | TPC::LEFT | TPC::TOP, Quaternion({theta, phi, alpha}) * (Vector3d(-1, 1, 1) * 10));
tpc.SetVertex(TPC::BACK | TPC::LEFT | TPC::BOTTOM, Quaternion({theta, phi, alpha}) * (Vector3d(-1, -1, -1) * 10));
tpc.SetVertex(TPC::BACK | TPC::LEFT | TPC::TOP, Quaternion({theta, phi, alpha}) * (Vector3d(-1, 1, -1) * 10));
tpc.SetVertex(TPC::FRONT | TPC::RIGHT | TPC::BOTTOM, Quaternion({theta, phi, alpha}) * (Vector3d(1, -1, 1) * 10));
tpc.SetVertex(TPC::FRONT | TPC::RIGHT | TPC::TOP, Quaternion({theta, phi, alpha}) * (Vector3d(1, 1, 1) * 10));
tpc.SetVertex(TPC::BACK | TPC::RIGHT | TPC::BOTTOM, Quaternion({theta, phi, alpha}) * (Vector3d(1, -1, -1) * 10));
tpc.SetVertex(TPC::BACK | TPC::RIGHT | TPC::TOP, Quaternion({theta, phi, alpha}) * (Vector3d(1, 1, -1) * 10));
// Verify
// Verify that all are inside
for (const Vector3d& v : knownInsides)
Assert::IsTrue(tpc.Contains(v));
}
return;
}
// Tests that points outside work.
// For this, we define a few points that are definitely outside for various reasons and check if they are not contained.
// We then rotate the collider, and check again
// Gets repeated for every possible rotation with a min-distance per axis of 2 deg
TEST_METHOD(Points_Outside)
{
// Setup
// Define known-inside points
std::array<Vector3d, 14> knownOutsides = {
Vector3d(-199, 0, 0),
Vector3d(0, -199, 0),
Vector3d(0, 0, -199),
Vector3d(199, 0, 0),
Vector3d(0, 199, 0),
Vector3d(0, 0, 199),
Vector3d( 20, -20, 0),
Vector3d(50, 50, 50),
Vector3d(50, -50, 0),
Vector3d( 0, 0, 29),
Vector3d( 2, 1, -18),
Vector3d( -1, 29, -1),
Vector3d( 0, -50, -50),
Vector3d( -50, -50, -50)
};
// Create collider, a cube of size 10^3 around the center
TPC tpc;
// Exercise
// Now check that these points are inside for all these possible angles
#ifndef _DEBUG
constexpr double stepSize = 2;
#else
constexpr double stepSize = 32;
#endif
for (double theta = 0; theta < 360.01; theta += stepSize)
for (double phi = 0; phi < 360.01; phi += 2)
for (double alpha = 0; alpha < 360.01; alpha += stepSize)
{
// Rotate box
tpc.SetVertex(TPC::FRONT | TPC::LEFT | TPC::BOTTOM, Quaternion({ theta, phi, alpha }) * (Vector3d(-1, -1, 1) * 10));
tpc.SetVertex(TPC::FRONT | TPC::LEFT | TPC::TOP, Quaternion({ theta, phi, alpha }) * (Vector3d(-1, 1, 1) * 10));
tpc.SetVertex(TPC::BACK | TPC::LEFT | TPC::BOTTOM, Quaternion({ theta, phi, alpha }) * (Vector3d(-1, -1, -1) * 10));
tpc.SetVertex(TPC::BACK | TPC::LEFT | TPC::TOP, Quaternion({ theta, phi, alpha }) * (Vector3d(-1, 1, -1) * 10));
tpc.SetVertex(TPC::FRONT | TPC::RIGHT | TPC::BOTTOM, Quaternion({ theta, phi, alpha }) * (Vector3d(1, -1, 1) * 10));
tpc.SetVertex(TPC::FRONT | TPC::RIGHT | TPC::TOP, Quaternion({ theta, phi, alpha }) * (Vector3d(1, 1, 1) * 10));
tpc.SetVertex(TPC::BACK | TPC::RIGHT | TPC::BOTTOM, Quaternion({ theta, phi, alpha }) * (Vector3d(1, -1, -1) * 10));
tpc.SetVertex(TPC::BACK | TPC::RIGHT | TPC::TOP, Quaternion({ theta, phi, alpha }) * (Vector3d(1, 1, -1) * 10));
// Verify
// Verify that all are inside
for (const Vector3d& v : knownOutsides)
Assert::IsFalse(tpc.Contains(v));
}
return;
}
};
}

934
Test/Vector2.cpp Normal file
View File

@@ -0,0 +1,934 @@
#include "CppUnitTest.h"
#include "../Eule/Vector2.h"
#include "../Eule/Math.h"
#include "../_TestingUtilities/HandyMacros.h"
#include <random>
#include <sstream>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace Vectors
{
TEST_CLASS(_Vector2)
{
private:
std::mt19937 rng;
public:
// Constructor
_Vector2()
{
rng = std::mt19937((std::random_device())());
return;
}
// Tests if all values are 0 after initialization via default constructor
TEST_METHOD(New_Vector_All_0)
{
Vector2d v2;
Assert::AreEqual(0.0, v2.x);
Assert::AreEqual(0.0, v2.y);
return;
}
// Tests if values can be set via the constructor
TEST_METHOD(Can_Set_Values_Constructor)
{
Vector2d v2(69, 32);
Assert::AreEqual(69.0, v2.x);
Assert::AreEqual(32.0, v2.y);
return;
}
// Tests if values can be set via letters
TEST_METHOD(Can_Set_Values_Letters)
{
Vector2d v2;
v2.x = 69;
v2.y = 32;
Assert::AreEqual(69.0, v2.x);
Assert::AreEqual(32.0, v2.y);
return;
}
// Tests if values can be set via array descriptors
TEST_METHOD(Can_Set_Values_ArrayDescriptor)
{
Vector2d v2;
v2[0] = 69;
v2[1] = 32;
Assert::AreEqual(69.0, v2.x);
Assert::AreEqual(32.0, v2.y);
return;
}
// Tests if values can be set via an initializer list
TEST_METHOD(Can_Set_Values_InitializerList)
{
Vector2d v2 = {69, 32};
Assert::AreEqual(69.0, v2.x);
Assert::AreEqual(32.0, v2.y);
return;
}
// Tests for vectors copied via the copy constructor to have the same values
TEST_METHOD(Copy_Constructor_Same_Values)
{
Vector2d a(69, 32);
Vector2d b(a);
Assert::AreEqual(a.x, b.x);
Assert::AreEqual(a.y, b.y);
return;
}
// Tests for vectors copied via the equals operator to have the same values
TEST_METHOD(Operator_Equals_Same_Values)
{
Vector2d a(69, 32);
Vector2d b = a;
Assert::AreEqual(a.x, b.x);
Assert::AreEqual(a.y, b.y);
return;
}
// Tests for vectors copied via the copy constructor to be modifyable without modifying the original object
TEST_METHOD(Copy_Constructor_Independent)
{
Vector2d a(69, 32);
Vector2d b(a);
b.x = 169;
b.y = 132;
Assert::AreEqual(69.0, a.x);
Assert::AreEqual(32.0, a.y);
Assert::AreEqual(169.0, b.x);
Assert::AreEqual(132.0, b.y);
return;
}
// Tests for vectors copied via the equals operator to be modifyable without modifying the original object
TEST_METHOD(Operator_Equals_Independent)
{
Vector2d a(69, 32);
Vector2d b = a;
b.x = 169;
b.y = 132;
Assert::AreEqual(69.0, a.x);
Assert::AreEqual(32.0, a.y);
Assert::AreEqual(169.0, b.x);
Assert::AreEqual(132.0, b.y);
return;
}
// Tests if the dot product between two vectors angled 90 degrees from one another is 0. It should by definition be 0!
// Dot products are commutative, so we'll check both directions.
TEST_METHOD(DotProduct_90deg)
{
// Test 1000 times
for (std::size_t i = 0; i < 100; i++)
{
// The length of the vectors should not matter. Only the angle should.
// Let's test that!
Vector2d a = Vector2d(1, 0) * (rng() % 6969 + 1.0);
Vector2d b = Vector2d(0, 1) * (rng() % 6969 + 1.0);
std::wstringstream wss;
wss << a << L" DOT " << b << L" = " << a.DotProduct(b) << std::endl;
Assert::AreEqual(0.0, a.DotProduct(b), wss.str().c_str());
Assert::AreEqual(0.0, b.DotProduct(a), wss.str().c_str());
}
return;
}
// Test if the dot product is positive for two vectors angled less than 90 degrees from another
// Dot products are commutative, so we'll check both directions.
TEST_METHOD(DotProduct_LessThan90deg)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// The length of the vectors should not matter. Only the angle should.
// Let's test that!
Vector2d a = Vector2d(1, 1.0 / (rng() % 100)) * (rng() % 6969 + 1.0); // Don't allow the scalar to become 0
Vector2d b = Vector2d(1.0 / (rng() % 100), 1) * (rng() % 6969 + 1.0);
std::wstringstream wss;
wss << a << L" DOT " << b << L" = " << a.DotProduct(b) << std::endl;
Assert::IsTrue(a.DotProduct(b) > 0, wss.str().c_str());
Assert::IsTrue(b.DotProduct(a) > 0, wss.str().c_str());
}
return;
}
// Test if the dot product is negative for two vectors angled greater than 90 degrees from another
// Dot products are commutative, so we'll check both directions.
TEST_METHOD(DotProduct_GreaterThan90deg)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
// The length of the vectors should not matter. Only the angle should.
// Let's test that!
Vector2d a = Vector2d(1, -1.0 / (rng() % 100)) * (rng() % 6969 + 1.0); // Don't allow the scalar to become 0
Vector2d b = Vector2d(-1.0 / (rng() % 100), 1) * (rng() % 6969 + 1.0);
std::wstringstream wss;
wss << a << L" DOT " << b << L" = " << a.DotProduct(b) << std::endl;
Assert::IsTrue(a.DotProduct(b) < 0, wss.str().c_str());
Assert::IsTrue(b.DotProduct(a) < 0, wss.str().c_str());
}
return;
}
// Tests that the dot product is correct for a known value
TEST_METHOD(DotProduct_Oracle)
{
// Setup
Vector2d a(-99, 199);
Vector2d b(18, -1);
// Exercise
const double dot = a.DotProduct(b);
// Verify
Assert::AreEqual(-1981.0, dot);
return;
}
// Quick and dirty check if the useless int-method is working
TEST_METHOD(DotProduct_Dirty_Int)
{
Vector2i a;
Vector2i b;
std::wstringstream wss;
// 90 deg
a = {0, 10};
b = {10, 0};
wss.str(L"");
wss << a << L" DOT " << b << L" = " << a.DotProduct(b) << std::endl;
Assert::AreEqual(0.0, a.DotProduct(b), wss.str().c_str());
Assert::AreEqual(0.0, b.DotProduct(a), wss.str().c_str());
// < 90 deg
a = { 7, 10 };
b = { 10, 1 };
wss.str(L"");
wss << a << L" DOT " << b << L" = " << a.DotProduct(b) << std::endl;
Assert::IsTrue(a.DotProduct(b) > 0.0, wss.str().c_str());
Assert::IsTrue(b.DotProduct(a) > 0.0, wss.str().c_str());
// > 90 deg
a = { -3, 10 };
b = { 10, -4 };
wss.str(L"");
wss << a << L" DOT " << b << L" = " << a.DotProduct(b) << std::endl;
Assert::IsTrue(a.DotProduct(b) < 0.0, wss.str().c_str());
Assert::IsTrue(b.DotProduct(a) < 0.0, wss.str().c_str());
return;
}
// Tests if the cross product of two vectors of the exact opposite direction is 0
TEST_METHOD(CrossProduct_Opposite_Direction)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE / 1000.0;
double y = LARGE_RAND_DOUBLE / 1000.0;
// Vector length should not matter, so randomize it
// In this case, they are allowed to be of length 0
// Don't scale it up too much to avoid failure due to floating point inaccuracy
Vector2d a = Vector2d( x, y) * (LARGE_RAND_DOUBLE / 1000.0);
Vector2d b = Vector2d(-x, -y) * (LARGE_RAND_DOUBLE / 1000.0);
std::wstringstream wss;
wss << a << L" CROSS " << b << L" = " << a.CrossProduct(b) << std::endl;
Assert::IsTrue(Math::Similar(a.CrossProduct(b), 0.0, 10), wss.str().c_str());
}
return;
}
// Tests if the cross product of two vectors of the exact same direction is 0
TEST_METHOD(CrossProduct_Same_Direction)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE / 1000.0;
double y = LARGE_RAND_DOUBLE / 1000.0;
// Vector length should not matter, so randomize it
// In this case, they are allowed to be of length 0
// Don't scale it up too much to avoid failure due to floating point inaccuracy
Vector2d a = Vector2d(x, y) * (LARGE_RAND_DOUBLE / 1000.0);
Vector2d b = Vector2d(x, y) * (LARGE_RAND_DOUBLE / 1000.0);
std::wstringstream wss;
wss << a << L" CROSS " << b << L" = " << a.CrossProduct(b) << std::endl;
Assert::IsTrue(Math::Similar(a.CrossProduct(b), 0.0, 10), wss.str().c_str());
}
return;
}
// Tests for the cross product to be positive, if vector b is to the left of a
TEST_METHOD(CrossProduct_BToTheLeft)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
if (x == 0) x++;
if (y == 0) y++;
// Vector length should not matter, so randomize it
Vector2d a = Vector2d(x, y) * (rng() % 6969 + 1.0);
Vector2d b = Vector2d(x - (rng() % 6969 + 1.0), y) * (rng() % 6969 + 1.0);
std::wstringstream wss;
wss << a << L" CROSS " << b << L" = " << a.CrossProduct(b) << std::endl;
Assert::IsTrue(a.CrossProduct(b) > 0, wss.str().c_str());
}
return;
}
// Tests for the cross product to be negative, if vector b is to the left of a
TEST_METHOD(CrossProduct_BToTheRight)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
if (x == 0) x++;
if (y == 0) y++;
// Vector length should not matter, so randomize it
Vector2d a = Vector2d(x, y) * (rng() % 6969 + 1.0);
Vector2d b = Vector2d(x + (rng() % 6969 + 1.0), y) * (rng() % 6969 + 1.0);
std::wstringstream wss;
wss << a << L" CROSS " << b << L" = " << a.CrossProduct(b) << std::endl;
Assert::IsTrue(a.CrossProduct(b) < 0, wss.str().c_str());
}
return;
}
// Quick and dirty check if the useless int-method is working
TEST_METHOD(CrossProduct_Dirty_Int)
{
Vector2i a;
Vector2i b;
std::wstringstream wss;
// Same direction
a = { 10, 0 };
b = { 10, 0 };
wss.str(L"");
wss << a << L" CROSS " << b << L" = " << a.CrossProduct(b) << std::endl;
Assert::AreEqual(0.0, a.CrossProduct(b), wss.str().c_str());
Assert::AreEqual(0.0, b.CrossProduct(a), wss.str().c_str());
// Opposite direction
a = { -10, 0 };
b = { 10, 0 };
wss.str(L"");
wss << a << L" CROSS " << b << L" = " << a.CrossProduct(b) << std::endl;
Assert::AreEqual(0.0, a.CrossProduct(b), wss.str().c_str());
Assert::AreEqual(0.0, b.CrossProduct(a), wss.str().c_str());
// B to the left
a = { 0, 10 };
b = { -5, 10 };
wss.str(L"");
wss << a << L" CROSS " << b << L" = " << a.CrossProduct(b) << std::endl;
Assert::IsTrue(a.CrossProduct(b) > 0.0, wss.str().c_str());
// B to the right
a = { 0, 10 };
b = { 17, 10 };
wss.str(L"");
wss << a << L" CROSS " << b << L" = " << a.CrossProduct(b) << std::endl;
Assert::IsTrue(a.CrossProduct(b) < 0.0, wss.str().c_str());
return;
}
// Tests the SqrMagnitude method to work as expected with random numbers
TEST_METHOD(SqrMagnitude)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = (double)(rng() % 1000) - 500.0;
double y = (double)(rng() % 1000) - 500.0;
double expected = x*x + y*y;
Assert::AreEqual(expected, Vector2d(x, y).SqrMagnitude());
}
return;
}
// Checks if the int method is working
TEST_METHOD(SqrMagnitude_Int)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
int x = LARGE_RAND_INT;
int y = LARGE_RAND_INT;
int expected = x*x + y*y;
Assert::IsTrue(Math::Similar((double)expected, Vector2i(x, y).SqrMagnitude()));
}
return;
}
// Tests for the length of the vector (0,0) being 0
TEST_METHOD(Magnitude_Is_0_On_Vec0)
{
Assert::AreEqual(0.0, Vector2d(0, 0).Magnitude());
return;
}
// Tests for a vector of a known length to actually return that
TEST_METHOD(Magnitude_One_Axis_X)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = (double)(rng() % 1000) - 500.0;
Vector2d vec(x, 0);
Assert::IsTrue(Math::Similar(abs(x), vec.Magnitude()));
}
return;
}
// Tests for a vector of a known length to actually return that
TEST_METHOD(Magnitude_One_Axis_Y)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double y = (double)(rng() % 1000) - 500.0;
Vector2d vec(0, y);
Assert::IsTrue(Math::Similar(abs(y), vec.Magnitude()));
}
return;
}
// Tests for a known result
TEST_METHOD(Magnitude)
{
// Ya'll got more of 'dem digits?
Assert::AreEqual(204.02205763103165736538358032703399658203125, Vector2d(192, -69).Magnitude());
return;
}
// Tests for expected lerp result 0.00
TEST_METHOD(Lerp_000)
{
Vector2d a(100, 1000);
Vector2d b(200, 4000);
Vector2d res = a.Lerp(b, 0.00);
std::wstringstream wss;
wss << res;
Assert::IsTrue(a == res, wss.str().c_str());
return;
}
// Tests for expected lerp result 0.25
TEST_METHOD(Lerp_025)
{
Vector2d a(100, 1000);
Vector2d b(200, 4000);
Vector2d res = a.Lerp(b, 0.25);
std::wstringstream wss;
wss << res;
Assert::IsTrue(Vector2d(125, 1750) == res, wss.str().c_str());
return;
}
// Tests for expected lerp result 0.50
TEST_METHOD(Lerp_050)
{
Vector2d a(100, 1000);
Vector2d b(200, 4000);
Vector2d res = a.Lerp(b, 0.50);
std::wstringstream wss;
wss << res;
Assert::IsTrue(Vector2d(150, 2500) == res, wss.str().c_str());
return;
}
// Tests for expected lerp result 0.75
TEST_METHOD(Lerp_075)
{
Vector2d a(100, 1000);
Vector2d b(200, 4000);
Vector2d res = a.Lerp(b, 0.75);
std::wstringstream wss;
wss << res;
Assert::IsTrue(Vector2d(175, 3250) == res, wss.str().c_str());
return;
}
// Tests for expected lerp result 1.00
TEST_METHOD(Lerp_100)
{
Vector2d a(100, 1000);
Vector2d b(200, 4000);
Vector2d res = a.Lerp(b, 1.00);
std::wstringstream wss;
wss << res;
Assert::IsTrue(b == res, wss.str().c_str());
return;
}
// Tests lerpself
TEST_METHOD(LerpSelf)
{
Vector2d a(100, 1000);
Vector2d b(200, 4000);
a.LerpSelf(b, 0.75);
std::wstringstream wss;
wss << a;
Assert::IsTrue(Vector2d(175, 3250) == a, wss.str().c_str());
return;
}
// Tests if an input vector of length 0 is handled correctly by the normalize method
TEST_METHOD(Normalize_Length_Before_Is_0)
{
Vector2d vec(0, 0);
Assert::AreEqual(0.0, vec.Normalize().Magnitude());
return;
}
// Tests for any normalized vector to be of length 1
TEST_METHOD(Normalize_Length_Is_1)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
if (x == 0) x++;
if (y == 0) y++;
Vector2d vec(x, y);
std::wstringstream wss;
wss << vec;
Assert::IsTrue(Math::Similar(vec.Normalize().Magnitude(), 1.0), wss.str().c_str()); // Account for floating point inaccuracy
}
return;
}
// Tests the normalize method with known values
TEST_METHOD(Normalize_Oracle)
{
// Setup
Vector2d v(3.2, -5.3);
// Exercise
v.NormalizeSelf();
// Verify
Vector2d expected(0.51686909903, -0.85606444527);
Assert::IsTrue(v.Similar(expected));
}
// Tests for a normalized vector to still point in the exact same direction
TEST_METHOD(Normalize_Direction_Stays_Unaffected)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
Vector2d vec(x, y);
// Prevent a vector of length 0 going in
if (vec.SqrMagnitude() == 0)
vec.x++;
Vector2d vec_n(x, y);
vec_n = vec_n.Normalize();
std::wstringstream wss;
wss << vec << L" | " << vec_n;
// Both vectors should still point in the same direction!
Assert::IsTrue(
(vec.DotProduct(vec_n) > 0) && // Roughly same direction
(Math::Similar(vec_n.CrossProduct(vec), 0.0)), // Both vectors align
wss.str().c_str());
}
return;
}
// Kinda dumb method, but ok lol
// DON'T NORMALIZE INT-VECTORS WHAT IS WRONG WITH YOU
TEST_METHOD(Normalized_Int_Vector_Is_0)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
int x = LARGE_RAND_INT;
int y = LARGE_RAND_INT;
Vector2i vec(x, y);
vec.NormalizeSelf();
std::wstringstream wss;
wss << vec;
Assert::AreEqual(0.0, vec.Magnitude(), wss.str().c_str());
}
}
// Tests that NormalizeSelf() results in the same as Normalize()
TEST_METHOD(NormalizeSelf_IsSameAs_Normalize)
{
// Run test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
Vector2d vec(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE);
Vector2d nVec = vec.Normalize();
vec.NormalizeSelf();
Assert::IsTrue(nVec == vec);
}
return;
}
// Tests for the VectorScale() method to work
TEST_METHOD(VectorScale)
{
// Run test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
const double ax = LARGE_RAND_DOUBLE;
const double ay = LARGE_RAND_DOUBLE;
const double bx = LARGE_RAND_DOUBLE;
const double by = LARGE_RAND_DOUBLE;
Vector2d a(ax, ay);
Vector2d b(bx, by);
Vector2d target(
ax * bx,
ay * by
);
Assert::IsTrue(a.VectorScale(b) == target);
}
return;
}
// Tests for operator- (unary) to work
TEST_METHOD(Operator_Unary_Negative)
{
Vector2d v(29, -5);
Assert::IsTrue(Vector2d(-29, 5) == -v);
return;
}
// Tests for operator+ to work as expected
TEST_METHOD(Operator_Add)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
Vector2d a(ax, ay);
Vector2d b(bx, by);
Assert::IsTrue(Vector2d(ax+bx, ay+by) == a+b);
}
return;
}
// Tests for operator+= to work as expected
TEST_METHOD(Operator_Add_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
Vector2d a(ax, ay);
a += Vector2d(bx, by);
Assert::IsTrue(Vector2d(ax + bx, ay + by) == a);
}
return;
}
// Tests for operator- to work as expected
TEST_METHOD(Operator_Sub)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
Vector2d a(ax, ay);
Vector2d b(bx, by);
Assert::IsTrue(Vector2d(ax - bx, ay - by) == a - b);
}
return;
}
// Tests for operator-= to work as expected
TEST_METHOD(Operator_Sub_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
Vector2d a(ax, ay);
a -= Vector2d(bx, by);
Assert::IsTrue(Vector2d(ax - bx, ay - by) == a);
}
return;
}
// Tests for operator* to work as expected
TEST_METHOD(Operator_Mult)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double scalar = LARGE_RAND_DOUBLE;
Vector2d a(x, y);
Assert::IsTrue(Vector2d(x * scalar, y * scalar) == a * scalar);
}
return;
}
// Tests for operator*= to work as expected
TEST_METHOD(Operator_Mult_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double scalar = LARGE_RAND_DOUBLE;
Vector2d a(x, y);
a *= scalar;
Assert::IsTrue(Vector2d(x * scalar, y * scalar) == a);
}
return;
}
// Tests for operator/ to work as expected
TEST_METHOD(Operator_Div)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double scalar = LARGE_RAND_DOUBLE;
Vector2d a(x, y);
Assert::IsTrue(Vector2d(x / scalar, y / scalar) == a / scalar);
}
return;
}
// Tests for operator/= to work as expected
TEST_METHOD(Operator_Div_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double scalar = LARGE_RAND_DOUBLE;
Vector2d a(x, y);
a /= scalar;
Assert::IsTrue(Vector2d(x / scalar, y / scalar) == a);
}
return;
}
// Tests for operator== to work as expected
TEST_METHOD(Operator_Compare_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = (rng() % 10) - 5;
double ay = (rng() % 10) - 5;
double bx = (rng() % 10) - 5;
double by = (rng() % 10) - 5;
Vector2d a(ax, ay);
Vector2d b(bx, by);
Assert::IsTrue(
((ax == bx) && (ay == by)) ==
(a == b)
);
}
return;
}
// Tests for operator!= to work as expected
TEST_METHOD(Operator_Not_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = (rng() % 10) - 5;
double ay = (rng() % 10) - 5;
double bx = (rng() % 10) - 5;
double by = (rng() % 10) - 5;
Vector2d a(ax, ay);
Vector2d b(bx, by);
Assert::IsTrue(
((ax != bx) || (ay != by)) ==
(a != b)
);
}
return;
}
// Tests loose comparison via Vector2d::Similar -> true
TEST_METHOD(Similar_True)
{
Assert::IsTrue(
Vector2d(0.00000000000000000000001, -6.6666666666666666666666666666).Similar(
Vector2d(0, -6.666666667)
));
return;
}
// Tests loose comparison via Vector2d::Similar -> false
TEST_METHOD(Similar_False)
{
Assert::IsFalse(
Vector2d(0.00000000000000000000001, -6.6666666666666666666666666666).Similar(
Vector2d(0.1, -6.7)
));
return;
}
// Tests that the move constructor works
TEST_METHOD(Move_Constructor)
{
Vector2d a(1, 2);
Vector2d b(std::move(a));
Assert::AreEqual(b.x, 1.0);
Assert::AreEqual(b.y, 2.0);
return;
}
// Tests that the move operator works
TEST_METHOD(Move_Operator)
{
Vector2d a(1, 2);
Vector2d b = std::move(a);
Assert::AreEqual(b.x, 1.0);
Assert::AreEqual(b.y, 2.0);
return;
}
};
}

1553
Test/Vector3.cpp Normal file

File diff suppressed because it is too large Load Diff

824
Test/Vector4.cpp Normal file
View File

@@ -0,0 +1,824 @@
#include "CppUnitTest.h"
#include "../Eule/Vector4.h"
#include "../Eule/Matrix4x4.h"
#include "../Eule/Math.h"
#include "../_TestingUtilities/HandyMacros.h"
#include <random>
#include <sstream>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace Vectors
{
TEST_CLASS(_Vector4)
{
private:
std::mt19937 rng;
public:
// Constructor
_Vector4()
{
rng = std::mt19937((std::random_device())());
return;
}
// Tests if all values are 0 after initialization via default constructor
TEST_METHOD(New_Vector_All_0)
{
Vector4d v4;
Assert::AreEqual(0.0, v4.x);
Assert::AreEqual(0.0, v4.y);
Assert::AreEqual(0.0, v4.z);
Assert::AreEqual(0.0, v4.w);
return;
}
// Tests if values can be set via the constructor
TEST_METHOD(Can_Set_Values_Constructor)
{
Vector4d v4(69, 32, 16, 10);
Assert::AreEqual(69.0, v4.x);
Assert::AreEqual(32.0, v4.y);
Assert::AreEqual(16.0, v4.z);
Assert::AreEqual(10.0, v4.w);
return;
}
// Tests if values can be set via letters
TEST_METHOD(Can_Set_Values_Letters)
{
Vector4d v4;
v4.x = 69;
v4.y = 32;
v4.z = 16;
v4.w = 10;
Assert::AreEqual(69.0, v4.x);
Assert::AreEqual(32.0, v4.y);
Assert::AreEqual(16.0, v4.z);
Assert::AreEqual(10.0, v4.w);
return;
}
// Tests if values can be set via array descriptors
TEST_METHOD(Can_Set_Values_ArrayDescriptor)
{
Vector4d v4;
v4[0] = 69;
v4[1] = 32;
v4[2] = 16;
v4[3] = 10;
Assert::AreEqual(69.0, v4.x);
Assert::AreEqual(32.0, v4.y);
Assert::AreEqual(16.0, v4.z);
Assert::AreEqual(10.0, v4.w);
return;
}
// Tests if values can be set via an initializer list
TEST_METHOD(Can_Set_Values_InitializerList)
{
Vector4d v4 = { 69, 32, 16, 10 };
Assert::AreEqual(69.0, v4.x);
Assert::AreEqual(32.0, v4.y);
Assert::AreEqual(16.0, v4.z);
Assert::AreEqual(10.0, v4.w);
return;
}
// Tests for vectors copied via the copy constructor to have the same values
TEST_METHOD(Copy_Constructor_Same_Values)
{
Vector4d a(69, 32, 16, 10);
Vector4d b(a);
Assert::AreEqual(69.0, b.x);
Assert::AreEqual(32.0, b.y);
Assert::AreEqual(16.0, b.z);
Assert::AreEqual(10.0, b.w);
return;
}
// Tests for vectors copied via the equals operator to have the same values
TEST_METHOD(Operator_Equals_Same_Values)
{
Vector4d a(69, 32, 16, 10);
Vector4d b = a;
Assert::AreEqual(69.0, b.x);
Assert::AreEqual(32.0, b.y);
Assert::AreEqual(16.0, b.z);
Assert::AreEqual(10.0, b.w);
return;
}
// Tests for vectors copied via the copy constructor to be modifyable without modifying the original object
TEST_METHOD(Copy_Constructor_Independent)
{
Vector4d a(69, 32, 16, 10);
Vector4d b(a);
b.x = 169;
b.y = 132;
b.z = 116;
b.w = 110;
Assert::AreEqual(69.0, a.x);
Assert::AreEqual(32.0, a.y);
Assert::AreEqual(16.0, a.z);
Assert::AreEqual(10.0, a.w);
Assert::AreEqual(169.0, b.x);
Assert::AreEqual(132.0, b.y);
Assert::AreEqual(116.0, b.z);
Assert::AreEqual(110.0, b.w);
return;
}
// Tests for vectors copied via the equals operator to be modifyable without modifying the original object
TEST_METHOD(Operator_Equals_Independent)
{
Vector4d a(69, 32, 16, 10);
Vector4d b = a;
b.x = 169;
b.y = 132;
b.z = 116;
b.w = 110;
Assert::AreEqual(69.0, a.x);
Assert::AreEqual(32.0, a.y);
Assert::AreEqual(16.0, a.z);
Assert::AreEqual(10.0, a.w);
Assert::AreEqual(169.0, b.x);
Assert::AreEqual(132.0, b.y);
Assert::AreEqual(116.0, b.z);
Assert::AreEqual(110.0, b.w);
return;
}
// Tests the SqrMagnitude method to work as expected with random numbers
TEST_METHOD(SqrMagnitude)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double z = LARGE_RAND_DOUBLE;
double w = LARGE_RAND_DOUBLE;
double expected = x*x + y*y + z*z + w*w;
Assert::AreEqual(expected, Vector4d(x, y, z, w).SqrMagnitude());
}
return;
}
// Tests for the length of the vector (0,0,0,0) being 0
TEST_METHOD(Magnitude_Is_0_On_Vec0)
{
Assert::AreEqual(0.0, Vector4d(0, 0, 0, 0).Magnitude());
return;
}
// Tests for a vector of a known length to actually return that
TEST_METHOD(Magnitude_One_Axis_X)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
Vector4d vec(x, 0, 0, 0);
Assert::AreEqual(abs(x), vec.Magnitude());
}
return;
}
// Tests for a vector of a known length to actually return that
TEST_METHOD(Magnitude_One_Axis_Y)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double y = LARGE_RAND_DOUBLE;
Vector4d vec(0, y, 0, 0);
Assert::AreEqual(abs(y), vec.Magnitude());
}
return;
}
// Tests for a vector of a known length to actually return that
TEST_METHOD(Magnitude_One_Axis_Z)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double z = LARGE_RAND_DOUBLE;
Vector4d vec(0, 0, z, 0);
Assert::AreEqual(abs(z), vec.Magnitude());
}
return;
}
// Tests for a vector of a known length to actually return that
TEST_METHOD(Magnitude_One_Axis_W)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double w = LARGE_RAND_DOUBLE;
Vector4d vec(0, 0, 0, w);
Assert::AreEqual(abs(w), vec.Magnitude());
}
return;
}
// Tests for a known result
TEST_METHOD(Magnitude)
{
// Ya'll got more of 'dem digits?
Assert::AreEqual(78.5746530377322045524124405346810817718505859375, Vector4d(-23.76, 15.82, 66.75, 30.06).Magnitude());
return;
}
// Tests for expected lerp result 0.00
TEST_METHOD(Lerp_000)
{
Vector4d a(100, 1000, 10, -200);
Vector4d b(200, 4000, 100, 200);
Vector4d res = a.Lerp(b, 0.00);
std::wstringstream wss;
wss << res;
Assert::IsTrue(a == res, wss.str().c_str());
return;
}
// Tests for expected lerp result 0.25
TEST_METHOD(Lerp_025)
{
Vector4d a(100, 1000, 10, -200);
Vector4d b(200, 4000, 100, 200);
Vector4d res = a.Lerp(b, 0.25);
std::wstringstream wss;
wss << res;
Assert::IsTrue(Vector4d(125, 1750, 32.5, -100) == res, wss.str().c_str());
return;
}
// Tests for expected lerp result 0.50
TEST_METHOD(Lerp_050)
{
Vector4d a(100, 1000, 10, -200);
Vector4d b(200, 4000, 100, 200);
Vector4d res = a.Lerp(b, 0.50);
std::wstringstream wss;
wss << res;
Assert::IsTrue(Vector4d(150, 2500, 55, 0) == res, wss.str().c_str());
return;
}
// Tests for expected lerp result 0.75
TEST_METHOD(Lerp_075)
{
Vector4d a(100, 1000, 10, -200);
Vector4d b(200, 4000, 100, 200);
Vector4d res = a.Lerp(b, 0.75);
std::wstringstream wss;
wss << res;
Assert::IsTrue(Vector4d(175, 3250, 77.5, 100) == res, wss.str().c_str());
return;
}
// Tests for expected lerp result 1.00
TEST_METHOD(Lerp_100)
{
Vector4d a(100, 1000, 10, -200);
Vector4d b(200, 4000, 100, 200);
Vector4d res = a.Lerp(b, 1.00);
std::wstringstream wss;
wss << res;
Assert::IsTrue(b == res, wss.str().c_str());
return;
}
// Tests lerpself
TEST_METHOD(LerpSelf)
{
Vector4d a(100, 1000, 10, -200);
Vector4d b(200, 4000, 100, 200);
a.LerpSelf(b, 0.75);
std::wstringstream wss;
wss << a;
Assert::IsTrue(Vector4d(175, 3250, 77.5, 100) == a, wss.str().c_str());
return;
}
// Tests if an input vector of length 0 is handled correctly by the normalize method
TEST_METHOD(Normalize_Length_Before_Is_0)
{
Vector4d vec(0, 0, 0, 0);
vec.NormalizeSelf();
Assert::AreEqual(0.0, vec.Magnitude());
return;
}
// Tests for any normalized vector to be of length 1
TEST_METHOD(Normalize_Length_Is_1)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double z = LARGE_RAND_DOUBLE;
double w = LARGE_RAND_DOUBLE;
Vector4d vec(x, y, z, w);
// Prevent a vector of length 0 going in
if (vec.SqrMagnitude() == 0)
vec.x++;
std::wstringstream wss;
wss << vec;
Assert::IsTrue(Math::Similar(vec.Normalize().Magnitude(), 1.0), wss.str().c_str()); // Account for floating point inaccuracy
}
return;
}
// Tests the normalize method with known values
TEST_METHOD(Normalize_Oracle)
{
// Setup
Vector4d v(3.2, -5.3, 9.88, 69.420);
// Exercise
v.NormalizeSelf();
// Verify
Vector4d expected(0.0454594951, -0.07529228877, 0.14035619114, 0.98618692201);
Assert::IsTrue(v.Similar(expected));
}
// Kinda dumb method, but ok lol
// DON'T NORMALIZE INT-VECTORS WHAT IS WRONG WITH YOU
TEST_METHOD(Normalized_Int_Vector_Is_0)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
int x = LARGE_RAND_INT;
int y = LARGE_RAND_INT;
int z = LARGE_RAND_INT;
int w = LARGE_RAND_INT;
Vector4i vec(x, y, z, w);
vec.NormalizeSelf();
std::wstringstream wss;
wss << vec;
Assert::AreEqual(0.0, vec.Magnitude(), wss.str().c_str());
}
}
// Tests that NormalizeSelf() results in the same as Normalize()
TEST_METHOD(NormalizeSelf_IsSameAs_Normalize)
{
// Run test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
Vector4d vec(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE);
Vector4d nVec = vec.Normalize();
vec.NormalizeSelf();
Assert::IsTrue(nVec == vec);
}
return;
}
// Tests for the VectorScale() method to work
TEST_METHOD(VectorScale)
{
// Run test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
const double ax = LARGE_RAND_DOUBLE;
const double ay = LARGE_RAND_DOUBLE;
const double az = LARGE_RAND_DOUBLE;
const double aw = LARGE_RAND_DOUBLE;
const double bx = LARGE_RAND_DOUBLE;
const double by = LARGE_RAND_DOUBLE;
const double bz = LARGE_RAND_DOUBLE;
const double bw = LARGE_RAND_DOUBLE;
Vector4d a(ax, ay, az, aw);
Vector4d b(bx, by, bz, bw);
Vector4d target(
ax * bx,
ay * by,
az * bz,
aw * bw
);
Assert::IsTrue(a.VectorScale(b) == target);
}
return;
}
// Tests for operator- (unary) to work
TEST_METHOD(Operator_Unary_Negative)
{
Vector4d v(29, -5, 35, -69);
Assert::IsTrue(Vector4d(-29, 5, -35, 69) == -v);
return;
}
// Tests for operator+ to work as expected
TEST_METHOD(Operator_Add)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double az = LARGE_RAND_DOUBLE;
double aw = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
double bz = LARGE_RAND_DOUBLE;
double bw = LARGE_RAND_DOUBLE;
Vector4d a(ax, ay, az, aw);
Vector4d b(bx, by, bz, bw);
Assert::IsTrue(Vector4d(ax + bx, ay + by, az + bz, aw + bw) == a + b);
}
return;
}
// Tests for operator+= to work as expected
TEST_METHOD(Operator_Add_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double az = LARGE_RAND_DOUBLE;
double aw = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
double bz = LARGE_RAND_DOUBLE;
double bw = LARGE_RAND_DOUBLE;
Vector4d a(ax, ay, az, aw);
a += Vector4d(bx, by, bz, bw);
Assert::IsTrue(Vector4d(ax + bx, ay + by, az + bz, aw + bw) == a);
}
return;
}
// Tests for operator- to work as expected
TEST_METHOD(Operator_Sub)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double az = LARGE_RAND_DOUBLE;
double aw = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
double bz = LARGE_RAND_DOUBLE;
double bw = LARGE_RAND_DOUBLE;
Vector4d a(ax, ay, az, aw);
Vector4d b(bx, by, bz, bw);
Assert::IsTrue(Vector4d(ax - bx, ay - by, az - bz, aw - bw) == a - b);
}
return;
}
// Tests for operator-= to work as expected
TEST_METHOD(Operator_Sub_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double az = LARGE_RAND_DOUBLE;
double aw = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
double bz = LARGE_RAND_DOUBLE;
double bw = LARGE_RAND_DOUBLE;
Vector4d a(ax, ay, az, aw);
a -= Vector4d(bx, by, bz, bw);
Assert::IsTrue(Vector4d(ax - bx, ay - by, az - bz, aw - bw) == a);
}
return;
}
// Tests for operator* to work as expected
TEST_METHOD(Operator_Mult)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double z = LARGE_RAND_DOUBLE;
double w = LARGE_RAND_DOUBLE;
double scalar = LARGE_RAND_DOUBLE;
Vector4d a(x, y, z, w);
Assert::IsTrue(Vector4d(x * scalar, y * scalar, z * scalar, w * scalar) == a * scalar);
}
return;
}
// Tests for operator*= to work as expected
TEST_METHOD(Operator_Mult_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double z = LARGE_RAND_DOUBLE;
double w = LARGE_RAND_DOUBLE;
double scalar = LARGE_RAND_DOUBLE;
Vector4d a(x, y, z, w);
a *= scalar;
Assert::IsTrue(Vector4d(x * scalar, y * scalar, z * scalar, w * scalar) == a);
}
return;
}
// Tests for operator/ to work as expected
TEST_METHOD(Operator_Div)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double z = LARGE_RAND_DOUBLE;
double w = LARGE_RAND_DOUBLE;
double scalar = LARGE_RAND_DOUBLE;
Vector4d a(x, y, z, w);
Assert::IsTrue(Vector4d(x / scalar, y / scalar, z / scalar, w / scalar) == a / scalar);
}
return;
}
// Tests for operator/= to work as expected
TEST_METHOD(Operator_Div_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double x = LARGE_RAND_DOUBLE;
double y = LARGE_RAND_DOUBLE;
double z = LARGE_RAND_DOUBLE;
double w = LARGE_RAND_DOUBLE;
double scalar = LARGE_RAND_DOUBLE;
Vector4d a(x, y, z, w);
a /= scalar;
Assert::IsTrue(Vector4d(x / scalar, y / scalar, z / scalar, w / scalar) == a);
}
return;
}
// Tests for operator== to work as expected
TEST_METHOD(Operator_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double az = LARGE_RAND_DOUBLE;
double aw = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
double bz = LARGE_RAND_DOUBLE;
double bw = LARGE_RAND_DOUBLE;
Vector4d a(ax, ay, az, aw);
Vector4d b(bx, by, bz, bw);
Assert::IsTrue(
((ax == bx) && (ay == by) && (az == bz) && (aw == bw)) ==
(a == b)
);
}
return;
}
// Tests for operator!= to work as expected
TEST_METHOD(Operator_Not_Equals)
{
// Test 1000 times
for (std::size_t i = 0; i < 1000; i++)
{
double ax = LARGE_RAND_DOUBLE;
double ay = LARGE_RAND_DOUBLE;
double az = LARGE_RAND_DOUBLE;
double aw = LARGE_RAND_DOUBLE;
double bx = LARGE_RAND_DOUBLE;
double by = LARGE_RAND_DOUBLE;
double bz = LARGE_RAND_DOUBLE;
double bw = LARGE_RAND_DOUBLE;
Vector4d a(ax, ay, az, aw);
Vector4d b(bx, by, bz, bw);
Assert::IsTrue(
((ax != bx) || (ay != by) || (az != bz) || (aw != bw)) ==
(a != b)
);
}
return;
}
// Tests matrix multiplication with the multiplication operator (*) with a known result
TEST_METHOD(MatrixMult)
{
Vector4d vec(117, 12, -36, 500);
Matrix4x4 mat;
mat[0] = { -43.7, 83, 96, 86 };
mat[1] = { 12, 34.3, 43, -47 };
mat[2] = { 36, 67, 48.9, -32 };
mat[3] = { -69, 47, 21, 89.01 };
vec = vec * mat;
Assert::IsTrue(Vector4d(35427.1, -23232.4, -12744.4, 36240) == vec);
return;
}
// Tests matrix multiplication with the multiplication equals operator (*=) with a known result
TEST_METHOD(MatrixMult_Equals)
{
Vector4d vec(117, 12, -36, 500);
Matrix4x4 mat;
mat[0] = { -43.7, 83, 96, 86 };
mat[1] = { 12, 34.3, 43, -47 };
mat[2] = { 36, 67, 48.9, -32 };
mat[3] = { -69, 47, 21, 89.01 };
vec *= mat;
Assert::IsTrue(Vector4d(35427.1, -23232.4, -12744.4, 36240) == vec);
return;
}
// Tests matrix multiplication with the multiplication operator (*) with a known result, but with an int-vector
TEST_METHOD(MatrixMult_Int)
{
Vector4i vec(112, -420, 80085, 1);
Matrix4x4 mat;
mat[0] = { 12, 83, 96, 86 };
mat[1] = { 12, -57, 43, -47 };
mat[2] = { 36, 67, 61, -32 };
mat[3] = { -69, 47, 21, 99 };
vec = vec * mat;
Assert::IsTrue(Vector4i(7654730, 3468892, 4861045, 1654416) == vec);
return;
}
// Tests matrix multiplication with the multiplication equals operator (*=) with a known result, but with an int - vector
TEST_METHOD(MatrixMult_Equals_Int)
{
Vector4i vec(112, -420, 80085, 1);
Matrix4x4 mat;
mat[0] = { 12, 83, 96, 86 };
mat[1] = { 12, -57, 43, -47 };
mat[2] = { 36, 67, 61, -32 };
mat[3] = { -69, 47, 21, 99 };
vec *= mat;
Assert::IsTrue(Vector4i(7654730, 3468892, 4861045, 1654416) == vec);
return;
}
// Tests loose comparison via Vector4d::Similar -> true
TEST_METHOD(Loose_Comparison_True_Vector4d)
{
Assert::IsTrue(
Vector4d(0.00000000000000000000001, -6.6666666666666666666666666666, 9.9999999999999999999999999999, -3.3333333333333333333333333333333333333).Similar(
Vector4d(0, -6.666666667, 10, -3.33333333333333)
));
return;
}
// Tests loose comparison via Vector4d::Similar -> false
TEST_METHOD(Loose_Comparison_False_Vector4d)
{
Assert::IsFalse(
Vector4d(0.00000000000000000000001, -6.6666666666666666666666666666, 9.9999999999999999999999999999, -3.3333333333333333333333333333333333333).Similar(
Vector4d(0.1, -6.7, 10.1, -3.333)
));
return;
}
// Tests that the move constructor works
TEST_METHOD(Move_Constructor)
{
Vector4d a(1, 2, 3, 4);
Vector4d b(std::move(a));
Assert::AreEqual(b.x, 1.0);
Assert::AreEqual(b.y, 2.0);
Assert::AreEqual(b.z, 3.0);
Assert::AreEqual(b.w, 4.0);
return;
}
// Tests that the move operator works
TEST_METHOD(Move_Operator)
{
Vector4d a(1, 2, 3, 4);
Vector4d b = std::move(a);
Assert::AreEqual(b.x, 1.0);
Assert::AreEqual(b.y, 2.0);
Assert::AreEqual(b.z, 3.0);
Assert::AreEqual(b.w, 4.0);
return;
}
};
}

220
Test/VectorConversion.cpp Normal file
View File

@@ -0,0 +1,220 @@
#include "CppUnitTest.h"
#include "../Eule/Vector2.h"
#include "../Eule/Vector3.h"
#include "../Eule/Vector4.h"
#include "../_TestingUtilities/HandyMacros.h"
#include <random>
#include <sstream>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Eule;
namespace Vectors
{
TEST_CLASS(_VectorConversion)
{
private:
std::mt19937 rng;
public:
// Constructor
_VectorConversion()
{
rng = std::mt19937((std::random_device())());
return;
}
// Tests that conversion vector2 -> vector3 works
TEST_METHOD(Convert_Vector2_To_Vector3)
{
// Run test 100 times
for (std::size_t i = 0; i < 100; i++)
{
Vector2d v2(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE);
Vector3d v3 = v2;
Assert::AreEqual(v2.x, v3.x);
Assert::AreEqual(v2.y, v3.y);
Assert::AreEqual(0.0, v3.z);
}
return;
}
// Tests that conversion vector2 -> vector4 works
TEST_METHOD(Convert_Vector2_To_Vector4)
{
// Run test 100 times
for (std::size_t i = 0; i < 100; i++)
{
Vector2d v2(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE);
Vector4d v4 = v2;
Assert::AreEqual(v2.x, v4.x);
Assert::AreEqual(v2.y, v4.y);
Assert::AreEqual(0.0, v4.z);
Assert::AreEqual(0.0, v4.w);
}
return;
}
// Tests that conversion vector3 -> vector2 works
TEST_METHOD(Convert_Vector3_To_Vector2)
{
// Run test 100 times
for (std::size_t i = 0; i < 100; i++)
{
Vector3d v3(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE);
Vector2d v2 = v3;
Assert::AreEqual(v3.x, v2.x);
Assert::AreEqual(v3.y, v2.y);
}
return;
}
// Tests that conversion vector3 -> vector4 works
TEST_METHOD(Convert_Vector3_To_Vector4)
{
// Run test 100 times
for (std::size_t i = 0; i < 100; i++)
{
Vector3d v3(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE);
Vector4d v4 = v3;
Assert::AreEqual(v3.x, v4.x);
Assert::AreEqual(v3.y, v4.y);
Assert::AreEqual(v3.z, v4.z);
Assert::AreEqual(0.0, v4.w);
}
return;
}
// Tests that conversion vector4 -> vector42 works
TEST_METHOD(Convert_Vector4_To_Vector2)
{
// Run tests 100 times
for (std::size_t i = 0; i < 100; i++)
{
Vector4d v4(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE);
Vector2d v2 = v4;
Assert::AreEqual(v4.x, v2.x);
Assert::AreEqual(v4.y, v2.y);
}
return;
}
// Tests that conversion vector4 -> vector3 works
TEST_METHOD(Convert_Vector4_To_Vector3)
{
// Run tests 100 times
for (std::size_t i = 0; i < 100; i++)
{
Vector4d v4(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE);
Vector3d v3 = v4;
Assert::AreEqual(v4.x, v3.x);
Assert::AreEqual(v4.y, v3.y);
Assert::AreEqual(v4.z, v3.z);
}
return;
}
// Tests Vector2i -> Vector2d
TEST_METHOD(Convert_Vector2i_To_Vector2d)
{
// Setup
Vector2i vi(69, 70);
// Exercise
Vector2d vd = vi.ToDouble();
// Verify
Assert::IsTrue(Vector2d(69, 70) == vd);
return;
}
// Tests Vector2d -> Vector2i
TEST_METHOD(Convert_Vector2d_To_Vector2i)
{
// Setup
Vector2d vd(69.2, 70.8);
// Exercise
Vector2i vi = vd.ToInt();
// Verify
Assert::IsTrue(Vector2i(69, 70) == vi);
return;
}
// Tests Vector3i -> Vector3d
TEST_METHOD(Convert_Vector3i_To_Vector3d)
{
// Setup
Vector3i vi(69, 70, 122);
// Exercise
Vector3d vd = vi.ToDouble();
// Verify
Assert::IsTrue(Vector3d(69, 70, 122) == vd);
return;
}
// Tests Vector3d -> Vector3i
TEST_METHOD(Convert_Vector3d_To_Vector3i)
{
// Setup
Vector3d vd(69.2, 70.8, 122);
// Exercise
Vector3i vi = vd.ToInt();
// Verify
Assert::IsTrue(Vector3i(69, 70, 122) == vi);
return;
}
// Tests Vector4i -> Vector4d
TEST_METHOD(Convert_Vector4i_To_Vector4d)
{
// Setup
Vector4i vi(69, 70, 122, 199);
// Exercise
Vector4d vd = vi.ToDouble();
// Verify
Assert::IsTrue(Vector4d(69, 70, 122, 199) == vd);
return;
}
// Tests Vector4d -> Vector4i
TEST_METHOD(Convert_Vector4d_To_Vector4i)
{
// Setup
Vector4d vd(69.2, 70.8, 122, 199.501);
// Exercise
Vector4i vi = vd.ToInt();
// Verify
Assert::IsTrue(Vector4i(69, 70, 122, 199) == vi);
return;
}
};
}

186
Test/_Test_Eule.vcxproj Normal file
View File

@@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Eule\Eule.vcxproj">
<Project>{e15cd460-78cb-4b3f-be85-c1e3205247b1}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Math_Abs.cpp" />
<ClCompile Include="Math_Clamp.cpp" />
<ClCompile Include="Math_Lerp.cpp" />
<ClCompile Include="Math_Max.cpp" />
<ClCompile Include="Math_Min.cpp" />
<ClCompile Include="Math_Random.cpp" />
<ClCompile Include="Math_RandomInteger.cpp" />
<ClCompile Include="Math_RandomIntRange.cpp" />
<ClCompile Include="Math_Similar.cpp" />
<ClCompile Include="Math__Oscillate.cpp" />
<ClCompile Include="Math__RandomRange.cpp" />
<ClCompile Include="Matrix4x4.cpp" />
<ClCompile Include="Quaternion.cpp" />
<ClCompile Include="TrapazoidalPrismCollider.cpp" />
<ClCompile Include="Vector2.cpp" />
<ClCompile Include="Vector3.cpp" />
<ClCompile Include="Vector4.cpp" />
<ClCompile Include="VectorConversion.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{2B6C03E2-179C-45EA-9FDE-45D0214B4D5E}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>TestEule</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectSubType>NativeUnitTestProject</ProjectSubType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Quelldateien">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headerdateien">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Ressourcendateien">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Tests">
<UniqueIdentifier>{b315014b-6f13-4ae9-bb64-68cd50dde287}</UniqueIdentifier>
</Filter>
<Filter Include="Tests\Math">
<UniqueIdentifier>{4af509be-a959-45e0-bec2-03894a16ad60}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Math__Oscillate.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math__RandomRange.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math_Abs.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math_Clamp.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math_Lerp.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math_Max.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math_Min.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math_Random.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math_RandomInteger.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math_RandomIntRange.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Math_Similar.cpp">
<Filter>Tests\Math</Filter>
</ClCompile>
<ClCompile Include="Matrix4x4.cpp">
<Filter>Tests</Filter>
</ClCompile>
<ClCompile Include="Quaternion.cpp">
<Filter>Tests</Filter>
</ClCompile>
<ClCompile Include="Vector2.cpp">
<Filter>Tests</Filter>
</ClCompile>
<ClCompile Include="Vector3.cpp">
<Filter>Tests</Filter>
</ClCompile>
<ClCompile Include="Vector4.cpp">
<Filter>Tests</Filter>
</ClCompile>
<ClCompile Include="VectorConversion.cpp">
<Filter>Tests</Filter>
</ClCompile>
<ClCompile Include="TrapazoidalPrismCollider.cpp">
<Filter>Tests</Filter>
</ClCompile>
</ItemGroup>
</Project>