Quellcode durchsuchen

Matrix and tests

Kajetan Johannes Hammerle vor 1 Monat
Ursprung
Commit
1ebddec0de
11 geänderte Dateien mit 578 neuen und 184 gelöschten Zeilen
  1. 1 1
      .clangd
  2. 3 6
      CMakeLists.txt
  3. 34 0
      include/core/Matrix.h
  4. 1 1
      include/core/Vector.h
  5. 153 0
      src/Matrix.c
  6. 23 15
      src/Vector.c
  7. 1 1
      test/Main.c
  8. 20 0
      test/Test.c
  9. 18 0
      test/Test.h
  10. 218 0
      test/modules/MatrixTests.c
  11. 106 160
      test/modules/VectorTests.c

+ 1 - 1
.clangd

@@ -1,3 +1,3 @@
 CompileFlags:
-  Add: [-ferror-limit=0, -std=c2x, -DERROR_SIMULATOR=true]
+  Add: [-std=c2x, -DERROR_SIMULATOR=true]
   CompilationDatabase: ./build_debug/

+ 3 - 6
CMakeLists.txt

@@ -6,18 +6,16 @@ set(CMAKE_C_STANDARD 23)
 set(SRC
     "src/Buffer.c"
     "src/Logger.c"
+    "src/Matrix.c"
     "src/Random.c"
     "src/Utility.c"
     "src/Vector.c"
     #"src/BitArray.cpp"
     #"src/Box.cpp"
     #"src/Frustum.cpp"
-    #"src/Matrix.cpp"
-    #"src/Mutex.cpp"
     #"src/Plane.cpp"
     #"src/Quaternion.cpp"
     #"src/SpinLock.cpp"
-    #"src/Thread.cpp"
     #"src/View.cpp"
 )
 
@@ -25,6 +23,7 @@ set(SRC_TESTS
     "test/Main.c"
     "test/Test.c"
     "test/modules/BufferTests.c"
+    "test/modules/MatrixTests.c"
     "test/modules/RandomTests.c"
     "test/modules/UtilityTests.c"
     "test/modules/VectorTests.c"
@@ -36,7 +35,6 @@ set(SRC_TESTS
     #"test/modules/LinkedListTests.cpp"
     #"test/modules/ListTests.cpp"
     #"test/modules/MatrixStackTests.cpp"
-    #"test/modules/MatrixTests.cpp"
     #"test/modules/PlaneTests.cpp"
     #"test/modules/QuaternionTests.cpp"
     #"test/modules/RingBufferTests.cpp"
@@ -159,6 +157,7 @@ target_sources(core PUBLIC
         ./include/core/Buffer.h
         ./include/core/Check.h
         ./include/core/Logger.h
+        ./include/core/Matrix.h
         ./include/core/Random.h
         ./include/core/Types.h
         ./include/core/Utility.h
@@ -169,14 +168,12 @@ target_sources(core PUBLIC
 #        ./include/core/HashMap.hpp
 #        ./include/core/LinkedList.hpp
 #        ./include/core/List.hpp
-#        ./include/core/Matrix.hpp
 #        ./include/core/MatrixStack.hpp
 #        ./include/core/Plane.hpp
 #        ./include/core/ProbingHashMap.hpp
 #        ./include/core/Quaternion.hpp
 #        ./include/core/RingBuffer.hpp
 #        ./include/core/Stack.hpp
-#        ./include/core/Thread.hpp
 #        ./include/core/Vector.hpp
 #        ./include/core/View.hpp
 )

+ 34 - 0
include/core/Matrix.h

@@ -0,0 +1,34 @@
+#ifndef CORE_MATRIX_H
+#define CORE_MATRIX_H
+
+// #include "core/Quaternion.h"
+#include "core/Vector.h"
+
+typedef struct {
+    CoreVector4 data[4];
+} CoreMatrix;
+
+#define CORE_ZERO_MATRIX ((CoreMatrix){0})
+#define CORE_UNIT_MATRIX                                                       \
+    ((CoreMatrix){{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}})
+
+CoreMatrix* coreTransposeMatrix(CoreMatrix* m);
+CoreMatrix* coreMulSetMatrix(CoreMatrix* m, const CoreMatrix* a);
+CoreMatrix* coreMulMatrix(CoreMatrix* m, const CoreMatrix* a,
+                          const CoreMatrix* b);
+CoreVector3* coreMulMatrixV3(CoreVector3* v, const CoreMatrix* m,
+                             const CoreVector3* a);
+CoreMatrix* coreScaleMatrix(CoreMatrix* m, const CoreVector3* v);
+CoreMatrix* coreScaleMatrixF(CoreMatrix* m, float f);
+CoreMatrix* coreTranslateMatrix(CoreMatrix* m, const CoreVector3* v);
+CoreMatrix* coreTranslateMatrixX(CoreMatrix* m, float tx);
+CoreMatrix* coreTranslateMatrixY(CoreMatrix* m, float ty);
+CoreMatrix* coreTranslateMatrixZ(CoreMatrix* m, float tz);
+CoreMatrix* coreTranslateMatrixTo(CoreMatrix* m, const CoreVector3* v);
+CoreMatrix* coreRotateMatrixX(CoreMatrix* m, float degrees);
+CoreMatrix* coreRotateMatrixY(CoreMatrix* m, float degrees);
+CoreMatrix* coreRotateMatrixZ(CoreMatrix* m, float degrees);
+// CoreMatrix* coreRotateMatrix(const Quaternion& q);
+size_t coreToStringMatrix(const CoreMatrix* m, char* buffer, size_t n);
+
+#endif

+ 1 - 1
include/core/Vector.h

@@ -24,7 +24,7 @@
     name* coreDiv##sname##F(name* r, const name* a, type f);                   \
     name* coreInvertSet##sname(name* r);                                       \
     name* coreInvert##sname(name* r, const name* a);                           \
-    void coreToString##sname(const name* a, char* buffer, size_t n);
+    size_t coreToString##sname(const name* a, char* buffer, size_t n);
 
 #define CORE_DEFINE_FVECTOR(N, name)                                           \
     float coreDotV##N(const name* a, const name* b);                           \

+ 153 - 0
src/Matrix.c

@@ -0,0 +1,153 @@
+#include "core/Matrix.h"
+
+#include <math.h>
+#include <stdio.h>
+
+#include "core/Utility.h"
+
+CoreMatrix* coreTransposeMatrix(CoreMatrix* m) {
+    CoreMatrix c;
+    for(size_t x = 0; x < 4; x++) {
+        for(size_t y = 0; y < 4; y++) {
+            c.data[x].data[y] = m->data[y].data[x];
+        }
+    }
+    *m = c;
+    return m;
+}
+
+#define CV40 (&(CoreVector4){0})
+
+CoreMatrix* coreMulSetMatrix(CoreMatrix* m, const CoreMatrix* a) {
+    for(int i = 0; i < 4; i++) {
+        CoreVector4 d = {0};
+        coreAddSetV4(&d, coreMulV4F(CV40, a->data + 0, m->data[i].data[0]));
+        coreAddSetV4(&d, coreMulV4F(CV40, a->data + 1, m->data[i].data[1]));
+        coreAddSetV4(&d, coreMulV4F(CV40, a->data + 2, m->data[i].data[2]));
+        coreAddSetV4(&d, coreMulV4F(CV40, a->data + 3, m->data[i].data[3]));
+        m->data[i] = d;
+    }
+    return m;
+}
+
+CoreMatrix* coreMulMatrix(CoreMatrix* m, const CoreMatrix* a,
+                          const CoreMatrix* b) {
+    *m = *a;
+    coreMulSetMatrix(m, b);
+    return m;
+}
+
+CoreVector3* coreMulMatrixV3(CoreVector3* v, const CoreMatrix* m,
+                             const CoreVector3* a) {
+    CoreVector4 v4 = {a->data[0], a->data[1], a->data[2], 1.0f};
+    v->data[0] = coreDotV4(m->data + 0, &v4);
+    v->data[1] = coreDotV4(m->data + 1, &v4);
+    v->data[2] = coreDotV4(m->data + 2, &v4);
+    coreMulSetV3F(v, 1.0f / coreDotV4(m->data + 3, &v4));
+    return v;
+}
+
+CoreMatrix* coreScaleMatrix(CoreMatrix* m, const CoreVector3* v) {
+    coreMulSetV4F(m->data + 0, v->data[0]);
+    coreMulSetV4F(m->data + 1, v->data[1]);
+    coreMulSetV4F(m->data + 2, v->data[2]);
+    return m;
+}
+
+CoreMatrix* coreScaleMatrixF(CoreMatrix* m, float f) {
+    return coreScaleMatrix(m, &(CoreVector3){f, f, f});
+}
+
+CoreMatrix* coreTranslateMatrix(CoreMatrix* m, const CoreVector3* v) {
+    coreTranslateMatrixX(m, v->data[0]);
+    coreTranslateMatrixY(m, v->data[1]);
+    coreTranslateMatrixZ(m, v->data[2]);
+    return m;
+}
+
+CoreMatrix* coreTranslateMatrixX(CoreMatrix* m, float tx) {
+    coreAddSetV4(m->data + 0, coreMulV4F(CV40, m->data + 3, tx));
+    return m;
+}
+
+CoreMatrix* coreTranslateMatrixY(CoreMatrix* m, float ty) {
+    coreAddSetV4(m->data + 1, coreMulV4F(CV40, m->data + 3, ty));
+    return m;
+}
+
+CoreMatrix* coreTranslateMatrixZ(CoreMatrix* m, float tz) {
+    coreAddSetV4(m->data + 2, coreMulV4F(CV40, m->data + 3, tz));
+    return m;
+}
+
+CoreMatrix* coreTranslateMatrixTo(CoreMatrix* m, const CoreVector3* v) {
+    m->data[0] = (CoreVector4){1.0f, 0.0f, 0.0f, v->data[0]};
+    m->data[1] = (CoreVector4){0.0f, 1.0f, 0.0f, v->data[1]};
+    m->data[2] = (CoreVector4){0.0f, 0.0f, 1.0f, v->data[2]};
+    m->data[3] = (CoreVector4){0.0f, 0.0f, 0.0f, 1.0f};
+    return m;
+}
+
+static CoreMatrix* rotate(CoreMatrix* m, float degrees, int a, int b) {
+    degrees = coreDegreeToRadian(degrees);
+    float sin = sinf(degrees);
+    float cos = cosf(degrees);
+    CoreVector4 v = m->data[a];
+    coreSubV4(m->data + a, coreMulV4F(CV40, &v, cos),
+              coreMulV4F(CV40, m->data + b, sin));
+    coreAddV4(m->data + b, coreMulV4F(CV40, &v, sin),
+              coreMulV4F(CV40, m->data + b, cos));
+    return m;
+}
+
+CoreMatrix* coreRotateMatrixX(CoreMatrix* m, float degrees) {
+    return rotate(m, degrees, 1, 2);
+}
+
+CoreMatrix* coreRotateMatrixY(CoreMatrix* m, float degrees) {
+    return rotate(m, -degrees, 0, 2);
+}
+
+CoreMatrix* coreRotateMatrixZ(CoreMatrix* m, float degrees) {
+    return rotate(m, degrees, 0, 1);
+}
+
+// CoreMatrix* coreRotateMatrix(const Quaternion& q){}
+// Core::Matrix& Core::Matrix::rotate(const Quaternion& q) {
+//    Vector3 a = q * Vector3(data[0][0], data[1][0], data[2][0]);
+//    Vector3 b = q * Vector3(data[0][1], data[1][1], data[2][1]);
+//    Vector3 c = q * Vector3(data[0][2], data[1][2], data[2][2]);
+//    Vector3 d = q * Vector3(data[0][3], data[1][3], data[2][3]);
+//    set(0, Vector4(a[0], b[0], c[0], d[0]));
+//    set(1, Vector4(a[1], b[1], c[1], d[1]));
+//    set(2, Vector4(a[2], b[2], c[2], d[2]));
+//    return *this;
+//}
+
+static void add(size_t* w, char** buffer, size_t* n, size_t shift) {
+    *w += shift;
+    if(*n > shift) {
+        *buffer += shift;
+        *n -= shift;
+    } else {
+        *n = 0;
+    }
+}
+
+static void addI(size_t* w, char** buffer, size_t* n, int shift) {
+    add(w, buffer, n, shift < 0 ? 0 : (size_t)shift);
+}
+
+size_t coreToStringMatrix(const CoreMatrix* m, char* buffer, size_t n) {
+    size_t w = 0;
+    addI(&w, &buffer, &n, snprintf(buffer, n, "["));
+    add(&w, &buffer, &n, coreToStringV4(m->data + 0, buffer, n));
+    addI(&w, &buffer, &n, snprintf(buffer, n, ", "));
+    add(&w, &buffer, &n, coreToStringV4(m->data + 1, buffer, n));
+    addI(&w, &buffer, &n, snprintf(buffer, n, ", "));
+    add(&w, &buffer, &n, coreToStringV4(m->data + 2, buffer, n));
+    addI(&w, &buffer, &n, snprintf(buffer, n, ", "));
+    add(&w, &buffer, &n, coreToStringV4(m->data + 3, buffer, n));
+    addI(&w, &buffer, &n, snprintf(buffer, n, "]"));
+    return w;
+}

+ 23 - 15
src/Vector.c

@@ -157,29 +157,37 @@ VECTOR_IMPL_FLOAT(V2, 2, IV2)
 VECTOR_IMPL_FLOAT(V3, 3, IV3)
 VECTOR_IMPL_FLOAT(V4, 4, IV4)
 
-void coreToStringV2(const V2* a, char* buffer, size_t n) {
-    snprintf(buffer, n, "[%.3f, %.3f]", (double)a->data[0], (double)a->data[1]);
+static size_t safeCast(int s) {
+    return s < 0 ? 0 : (size_t)s;
 }
 
-void coreToStringV3(const V3* a, char* buffer, size_t n) {
-    snprintf(buffer, n, "[%.3f, %.3f, %.3f]", (double)a->data[0],
-             (double)a->data[1], (double)a->data[2]);
+size_t coreToStringV2(const V2* a, char* buffer, size_t n) {
+    return safeCast(snprintf(buffer, n, "[%.3f, %.3f]", (double)a->data[0],
+                             (double)a->data[1]));
 }
 
-void coreToStringV4(const V4* a, char* buffer, size_t n) {
-    snprintf(buffer, n, "[%.3f, %.3f, %.3f, %.3f]", (double)a->data[0],
-             (double)a->data[1], (double)a->data[2], (double)a->data[3]);
+size_t coreToStringV3(const V3* a, char* buffer, size_t n) {
+    return safeCast(snprintf(buffer, n, "[%.3f, %.3f, %.3f]",
+                             (double)a->data[0], (double)a->data[1],
+                             (double)a->data[2]));
 }
 
-void coreToStringIV2(const IV2* a, char* buffer, size_t n) {
-    snprintf(buffer, n, "[%d, %d]", a->data[0], a->data[1]);
+size_t coreToStringV4(const V4* a, char* buffer, size_t n) {
+    return safeCast(snprintf(buffer, n, "[%.3f, %.3f, %.3f, %.3f]",
+                             (double)a->data[0], (double)a->data[1],
+                             (double)a->data[2], (double)a->data[3]));
 }
 
-void coreToStringIV3(const IV3* a, char* buffer, size_t n) {
-    snprintf(buffer, n, "[%d, %d, %d]", a->data[0], a->data[1], a->data[2]);
+size_t coreToStringIV2(const IV2* a, char* buffer, size_t n) {
+    return safeCast(snprintf(buffer, n, "[%d, %d]", a->data[0], a->data[1]));
 }
 
-void coreToStringIV4(const IV4* a, char* buffer, size_t n) {
-    snprintf(buffer, n, "[%d, %d, %d, %d]", a->data[0], a->data[1], a->data[2],
-             a->data[3]);
+size_t coreToStringIV3(const IV3* a, char* buffer, size_t n) {
+    return safeCast(snprintf(buffer, n, "[%d, %d, %d]", a->data[0], a->data[1],
+                             a->data[2]));
+}
+
+size_t coreToStringIV4(const IV4* a, char* buffer, size_t n) {
+    return safeCast(snprintf(buffer, n, "[%d, %d, %d, %d]", a->data[0],
+                             a->data[1], a->data[2], a->data[3]));
 }

+ 1 - 1
test/Main.c

@@ -40,7 +40,7 @@ int main(int argAmount, const char** args) {
     // coreTestLinkedList(light);
     // coreTestList(light);
     // coreTestMatrixStack(light);
-    // coreTestMatrix();
+    coreTestMatrix();
     // coreTestPlane();
     // coreTestQuaternion();
     coreTestRandom(light);

+ 20 - 0
test/Test.c

@@ -121,3 +121,23 @@ bool coreTestNotNull(CORE_TEST_ARGS, const void* actual) {
     puts(CORE_TERMINAL_RESET);
     return false;
 }
+
+bool coreTestVectorN(CORE_TEST_ARGS, const float* wanted, const float* actual,
+                     size_t n) {
+    for(size_t i = 0; i < n; i++) {
+        if(!coreTestFloat(file, line, wanted[i], actual[i], 0.01f)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool coreTestIntVectorN(CORE_TEST_ARGS, const int* wanted, const int* actual,
+                        size_t n) {
+    for(size_t i = 0; i < n; i++) {
+        if(!coreTestInt(file, line, wanted[i], actual[i])) {
+            return false;
+        }
+    }
+    return true;
+}

+ 18 - 0
test/Test.h

@@ -38,4 +38,22 @@ bool coreTestNotNull(CORE_TEST_ARGS, const void* p);
 #define CORE_TEST_NULL(actual) coreTestNull(__FILE__, __LINE__, actual)
 #define CORE_TEST_NOT_NULL(actual) coreTestNotNull(__FILE__, __LINE__, actual)
 
+bool coreTestVectorN(CORE_TEST_ARGS, const float* wanted, const float* actual,
+                     size_t n);
+#define CORE_TEST_V2(wanted, actual)                                           \
+    coreTestVectorN(__FILE__, __LINE__, (wanted)->data, (actual)->data, 2)
+#define CORE_TEST_V3(wanted, actual)                                           \
+    coreTestVectorN(__FILE__, __LINE__, (wanted)->data, (actual)->data, 3)
+#define CORE_TEST_V4(wanted, actual)                                           \
+    coreTestVectorN(__FILE__, __LINE__, (wanted)->data, (actual)->data, 4)
+
+bool coreTestIntVectorN(CORE_TEST_ARGS, const int* wanted, const int* actual,
+                        size_t n);
+#define CORE_TEST_IV2(wanted, actual)                                          \
+    coreTestIntVectorN(__FILE__, __LINE__, (wanted)->data, (actual)->data, 2)
+#define CORE_TEST_IV3(wanted, actual)                                          \
+    coreTestIntVectorN(__FILE__, __LINE__, (wanted)->data, (actual)->data, 3)
+#define CORE_TEST_IV4(wanted, actual)                                          \
+    coreTestIntVectorN(__FILE__, __LINE__, (wanted)->data, (actual)->data, 4)
+
 #endif

+ 218 - 0
test/modules/MatrixTests.c

@@ -0,0 +1,218 @@
+#include "../Tests.h"
+#include "core/Matrix.h"
+
+typedef CoreMatrix Matrix;
+typedef CoreVector3 V3;
+#define CV3(a, b, c) (&(V3){a, b, c})
+#define CV30 CV3(0.0f, 0.0f, 0.0f)
+
+static void testInit() {
+    Matrix m = CORE_UNIT_MATRIX;
+    const float* data = (float*)&m;
+    for(int i = 0; i < 16; i++) {
+        int x = i % 4;
+        int y = i / 4;
+        CORE_TEST_FLOAT(x == y, data[i], 0.0f);
+    }
+}
+
+static void testTranspose() {
+    Matrix m;
+    float* data = (float*)&m;
+    for(int i = 0; i < 16; i++) {
+        data[i] = (float)(i + 1);
+    }
+    Matrix t = m;
+    coreTransposeMatrix(&t);
+    Matrix m2 = t;
+    coreTransposeMatrix(&m2);
+
+    const float* mp = (float*)&m;
+    const float* tp = (float*)&t;
+    for(int x = 0; x < 4; x++) {
+        for(int y = 0; y < 4; y++) {
+            CORE_TEST_FLOAT(mp[y * 4 + x], tp[x * 4 + y], 0.0f);
+        }
+    }
+    const float* mp2 = (float*)&m2;
+    for(int i = 0; i < 16; i++) {
+        CORE_TEST_FLOAT(mp[i], mp2[i], 0.0f);
+    }
+}
+
+static void testScale() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreScaleMatrix(&m, CV3(2.0f, 3.0f, 4.0f));
+    CORE_TEST_V3(CV3(-8.0f, 18.0f, 28.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(-4.0f, 6.0f, 7.0f)));
+}
+
+static void testUniformScale() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreScaleMatrixF(&m, 2.0f);
+    CORE_TEST_V3(CV3(-8.0f, 12.0f, 14.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(-4.0f, 6.0f, 7.0f)));
+}
+
+static void testTranslateX() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreTranslateMatrixX(&m, 5.0f);
+    CORE_TEST_V3(CV3(1.0f, 6.0f, 7.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(-4.0f, 6.0f, 7.0f)));
+}
+
+static void testTranslateY() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreTranslateMatrixY(&m, 6.0f);
+    CORE_TEST_V3(CV3(-4.0f, 12.0f, 7.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(-4.0f, 6.0f, 7.0f)));
+}
+
+static void testTranslateZ() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreTranslateMatrixZ(&m, 7.0f);
+    CORE_TEST_V3(CV3(-4.0f, 6.0f, 14.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(-4.0f, 6.0f, 7.0f)));
+}
+
+static void testTranslate() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreTranslateMatrix(&m, CV3(1.0f, 2.0f, 3.0f));
+    CORE_TEST_V3(CV3(-3.0f, 8.0f, 10.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(-4.0f, 6.0f, 7.0f)));
+}
+
+static void testTranslateTo() {
+    char buffer[1024];
+    Matrix m;
+    for(int i = 0; i < 16; i++) {
+        ((float*)&m)[i] = (float)i + 1.0f;
+    }
+    coreTranslateMatrixTo(&m, CV3(6.0f, 8.0f, 9.0f));
+    coreToStringMatrix(&m, buffer, sizeof(buffer));
+    CORE_TEST_STRING(
+        "[[1.000, 0.000, 0.000, 6.000], [0.000, 1.000, 0.000, 8.000], "
+        "[0.000, 0.000, 1.000, 9.000], [0.000, 0.000, 0.000, 1.000]]",
+        buffer);
+}
+
+static void testCombination() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreScaleMatrixF(&m, 2.0f);
+    coreTranslateMatrixX(&m, 1.0f);
+    coreTranslateMatrixY(&m, 2.0f);
+    coreTranslateMatrixZ(&m, 3.0f);
+    coreTranslateMatrix(&m, CV3(-4.0f, 2.0f, 3.0f));
+    coreScaleMatrix(&m, CV3(2.0f, 3.0f, 4.0f));
+    coreScaleMatrixF(&m, 0.5f);
+    CORE_TEST_V3(CV3(-1.0f, 9.0f, 16.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(1.0f, 1.0f, 1.0f)));
+}
+
+static void testMatrixCombination() {
+    Matrix a = CORE_UNIT_MATRIX;
+    coreScaleMatrixF(&a, 2.0f);
+    coreTranslateMatrix(&a, CV3(1.0f, 2.0f, 3.0f));
+
+    Matrix b = CORE_UNIT_MATRIX;
+    coreScaleMatrixF(&b, 3.0f);
+    coreTranslateMatrix(&b, CV3(1.0f, 1.0f, 1.0f));
+
+    Matrix c = CORE_UNIT_MATRIX;
+    coreTranslateMatrix(&c, CV3(-1.0f, -2.0f, -3.0f));
+
+    coreMulSetMatrix(&c, coreMulMatrix(&CORE_ZERO_MATRIX, &b, &a));
+
+    CORE_TEST_V3(CV3(9.0f, 11.0f, 13.0f),
+                 coreMulMatrixV3(CV30, &c, CV3(1.0f, 1.0f, 1.0f)));
+}
+
+static void testRotateX() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreRotateMatrixX(&m, 90.0f);
+    CORE_TEST_V3(CV3(1.0f, 0.0f, 0.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(1.0f, 0.0f, 0.0f)));
+    CORE_TEST_V3(CV3(0.0f, 0.0f, 1.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(0.0f, 1.0f, 0.0f)));
+    CORE_TEST_V3(CV3(0.0f, -1.0f, 0.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(0.0f, 0.0f, 1.0f)));
+}
+
+static void testRotateY() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreRotateMatrixY(&m, 90.0f);
+    CORE_TEST_V3(CV3(0.0f, 0.0f, -1.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(1.0f, 0.0f, 0.0f)));
+    CORE_TEST_V3(CV3(0.0f, 1.0f, 0.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(0.0f, 1.0f, 0.0f)));
+    CORE_TEST_V3(CV3(1.0f, 0.0f, 0.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(0.0f, 0.0f, 1.0f)));
+}
+
+static void testRotateZ() {
+    Matrix m = CORE_UNIT_MATRIX;
+    coreRotateMatrixZ(&m, 90.0f);
+    CORE_TEST_V3(CV3(0.0f, 1.0f, 0.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(1.0f, 0.0f, 0.0f)));
+    CORE_TEST_V3(CV3(-1.0f, 0.0f, 0.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(0.0f, 1.0f, 0.0f)));
+    CORE_TEST_V3(CV3(0.0f, 0.0f, 1.0f),
+                 coreMulMatrixV3(CV30, &m, CV3(0.0f, 0.0f, 1.0f)));
+}
+
+static void testToString() {
+    Matrix m;
+    for(int i = 0; i < 16; i++) {
+        ((float*)&m)[i] = (float)i + 1.0f;
+    }
+    char buffer[1024];
+    size_t n = coreToStringMatrix(&m, buffer, sizeof(buffer));
+    CORE_TEST_SIZE(127, n);
+    CORE_TEST_STRING(
+        "[[1.000, 2.000, 3.000, 4.000], [5.000, 6.000, 7.000, 8.000], "
+        "[9.000, 10.000, 11.000, 12.000], [13.000, 14.000, 15.000, 16.000]]",
+        buffer);
+
+    n = coreToStringMatrix(&m, buffer, 20);
+    CORE_TEST_SIZE(127, n);
+    CORE_TEST_STRING("[[1.000, 2.000, 3.0", buffer);
+}
+
+/*static void testQuaternionMatrix() {
+    Core::Quaternion q1(V3(1.0f, 0.0f, 0.0f), 48.0f);
+    Core::Quaternion q2(V3(0.0f, 1.0f, 0.0f), 52.0f);
+    Core::Quaternion q3(V3(0.0f, 0.0f, 1.0f), 60.0f);
+
+    Core::Matrix m;
+    m.translate(V3(1.0f, 2.0f, 3.0f));
+    m.rotate(q1).rotate(q2).rotate(q3);
+    m.translate(V3(1.0f, 2.0f, 3.0f));
+
+    Core::Matrix check;
+    check.translate(V3(1.0f, 2.0f, 3.0f));
+    check.rotateX(48.0f).rotateY(52.0f).rotateZ(60.0f);
+    check.translate(V3(1.0f, 2.0f, 3.0f));
+
+    for(int i = 0; i < 16; i++) {
+        CORE_TEST_FLOAT(check.getValues()[i], m.getValues()[i], 0.0001f);
+    }
+}*/
+
+void coreTestMatrix() {
+    testInit();
+    testTranspose();
+    testScale();
+    testUniformScale();
+    testTranslateX();
+    testTranslateY();
+    testTranslateZ();
+    testTranslate();
+    testTranslateTo();
+    testCombination();
+    testMatrixCombination();
+    testRotateX();
+    testRotateY();
+    testRotateZ();
+    testToString();
+    // testQuaternionMatrix();
+}

+ 106 - 160
test/modules/VectorTests.c

@@ -33,224 +33,170 @@ const float eps = 0.0001f;
 #define CIV4(a, b, c, d) (&(IV4){a, b, c, d})
 #define CIV40 CIV4(0, 0, 0, 0)
 
-static void testV(const char* file, int line, const float* wanted,
-                  const float* actual, size_t n) {
-    for(size_t i = 0; i < n; i++) {
-        coreTestFloat(file, line, wanted[i], actual[i], eps);
-    }
-}
-
-#define testV2(wanted, actual)                                                 \
-    testV(__FILE__, __LINE__, (wanted)->data, (actual)->data, 2)
-#define testV3(wanted, actual)                                                 \
-    testV(__FILE__, __LINE__, (wanted)->data, (actual)->data, 3)
-#define testV4(wanted, actual)                                                 \
-    testV(__FILE__, __LINE__, (wanted)->data, (actual)->data, 4)
-
-static void testIV(const char* file, int line, const int* wanted,
-                   const int* actual, size_t n) {
-    for(size_t i = 0; i < n; i++) {
-        coreTestInt(file, line, wanted[i], actual[i]);
-    }
-}
-
-#define testIV2(wanted, actual)                                                \
-    testIV(__FILE__, __LINE__, (wanted)->data, (actual)->data, 2)
-#define testIV3(wanted, actual)                                                \
-    testIV(__FILE__, __LINE__, (wanted)->data, (actual)->data, 3)
-#define testIV4(wanted, actual)                                                \
-    testIV(__FILE__, __LINE__, (wanted)->data, (actual)->data, 4)
+#define TESTS X(V2) X(V3) X(V4) X(IV2) X(IV3) X(IV4)
 
 static void testSetAngles() {
     float root = sqrtf(2) * 0.5f;
-    testV3(FV3(1, 0, 0), coreAngles(CV30, 0, 0));
-    testV3(FV3(root, 0, -root), coreAngles(CV30, 45, 0));
-    testV3(FV3(0, 0, -1), coreAngles(CV30, 90, 0));
-    testV3(FV3(-root, 0, -root), coreAngles(CV30, 135, 0));
-    testV3(FV3(-1, 0, 0), coreAngles(CV30, 180, 0));
-    testV3(FV3(-root, 0, root), coreAngles(CV30, 225, 0));
-    testV3(FV3(0, 0, 1), coreAngles(CV30, 270, 0));
-    testV3(FV3(root, 0, root), coreAngles(CV30, 315, 0));
-
-    testV3(FV3(0, 1, 0), coreAngles(CV30, 0, 90));
-    testV3(FV3(0, 1, 0), coreAngles(CV30, 90, 90));
-    testV3(FV3(0, 1, 0), coreAngles(CV30, 180, 90));
-    testV3(FV3(0, 1, 0), coreAngles(CV30, 270, 90));
-
-    testV3(FV3(0, -1, 0), coreAngles(CV30, 0, -90));
-    testV3(FV3(0, -1, 0), coreAngles(CV30, 90, -90));
-    testV3(FV3(0, -1, 0), coreAngles(CV30, 180, -90));
-    testV3(FV3(0, -1, 0), coreAngles(CV30, 270, -90));
-
-    testV3(FV3(root, root, 0), coreAngles(CV30, 0, 45));
-    testV3(FV3(0, root, -root), coreAngles(CV30, 90, 45));
-    testV3(FV3(-root, root, 0), coreAngles(CV30, 180, 45));
-    testV3(FV3(0, root, root), coreAngles(CV30, 270, 45));
-
-    testV3(FV3(root, -root, 0), coreAngles(CV30, 0, -45));
-    testV3(FV3(0, -root, -root), coreAngles(CV30, 90, -45));
-    testV3(FV3(-root, -root, 0), coreAngles(CV30, 180, -45));
-    testV3(FV3(0, -root, root), coreAngles(CV30, 270, -45));
-
-    testV3(FV3(0.5f, root, -0.5f), coreAngles(CV30, 45, 45));
+    CORE_TEST_V3(FV3(1, 0, 0), coreAngles(CV30, 0, 0));
+    CORE_TEST_V3(FV3(root, 0, -root), coreAngles(CV30, 45, 0));
+    CORE_TEST_V3(FV3(0, 0, -1), coreAngles(CV30, 90, 0));
+    CORE_TEST_V3(FV3(-root, 0, -root), coreAngles(CV30, 135, 0));
+    CORE_TEST_V3(FV3(-1, 0, 0), coreAngles(CV30, 180, 0));
+    CORE_TEST_V3(FV3(-root, 0, root), coreAngles(CV30, 225, 0));
+    CORE_TEST_V3(FV3(0, 0, 1), coreAngles(CV30, 270, 0));
+    CORE_TEST_V3(FV3(root, 0, root), coreAngles(CV30, 315, 0));
+
+    CORE_TEST_V3(FV3(0, 1, 0), coreAngles(CV30, 0, 90));
+    CORE_TEST_V3(FV3(0, 1, 0), coreAngles(CV30, 90, 90));
+    CORE_TEST_V3(FV3(0, 1, 0), coreAngles(CV30, 180, 90));
+    CORE_TEST_V3(FV3(0, 1, 0), coreAngles(CV30, 270, 90));
+
+    CORE_TEST_V3(FV3(0, -1, 0), coreAngles(CV30, 0, -90));
+    CORE_TEST_V3(FV3(0, -1, 0), coreAngles(CV30, 90, -90));
+    CORE_TEST_V3(FV3(0, -1, 0), coreAngles(CV30, 180, -90));
+    CORE_TEST_V3(FV3(0, -1, 0), coreAngles(CV30, 270, -90));
+
+    CORE_TEST_V3(FV3(root, root, 0), coreAngles(CV30, 0, 45));
+    CORE_TEST_V3(FV3(0, root, -root), coreAngles(CV30, 90, 45));
+    CORE_TEST_V3(FV3(-root, root, 0), coreAngles(CV30, 180, 45));
+    CORE_TEST_V3(FV3(0, root, root), coreAngles(CV30, 270, 45));
+
+    CORE_TEST_V3(FV3(root, -root, 0), coreAngles(CV30, 0, -45));
+    CORE_TEST_V3(FV3(0, -root, -root), coreAngles(CV30, 90, -45));
+    CORE_TEST_V3(FV3(-root, -root, 0), coreAngles(CV30, 180, -45));
+    CORE_TEST_V3(FV3(0, -root, root), coreAngles(CV30, 270, -45));
+
+    CORE_TEST_V3(FV3(0.5f, root, -0.5f), coreAngles(CV30, 45, 45));
 }
 
 static void testCross() {
-    testV3(FV3(0, 0, 1), coreCross(CV30, FV3(1, 0, 0), FV3(0, 1, 0)));
-    testV3(FV3(0, -1, 0), coreCross(CV30, FV3(1, 0, 0), FV3(0, 0, 1)));
-    testV3(FV3(0, 0, -1), coreCross(CV30, FV3(0, 1, 0), FV3(1, 0, 0)));
-    testV3(FV3(1, 0, 0), coreCross(CV30, FV3(0, 1, 0), FV3(0, 0, 1)));
-    testV3(FV3(0, 1, 0), coreCross(CV30, FV3(0, 0, 1), FV3(1, 0, 0)));
-    testV3(FV3(-1, 0, 0), coreCross(CV30, FV3(0, 0, 1), FV3(0, 1, 0)));
+    CORE_TEST_V3(FV3(0, 0, 1), coreCross(CV30, FV3(1, 0, 0), FV3(0, 1, 0)));
+    CORE_TEST_V3(FV3(0, -1, 0), coreCross(CV30, FV3(1, 0, 0), FV3(0, 0, 1)));
+    CORE_TEST_V3(FV3(0, 0, -1), coreCross(CV30, FV3(0, 1, 0), FV3(1, 0, 0)));
+    CORE_TEST_V3(FV3(1, 0, 0), coreCross(CV30, FV3(0, 1, 0), FV3(0, 0, 1)));
+    CORE_TEST_V3(FV3(0, 1, 0), coreCross(CV30, FV3(0, 0, 1), FV3(1, 0, 0)));
+    CORE_TEST_V3(FV3(-1, 0, 0), coreCross(CV30, FV3(0, 0, 1), FV3(0, 1, 0)));
 }
 
-#define TEST_SET_ADD(T)                                                        \
+static void testSetAdd() {
+#define X(T)                                                                   \
     {                                                                          \
         T v = {0};                                                             \
         coreAddSet##T(&v, C##T(1, 2, 3, 4));                                   \
-        test##T(C##T(1, 2, 3, 4), &v);                                         \
+        CORE_TEST_##T(C##T(1, 2, 3, 4), &v);                                   \
         coreAddSet##T(&v, C##T(2, 3, 4, 5));                                   \
-        test##T(C##T(3, 5, 7, 9), &v);                                         \
+        CORE_TEST_##T(C##T(3, 5, 7, 9), &v);                                   \
     }
-
-static void testSetAdd() {
-    TEST_SET_ADD(V2)
-    TEST_SET_ADD(V3)
-    TEST_SET_ADD(V4)
-    TEST_SET_ADD(IV2)
-    TEST_SET_ADD(IV3)
-    TEST_SET_ADD(IV4)
+    TESTS
+#undef X
 }
 
 static void testAdd() {
-    testV3(FV3(1, 2, 3), coreAddV3(CV30, CV30, FV3(1, 2, 3)));
-    testV3(FV3(3, 5, 7), coreAddV3(CV30, FV3(1, 2, 3), FV3(2, 3, 4)));
+    CORE_TEST_V3(FV3(1, 2, 3), coreAddV3(CV30, CV30, FV3(1, 2, 3)));
+    CORE_TEST_V3(FV3(3, 5, 7), coreAddV3(CV30, FV3(1, 2, 3), FV3(2, 3, 4)));
 }
 
-#define TEST_SET_SUB(T)                                                        \
+static void testSetSub() {
+#define X(T)                                                                   \
     {                                                                          \
         T v = {0};                                                             \
         coreSubSet##T(&v, C##T(1, 2, 3, 4));                                   \
-        test##T(C##T(-1, -2, -3, -4), &v);                                     \
+        CORE_TEST_##T(C##T(-1, -2, -3, -4), &v);                               \
         coreSubSet##T(&v, C##T(2, 3, 4, 5));                                   \
-        test##T(C##T(-3, -5, -7, -9), &v);                                     \
+        CORE_TEST_##T(C##T(-3, -5, -7, -9), &v);                               \
     }
-
-static void testSetSub() {
-    TEST_SET_SUB(V2)
-    TEST_SET_SUB(V3)
-    TEST_SET_SUB(V4)
-    TEST_SET_SUB(IV2)
-    TEST_SET_SUB(IV3)
-    TEST_SET_SUB(IV4)
+    TESTS
+#undef X
 }
 
 static void testSub() {
-    testV3(FV3(1, 2, 3), coreSubV3(CV30, CV30, FV3(-1, -2, -3)));
-    testV3(FV3(-1, -1, -1), coreSubV3(CV30, FV3(1, 2, 3), FV3(2, 3, 4)));
+    CORE_TEST_V3(FV3(1, 2, 3), coreSubV3(CV30, CV30, FV3(-1, -2, -3)));
+    CORE_TEST_V3(FV3(-1, -1, -1), coreSubV3(CV30, FV3(1, 2, 3), FV3(2, 3, 4)));
 }
 
-#define TEST_SET_MUL(T)                                                        \
+static void testSetMul() {
+#define X(T)                                                                   \
     {                                                                          \
         T v = *C##T(1, 2, 3, 4);                                               \
         coreMulSet##T##F(&v, 3);                                               \
-        test##T(C##T(3, 6, 9, 12), &v);                                        \
+        CORE_TEST_##T(C##T(3, 6, 9, 12), &v);                                  \
         coreMulSet##T##F(&v, -2);                                              \
-        test##T(C##T(-6, -12, -18, -24), &v);                                  \
+        CORE_TEST_##T(C##T(-6, -12, -18, -24), &v);                            \
     }
-
-static void testSetMul() {
-    TEST_SET_MUL(V2)
-    TEST_SET_MUL(V3)
-    TEST_SET_MUL(V4)
-    TEST_SET_MUL(IV2)
-    TEST_SET_MUL(IV3)
-    TEST_SET_MUL(IV4)
+    TESTS
+#undef X
 }
 
 static void testMul() {
-    testV3(FV3(3, 6, 9), coreMulV3F(CV30, FV3(1, 2, 3), 3));
+    CORE_TEST_V3(FV3(3, 6, 9), coreMulV3F(CV30, FV3(1, 2, 3), 3));
 }
 
-#define TEST_SET_MUL_VECTOR(T)                                                 \
+static void testSetMulVector() {
+#define X(T)                                                                   \
     {                                                                          \
         T v = *C##T(1, 2, 3, 4);                                               \
         coreMulSet##T(&v, C##T(2, 1, 3, 4));                                   \
-        test##T(C##T(2, 2, 9, 16), &v);                                        \
+        CORE_TEST_##T(C##T(2, 2, 9, 16), &v);                                  \
         coreMulSet##T(&v, C##T(-3, 4, -2, -2));                                \
-        test##T(C##T(-6, 8, -18, -32), &v);                                    \
+        CORE_TEST_##T(C##T(-6, 8, -18, -32), &v);                              \
     }
-
-static void testSetMulVector() {
-    TEST_SET_MUL_VECTOR(V2)
-    TEST_SET_MUL_VECTOR(V3)
-    TEST_SET_MUL_VECTOR(V4)
-    TEST_SET_MUL_VECTOR(IV2)
-    TEST_SET_MUL_VECTOR(IV3)
-    TEST_SET_MUL_VECTOR(IV4)
+    TESTS
+#undef X
 }
 
 static void testMulVector() {
-    testV3(FV3(-2, -2, -9), coreMulV3(CV30, FV3(2, 1, 3), FV3(-1, -2, -3)));
-    testV3(FV3(2, 2, 9), coreMulV3(CV30, FV3(1, 2, 3), FV3(2, 1, 3)));
+    CORE_TEST_V3(FV3(-2, -2, -9),
+                 coreMulV3(CV30, FV3(2, 1, 3), FV3(-1, -2, -3)));
+    CORE_TEST_V3(FV3(2, 2, 9), coreMulV3(CV30, FV3(1, 2, 3), FV3(2, 1, 3)));
 }
 
-#define TEST_SET_DIV(T)                                                        \
+static void testSetDiv() {
+#define X(T)                                                                   \
     {                                                                          \
         T v = *C##T(18, 36, 9, 27);                                            \
         coreDivSet##T##F(&v, 3);                                               \
-        test##T(C##T(6, 12, 3, 9), &v);                                        \
+        CORE_TEST_##T(C##T(6, 12, 3, 9), &v);                                  \
         coreDivSet##T##F(&v, -3);                                              \
-        test##T(C##T(-2, -4, -1, -3), &v);                                     \
+        CORE_TEST_##T(C##T(-2, -4, -1, -3), &v);                               \
     }
-
-static void testSetDiv() {
-    TEST_SET_DIV(V2);
-    TEST_SET_DIV(V3);
-    TEST_SET_DIV(V4);
-    TEST_SET_DIV(IV2);
-    TEST_SET_DIV(IV3);
-    TEST_SET_DIV(IV4);
+    TESTS
+#undef X
 }
 
 static void testDiv() {
-    testV3(FV3(-1, -2, -3), coreDivV3F(CV30, FV3(-3, -6, -9), 3));
+    CORE_TEST_V3(FV3(-1, -2, -3), coreDivV3F(CV30, FV3(-3, -6, -9), 3));
 }
 
-#define TEST_SET_DIV_VECTOR(T)                                                 \
+static void testSetDivVector() {
+#define X(T)                                                                   \
     {                                                                          \
         T v = *C##T(12, 4, 6, 8);                                              \
         coreDivSet##T(&v, C##T(2, 1, 3, 4));                                   \
-        test##T(C##T(6, 4, 2, 2), &v);                                         \
+        CORE_TEST_##T(C##T(6, 4, 2, 2), &v);                                   \
         coreDivSet##T(&v, C##T(-3, 4, -2, -1));                                \
-        test##T(C##T(-2, 1, -1, -2), &v);                                      \
+        CORE_TEST_##T(C##T(-2, 1, -1, -2), &v);                                \
     }
-
-static void testSetDivVector() {
-    TEST_SET_DIV_VECTOR(V2)
-    TEST_SET_DIV_VECTOR(V3)
-    TEST_SET_DIV_VECTOR(V4)
-    TEST_SET_DIV_VECTOR(IV2)
-    TEST_SET_DIV_VECTOR(IV3)
-    TEST_SET_DIV_VECTOR(IV4)
+    TESTS
+#undef X
 }
 
 static void testDivVector() {
-    testV3(FV3(-2, -0.5f, -1), coreDivV3(CV30, FV3(2, 1, 3), FV3(-1, -2, -3)));
-    testV3(FV3(0.5f, 2, 1), coreDivV3(CV30, FV3(1, 2, 3), FV3(2, 1, 3)));
+    CORE_TEST_V3(FV3(-2, -0.5f, -1),
+                 coreDivV3(CV30, FV3(2, 1, 3), FV3(-1, -2, -3)));
+    CORE_TEST_V3(FV3(0.5f, 2, 1), coreDivV3(CV30, FV3(1, 2, 3), FV3(2, 1, 3)));
 }
 
 static void testSetInvert() {
-    testV2(FV2(-1, 2), coreInvertSetV2(FV2(1, -2)));
-    testV3(FV3(-1, 2, 3), coreInvertSetV3(FV3(1, -2, -3)));
-    testV4(CV4(-1, 2, 3, 4), coreInvertSetV4(CV4(1, -2, -3, -4)));
-    testIV2(FIV2(-1, 2), coreInvertSetIV2(FIV2(1, -2)));
-    testIV3(FIV3(-1, 2, 3), coreInvertSetIV3(FIV3(1, -2, -3)));
-    testIV4(CIV4(-1, 2, 3, 4), coreInvertSetIV4(CIV4(1, -2, -3, -4)));
+    CORE_TEST_V2(FV2(-1, 2), coreInvertSetV2(FV2(1, -2)));
+    CORE_TEST_V3(FV3(-1, 2, 3), coreInvertSetV3(FV3(1, -2, -3)));
+    CORE_TEST_V4(CV4(-1, 2, 3, 4), coreInvertSetV4(CV4(1, -2, -3, -4)));
+    CORE_TEST_IV2(FIV2(-1, 2), coreInvertSetIV2(FIV2(1, -2)));
+    CORE_TEST_IV3(FIV3(-1, 2, 3), coreInvertSetIV3(FIV3(1, -2, -3)));
+    CORE_TEST_IV4(CIV4(-1, 2, 3, 4), coreInvertSetIV4(CIV4(1, -2, -3, -4)));
 }
 
 static void testInvert() {
-    testV3(FV3(-1, 2, 3), coreInvertV3(CV30, FV3(1, -2, -3)));
+    CORE_TEST_V3(FV3(-1, 2, 3), coreInvertV3(CV30, FV3(1, -2, -3)));
 }
 
 static void testDot() {
@@ -280,51 +226,51 @@ static void testNormalize() {
         V2 v2;
         coreMulV2F(&v2, &v1, 1.0f / 25.0f);
         coreNormalizeV2(&v1);
-        testV2(&v2, &v1);
+        CORE_TEST_V2(&v2, &v1);
 
         V2 v3 = {15, 36};
         V2 v4;
         coreMulV2F(&v4, &v3, 1.0f / 39.0f);
         coreNormalizeV2(&v3);
-        testV2(&v4, &v3);
+        CORE_TEST_V2(&v4, &v3);
     }
     {
         V3 v1 = {-2, 2, -1};
         V3 v2;
         coreMulV3F(&v2, &v1, 1.0f / 3.0f);
         coreNormalizeV3(&v1);
-        testV3(&v2, &v1);
+        CORE_TEST_V3(&v2, &v1);
 
         V3 v3 = {6, 2, -3};
         V3 v4;
         coreMulV3F(&v4, &v3, 1.0f / 7.0f);
         coreNormalizeV3(&v3);
-        testV3(&v4, &v3);
+        CORE_TEST_V3(&v4, &v3);
     }
     {
         V4 v1 = {-2, 2, 0, -1};
         V4 v2;
         coreMulV4F(&v2, &v1, 1.0f / 3.0f);
         coreNormalizeV4(&v1);
-        testV4(&v2, &v1);
+        CORE_TEST_V4(&v2, &v1);
 
         V4 v3 = {6, 0, -6, 3};
         V4 v4;
         coreMulV4F(&v4, &v3, 1.0f / 9.0f);
         coreNormalizeV4(&v3);
-        testV4(&v4, &v3);
+        CORE_TEST_V4(&v4, &v3);
     }
 }
 
 static void testCast() {
-    testV2(FV2(-2.0f, 2.0f), coreConvertIV2(CV20, FIV2(-2, 2)));
-    testIV2(FIV2(-2, 2), coreConvertV2(CIV20, FV2(-2.5f, 2.6f)));
-    testV3(FV3(-2.0f, 2.0f, 9.0f), coreConvertIV3(CV30, FIV3(-2, 2, 9)));
-    testIV3(FIV3(-2, 2, 9), coreConvertV3(CIV30, FV3(-2.5f, 2.6f, 9.0f)));
-    testV4(CV4(-2.0f, 2.0f, 9.0f, 6.0f),
-           coreConvertIV4(CV40, CIV4(-2, 2, 9, 6)));
-    testIV4(CIV4(-2, 2, 9, 3),
-            coreConvertV4(CIV40, CV4(-2.5f, 2.6f, 9.0f, 3.2f)));
+    CORE_TEST_V2(FV2(-2.0f, 2.0f), coreConvertIV2(CV20, FIV2(-2, 2)));
+    CORE_TEST_IV2(FIV2(-2, 2), coreConvertV2(CIV20, FV2(-2.5f, 2.6f)));
+    CORE_TEST_V3(FV3(-2.0f, 2.0f, 9.0f), coreConvertIV3(CV30, FIV3(-2, 2, 9)));
+    CORE_TEST_IV3(FIV3(-2, 2, 9), coreConvertV3(CIV30, FV3(-2.5f, 2.6f, 9.0f)));
+    CORE_TEST_V4(CV4(-2.0f, 2.0f, 9.0f, 6.0f),
+                 coreConvertIV4(CV40, CIV4(-2, 2, 9, 6)));
+    CORE_TEST_IV4(CIV4(-2, 2, 9, 3),
+                  coreConvertV4(CIV40, CV4(-2.5f, 2.6f, 9.0f, 3.2f)));
 }
 
 static void testToString() {