commit df7960ee84ff2205abf1d4b1a016486c96b9fb7d
parent 0396aa42e744eab1e99da14554cc74d96659de2e
Author: vaplv <vaplv@free.fr>
Date: Sun, 22 Jun 2014 22:04:53 +0200
Merge the rmath sources into rsys
Diffstat:
| M | cmake/CMakeLists.txt | | | 14 | ++++++++++++++ |
| A | cmake/RSysConfig.cmake | | | 45 | +++++++++++++++++++++++++++++++++++++++++++++ |
| A | cmake/RSysConfigVersion.cmake | | | 40 | ++++++++++++++++++++++++++++++++++++++++ |
| A | src/float2.h | | | 16 | ++++++++++++++++ |
| A | src/float22.h | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/float3.h | | | 20 | ++++++++++++++++++++ |
| A | src/float33.h | | | 80 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/float4.h | | | 9 | +++++++++ |
| A | src/float44.c | | | 69 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/float44.h | | | 67 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/floatX.h | | | 281 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/floatXY.h | | | 294 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/test_float2.c | | | 90 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/test_float22.c | | | 108 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/test_float3.c | | | 99 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/test_float33.c | | | 164 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/test_float4.c | | | 97 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/test_float44.c | | | 359 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
18 files changed, 1907 insertions(+), 0 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -43,6 +43,14 @@ set(RSYS_FILES_INC
dynamic_array_char.h
dynamic_array_uchar.h
dynamic_array_u64.h
+ floatX.h
+ float2.h
+ float3.h
+ float4.h
+ floatXY.h
+ float22.h
+ float33.h
+ float44.h
free_list.h
hash.h
hash_table.h
@@ -88,6 +96,12 @@ endmacro(new_test)
new_test(test_atomic)
new_test(test_dynamic_array rsys)
+new_test(test_float2 m)
+new_test(test_float3 m)
+new_test(test_float4 m)
+new_test(test_float22)
+new_test(test_float33)
+new_test(test_float44 rsys)
new_test(test_free_list rsys)
new_test(test_hash_table rsys)
new_test(test_library rsys)
diff --git a/cmake/RSysConfig.cmake b/cmake/RSysConfig.cmake
@@ -0,0 +1,45 @@
+cmake_minimum_required(VERSION 2.6)
+# Try to find the RSys devel. Once done this will define:
+# - RSys_FOUND: system has RSys
+# - RSys_INCLUDE_DIR: the include directory
+# - RSys: Link this to use rsys
+find_path(RSys_INCLUDE_DIR rsys/rsys.h)
+
+find_library(RSys_LIBRARY
+ rsys
+ PATHS bin Bin BIN)
+
+find_library(RSys_LIBRARY_DEBUG
+ rsys-dbg
+ PATHS bin Bin BIN)
+
+if(NOT RSys_LIBRARY AND RSys_LIBRARY_DEBUG)
+ unset(RSys_LIBRARY CACHE)
+ set(RSys_LIBRARY ${RSys_LIBRARY_DEBUG}
+ CACHE PATH "Path to a library")
+endif(NOT RSys_LIBRARY)
+
+if(NOT RSys_LIBRARY_DEBUG AND RSys_LIBRARY)
+ unset(RSys_LIBRARY_DEBUG CACHE)
+ set(RSys_LIBRARY_DEBUG ${RSys_LIBRARY}
+ CACHE PATH "Path to a library")
+endif(NOT RSys_LIBRARY_DEBUG)
+
+if(CMAKE_HOST_WIN32)
+ set(_property IMPORTED_IMPLIB)
+else(CMAKE_HOST_WIN32)
+ set(_property IMPORTED_LOCATION)
+endif(CMAKE_HOST_WIN32)
+
+add_library(RSys IMPORTED)
+set_target_properties(RSys PROPERTIES
+ ${_property} ${RSys_LIBRARY_DEBUG}
+ ${_property}_DEBUG ${RSys_LIBRARY_DEBUG}
+ ${_property}_RELEASE ${RSys_LIBRARY})
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(RSys DEFAULT_MSG
+ RSys_INCLUDE_DIR
+ RSys_LIBRARY
+ RSys_LIBRARY_DEBUG)
+
diff --git a/cmake/RSysConfigVersion.cmake b/cmake/RSysConfigVersion.cmake
@@ -0,0 +1,40 @@
+set(VERSION_MAJOR 0)
+set(VERSION_MINOR 0)
+set(VERSION_PATCH 0)
+set(PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
+
+if(NOT PACKAGE_FIND_VERSION
+ OR PACKAGE_VERSION VERSION_EQUAL PACKAGE_FIND_VERSION)
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ set(PACKAGE_VERSION_EXACT TRUE)
+ set(PACKAGE_VERSION_UNSUITABLE FALSE)
+ return()
+endif(NOT PACKAGE_FIND_VERSION
+ OR PACKAGE_VERSION VERSION_EQUAL PACKAGE_FIND_VERSION)
+
+if(NOT VERSION_MAJOR VERSION_EQUAL PACKAGE_FIND_VERSION_MAJOR)
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+ set(PACKAGE_VERSION_EXACT FALSE)
+ set(PACKAGE_VERSION_UNSUITABLE TRUE)
+ return()
+endif(NOT VERSION_MAJOR VERSION_EQUAL PACKAGE_FIND_VERSION_MAJOR)
+
+if(VERSION_MINOR VERSION_LESS PACKAGE_FIND_VERSION_MINOR)
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+ set(PACKAGE_VERSION_EXACT FALSE)
+ set(PACKAGE_VERSION_UNSUITABLE TRUE)
+ return()
+endif(VERSION_MINOR VERSION_LESS PACKAGE_FIND_VERSION_MINOR)
+
+if(VERSION_MINOR VERSION_EQUAL PACKAGE_FIND_VERSION_MINOR )
+ if(VERSION_PATCH VERSION_LESS PACKAGE_FIND_VERSION_PATCH)
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+ set(PACKAGE_VERSION_EXACT FALSE)
+ set(PACKAGE_VERSION_UNSUITABLE TRUE)
+ return()
+ endif()
+endif()
+
+set(PACKAGE_VERSION_COMPATIBLE TRUE)
+set(PACKAGE_VERSION_EXACT FALSE)
+set(PACKAGE_VERSION_UNSUITABLE FALSE)
diff --git a/src/float2.h b/src/float2.h
@@ -0,0 +1,16 @@
+#ifndef FLOAT2_H
+#define FLOAT2_H
+
+/* Generate common floatX funcs */
+#define FLOATX_DIMENSION__ 2
+#include "floatX.h"
+
+static FINLINE float
+f2_cross(const float a[2], const float b[2])
+{
+ ASSERT(a && b);
+ return a[0]*b[1] - a[1]*b[0];
+}
+
+#endif /* FLOAT2_H */
+
diff --git a/src/float22.h b/src/float22.h
@@ -0,0 +1,55 @@
+#ifndef FLOAT22_H
+#define FLOAT22_H
+
+#include "float2.h"
+
+/* Generate common floatXY funcs */
+#define FLOATX_DIMENSION__ 2
+#define FLOATY_DIMENSION__ 2
+#include "floatXY.h"
+
+/* Specific float22 funcs */
+static FINLINE float*
+f22(float* dst, const float a, const float b, const float c, const float d)
+{
+ ASSERT(dst);
+ dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+ return dst;
+}
+
+static FINLINE float
+f22_det(const float* mat)
+{
+ return mat[0] * mat[3] - mat[2] * mat[1];
+}
+
+static FINLINE float
+f22_inverse(float* dst, const float* mat)
+{
+ float det, rcp_det, mat0;
+ ASSERT(dst && mat);
+ det = f22_det(mat);
+ rcp_det = 1.f / det;
+ mat0 = mat[0];
+ dst[0] = mat[3] * rcp_det;
+ dst[1] = -mat[1] * rcp_det;
+ dst[2] = -mat[2] * rcp_det;
+ dst[3] = mat0 * rcp_det;
+ return det;
+}
+
+static FINLINE float
+f22_invtrans(float* dst, const float* mat)
+{
+ float det, dst1, dst2;
+ ASSERT(dst && mat);
+ det = f22_inverse(dst, mat);
+ dst1 = dst[1];
+ dst2 = dst[2];
+ dst[1] = dst2;
+ dst[2] = dst1;
+ return det;
+}
+
+#endif /* FLOAT22_H */
+
diff --git a/src/float3.h b/src/float3.h
@@ -0,0 +1,20 @@
+#ifndef FLOAT3_H
+#define FLOAT3_H
+
+/* Generate common floatX funcs */
+#define FLOATX_DIMENSION__ 3
+#include "floatX.h"
+
+static FINLINE float*
+f3_cross(float dst[3], const float a[3], const float b[3])
+{
+ float tmp[3];
+ ASSERT(dst && a && b);
+ tmp[0] = a[1]*b[2] - a[2]*b[1];
+ tmp[1] = a[2]*b[0] - a[0]*b[2];
+ tmp[2] = a[0]*b[1] - a[1]*b[0];
+ return f3_set(dst, tmp);
+}
+
+#endif /* FLOAT3_H */
+
diff --git a/src/float33.h b/src/float33.h
@@ -0,0 +1,80 @@
+#ifndef FLOAT33_H
+#define FLOAT33_H
+
+#include "float3.h"
+#include <math.h>
+
+
+/* Generate common floatXY funcs */
+#define FLOATX_DIMENSION__ 3
+#define FLOATY_DIMENSION__ 3
+#include "floatXY.h"
+
+/* Specific float33 funcs */
+static FINLINE float*
+f33
+ (float* dst,
+ const float a, const float b, const float c,
+ const float d, const float e, const float f,
+ const float g, const float h, const float i)
+{
+ ASSERT(dst);
+ dst[0] = a; dst[1] = b; dst[2] = c;
+ dst[3] = d; dst[4] = e; dst[5] = f;
+ dst[6] = g; dst[7] = h; dst[8] = i;
+ return dst;
+}
+
+static FINLINE float
+f33_det(const float* mat)
+{
+ float tmp[3];
+ f3_cross(tmp, f33_col_cptr(mat, 0), f33_col_cptr(mat, 1));
+ return f3_dot(f33_col_cptr(mat, 2), tmp);
+}
+
+static FINLINE float
+f33_invtrans(float* dst, const float* src)
+{
+ float f33[9];
+ float det;
+ f3_cross(f33_col_ptr(f33, 0), f33_col_cptr(src, 1), f33_col_cptr(src, 2));
+ f3_cross(f33_col_ptr(f33, 1), f33_col_cptr(src, 2), f33_col_cptr(src, 0));
+ f3_cross(f33_col_ptr(f33, 2), f33_col_cptr(src, 0), f33_col_cptr(src, 1));
+
+ det = f3_dot(f33_col_cptr(f33, 2), f33_col_cptr(src, 2));
+ f33_mul(dst, f33, 1.f / det);
+ return det;
+}
+
+static FINLINE float
+f33_inverse(float* dst, const float* src)
+{
+ float f33[9];
+ const float det = f33_invtrans(f33, src);
+ f33_transpose(dst, f33);
+ return det;
+}
+
+static FINLINE float*
+f33_rotation /* XYZ norm */
+ (float* dst,
+ const float pitch,
+ const float yaw,
+ const float roll)
+{
+ const float c1 = (float)cos((double)pitch);
+ const float c2 = (float)cos((double)yaw);
+ const float c3 = (float)cos((double)roll);
+ const float s1 = (float)sin((double)pitch);
+ const float s2 = (float)sin((double)yaw);
+ const float s3 = (float)sin((double)roll);
+ ASSERT(dst);
+ dst[0] = c2*c3; dst[1] = c1*s3 + c3*s1*s2; dst[2] = s1*s3 - c1*c3*s2;
+ dst[3] =-c2*s3; dst[4] = c1*c3 - s1*s2*s3; dst[5] = c1*s2*s3 + c3*s1;
+ dst[6] = s2; dst[7] =-c2*s1; dst[8] = c1*c2;
+ return dst;
+}
+
+#endif /* FLOAT33_H */
+
diff --git a/src/float4.h b/src/float4.h
@@ -0,0 +1,9 @@
+#ifndef FLOAT4_H
+#define FLOAT4_H
+
+/* Generate common floatX funcs */
+#define FLOATX_DIMENSION__ 4
+#include "floatX.h"
+
+#endif /* FLOAT4_H */
+
diff --git a/src/float44.c b/src/float44.c
@@ -0,0 +1,69 @@
+#include "float44.h"
+
+float
+f44_inverse(float* dst, const float* m)
+{
+ float tmp[9];
+ float det_012[4], det_023[4], det_123[4], det_013[4];
+ float cofacts[4];
+ float det, rcp_det, mpmp_rcp_det[4], pmpm_rcp_det[4];
+ ASSERT( dst && m );
+
+ /* Define the 3x3 sub matrices and compute their determinants */
+ #define C3( Dst, Mat, ICol, X, Y, Z ) \
+ (Dst)[0] = Mat[ICol*4+X], (Dst)[1] = Mat[ICol*4+Y], (Dst)[2] = Mat[ICol*4+Z]
+ C3(tmp+0 ,m, 1, 0, 1, 2); C3(tmp+3, m, 2, 0, 1, 2); C3(tmp+6, m, 3, 0, 1, 2);
+ det_012[0] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 0, 1, 2); C3(tmp+3, m, 2, 0, 1, 2); C3(tmp+6, m, 3, 0, 1, 2);
+ det_012[1] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 0, 1, 2); C3(tmp+3, m, 1, 0, 1, 2); C3(tmp+6, m, 3, 0, 1, 2);
+ det_012[2] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 0, 1, 2); C3(tmp+3, m, 1, 0, 1, 2); C3(tmp+6, m, 2, 0, 1, 2);
+ det_012[3] = f33_det(tmp);
+
+ C3(tmp+0 ,m, 1, 0, 2, 3); C3(tmp+3, m, 2, 0, 2, 3); C3(tmp+6, m, 3, 0, 2, 3);
+ det_023[0] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 0, 2, 3); C3(tmp+3, m, 2, 0, 2, 3); C3(tmp+6, m, 3, 0, 2, 3);
+ det_023[1] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 0, 2, 3); C3(tmp+3, m, 1, 0, 2, 3); C3(tmp+6, m, 3, 0, 2, 3);
+ det_023[2] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 0, 2, 3); C3(tmp+3, m, 1, 0, 2, 3); C3(tmp+6, m, 2, 0, 2, 3);
+ det_023[3] = f33_det(tmp);
+
+ C3(tmp+0 ,m, 1, 1, 2, 3); C3(tmp+3, m, 2, 1, 2, 3); C3(tmp+6, m, 3, 1, 2, 3);
+ det_123[0] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 1, 2, 3); C3(tmp+3, m, 2, 1, 2, 3); C3(tmp+6, m, 3, 1, 2, 3);
+ det_123[1] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 1, 2, 3); C3(tmp+3, m, 1, 1, 2, 3); C3(tmp+6, m, 3, 1, 2, 3);
+ det_123[2] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 1, 2, 3); C3(tmp+3, m, 1, 1, 2, 3); C3(tmp+6, m, 2, 1, 2, 3);
+ det_123[3] = f33_det(tmp);
+
+ C3(tmp+0 ,m, 1, 0, 1, 3); C3(tmp+3, m, 2, 0, 1, 3); C3(tmp+6, m, 3, 0, 1, 3);
+ det_013[0] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 0, 1, 3); C3(tmp+3, m, 2, 0, 1, 3); C3(tmp+6, m, 3, 0, 1, 3);
+ det_013[1] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 0, 1, 3); C3(tmp+3, m, 1, 0, 1, 3); C3(tmp+6, m, 3, 0, 1, 3);
+ det_013[2] = f33_det(tmp);
+ C3(tmp+0 ,m, 0, 0, 1, 3); C3(tmp+3, m, 1, 0, 1, 3); C3(tmp+6, m, 2, 0, 1, 3);
+ det_013[3] = f33_det(tmp);
+ #undef C3
+
+ f4_set(cofacts, f4(tmp, -det_012[0], det_012[1], -det_012[2], det_012[3]));
+
+ /* Compute the determinant of src */
+ det = f4_dot(cofacts, f4(tmp, m[3], m[7], m[11], m[15]));
+
+ /* Invert the matrix */
+ if( det == 0.f )
+ return det;
+
+ rcp_det = 1.f / det;
+ f4_set(mpmp_rcp_det, f4(tmp,-rcp_det, rcp_det,-rcp_det, rcp_det));
+ f4_set(pmpm_rcp_det, f4(tmp, rcp_det,-rcp_det, rcp_det,-rcp_det));
+ f4_mul(f44_col_ptr(dst, 0), det_123, pmpm_rcp_det);
+ f4_mul(f44_col_ptr(dst, 1), det_023, mpmp_rcp_det);
+ f4_mul(f44_col_ptr(dst, 2), det_013, pmpm_rcp_det);
+ f4_mul(f44_col_ptr(dst, 3), det_012, mpmp_rcp_det);
+ return det;
+}
diff --git a/src/float44.h b/src/float44.h
@@ -0,0 +1,67 @@
+#ifndef FLOAT44_H
+#define FLOAT44_H
+
+#include "float33.h"
+#include "float4.h"
+
+/* Generate common floatXY funcs */
+#define FLOATX_DIMENSION__ 4
+#define FLOATY_DIMENSION__ 4
+#include "floatXY.h"
+
+/* Specific float44 funcs*/
+static FINLINE float*
+f44
+ (float* dst,
+ const float a, const float b, const float c, const float d,
+ const float e, const float f, const float g, const float h,
+ const float i, const float j, const float k, const float l,
+ const float m, const float n, const float o, const float p)
+{
+ ASSERT(dst);
+ dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+ dst[4] = e; dst[5] = f; dst[6] = g; dst[7] = h;
+ dst[8] = i; dst[9] = j; dst[10] = k; dst[11] = l;
+ dst[12] = m; dst[13] = n; dst[14] = o; dst[15] = p;
+ return dst;
+}
+
+static FINLINE float
+f44_det(const float* mat)
+{
+ float f33[9];
+ float row3[4], tmp[4];
+ ASSERT( mat );
+
+ #define C3( Dst, Mat, ICol ) \
+ (Dst)[0] = Mat[ICol*4], (Dst)[1] = Mat[ICol*4+1], (Dst)[2] = Mat[ICol*4+2]
+ C3(f33 + 0, mat, 1); C3(f33 + 3, mat, 2); C3(f33 + 6, mat, 3);
+ tmp[0] = -f33_det(f33);
+ C3(f33 + 0, mat, 0); C3(f33 + 3, mat, 2); C3(f33 + 6, mat, 3);
+ tmp[1] = f33_det(f33);
+ C3(f33 + 0, mat, 0); C3(f33 + 3, mat, 1); C3(f33 + 6, mat, 3);
+ tmp[2] = -f33_det(f33);
+ C3(f33 + 0, mat, 0); C3(f33 + 3, mat, 1); C3(f33 + 6, mat, 2);
+ #undef C3
+ tmp[3] = f33_det(f33);
+ f44_row(row3, mat, 3);
+ return f4_dot(tmp, row3);
+}
+
+BEGIN_DECLS
+
+RSYS_API float
+f44_inverse(float* dst, const float* mat);
+
+END_DECLS
+
+static FINLINE float
+f44_invtrans(float* dst, const float* mat)
+{
+ const float det = f44_inverse(dst, mat);
+ f44_transpose(dst, dst);
+ return det;
+}
+
+#endif /* FLOAT44_H */
+
diff --git a/src/floatX.h b/src/floatX.h
@@ -0,0 +1,281 @@
+/*
+ * Internal header used to generate funcs on float vector of X dimensions
+ */
+#if !defined(FLOATX_DIMENSION__)
+ #error Missing arguments
+#endif
+
+#if defined(FLOATX_FUNC__)
+ #error Unexpected macro defintion
+#endif
+
+#include "math.h"
+#include "rsys.h"
+#include <math.h>
+
+STATIC_ASSERT(FLOATX_DIMENSION__ > 1, Unexpected_value);
+
+#define FLOATX_FUNC__(Func) \
+ CONCAT(CONCAT(CONCAT(f, FLOATX_DIMENSION__), _), Func)
+
+#if FLOATX_DIMENSION__ <= 4
+static FINLINE float*
+CONCAT(f, FLOATX_DIMENSION__)
+ (float* dst
+ ,const float x
+ ,const float y
+#if FLOATX_DIMENSION__ > 2
+ ,const float z
+#endif
+#if FLOATX_DIMENSION__ > 3
+ ,const float w
+#endif
+ )
+{
+ ASSERT(dst);
+ dst[0] = x;
+ dst[1] = y;
+#if FLOATX_DIMENSION__ > 2
+ dst[2] = z;
+#endif
+#if FLOATX_DIMENSION__ > 3
+ dst[3] = w;
+#endif
+ return dst;
+}
+#endif
+
+static FINLINE float*
+FLOATX_FUNC__(splat)(float* dst, const float val)
+{
+ int i;
+ ASSERT(dst);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = val;
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(set)(float* dst, const float* src)
+{
+ int i;
+ ASSERT(dst && src);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = src[i];
+ return dst;
+}
+
+static FINLINE float
+FLOATX_FUNC__(dot)(const float* a, const float* b)
+{
+ float dot = 0.0f;
+ int i;
+ ASSERT(a && b);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dot += a[i] * b[i];
+ return dot;
+}
+
+static FINLINE float
+FLOATX_FUNC__(len)(const float* a)
+{
+ ASSERT(a);
+ return (float)sqrt((double)FLOATX_FUNC__(dot)(a, a));
+}
+
+static FINLINE float
+FLOATX_FUNC__(normalize)(float* dst, const float* a)
+{
+ float len, rcp_len;
+ int i;
+ ASSERT(dst && a);
+
+ len = FLOATX_FUNC__(len)(a);
+ if(len == 0.f)
+ return len;
+
+ rcp_len = 1.0f / len;
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] * rcp_len;
+ return len;
+}
+
+static FINLINE char
+FLOATX_FUNC__(is_normalized)(const float* a)
+{
+ return eq_eps(FLOATX_FUNC__(len)(a), 1.f, 1.e-6f);
+}
+
+static FINLINE float*
+FLOATX_FUNC__(add)(float* dst, const float* a, const float* b)
+{
+ int i;
+ ASSERT(dst && a && b);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] + b[i];
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(addf)(float* dst, const float* a, const float f)
+{
+ int i;
+ ASSERT(dst && a);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] + f;
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(sub)(float* dst, const float* a, const float* b)
+{
+ int i;
+ ASSERT(dst && a && b);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] - b[i];
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(subf)(float* dst, const float* a, const float f)
+{
+ int i;
+ ASSERT(dst && a);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] - f;
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(mul)(float* dst, const float* a, const float* b)
+{
+ int i;
+ ASSERT(dst && a && b);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] * b[i];
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(mulf)(float* dst, const float* a, const float f)
+{
+ int i;
+ ASSERT(dst && a);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] * f;
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(div)(float* dst, const float* a, const float* b)
+{
+ int i;
+ ASSERT(dst && a && b);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] / b[i];
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(divf)(float* dst, const float* a, const float f)
+{
+ int i;
+ ASSERT(dst && a);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] / f;
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(minus)(float* dst, const float* a)
+{
+ int i;
+ ASSERT(dst && a);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = -a[i];
+ return dst;
+}
+
+static FINLINE float
+FLOATX_FUNC__(sum)(const float* a)
+{
+ float f = 0.0f;
+ int i = 0;
+ ASSERT(a);
+ do {
+ f += a[i];
+ ++i;
+ } while(i < FLOATX_DIMENSION__);
+ return f;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(lerp)
+ (float* dst,
+ const float* from,
+ const float* to,
+ const float t)
+{
+ ASSERT(dst && from && to);
+ if(t <= 0.f) {
+ FLOATX_FUNC__(set)(dst, from);
+ } else if(t >= 1.0f) {
+ FLOATX_FUNC__(set)(dst, to);
+ } else {
+ int i;
+ FOR_EACH(i, 0, FLOATX_DIMENSION__) {
+ dst[i] = from[i] + t * (to[i] - from[i]);
+ }
+ }
+ return dst;
+}
+
+static FINLINE char
+FLOATX_FUNC__(eq)(const float* a, const float* b)
+{
+ int i = 0;
+ char is_eq = 1;
+ ASSERT(a && b);
+ do {
+ is_eq = a[i] == b[i];
+ ++i;
+ } while(i < FLOATX_DIMENSION__ && is_eq);
+ return is_eq;
+}
+
+static FINLINE char
+FLOATX_FUNC__(eq_eps)(const float* a, const float* b, const float eps)
+{
+ int i = 0;
+ char is_eq = 1;
+ ASSERT(a && b);
+ do {
+ is_eq = eq_eps(a[i], b[i], eps);
+ ++i;
+ } while(i < FLOATX_DIMENSION__ && is_eq);
+ return is_eq;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(max)(float* dst, const float* a, const float* b)
+{
+ int i;
+ ASSERT(dst && a && b);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] > b[i] ? a[i] : b[i];
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(min)(float* dst, const float* a, const float* b)
+{
+ int i;
+ ASSERT(dst && a && b);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__)
+ dst[i] = a[i] < b[i] ? a[i] : b[i];
+ return dst;
+}
+
+#undef FLOATX_DIMENSION__
+#undef FLOATX_FUNC__
+
diff --git a/src/floatXY.h b/src/floatXY.h
@@ -0,0 +1,294 @@
+/*
+ * Internal header used to generate funcs on column major float matrix of X x Y
+ * dimensions.
+ */
+#if !defined(FLOATX_DIMENSION__) && !defined(FLOATY_DIMENSION__)
+ #error Missing arguments
+#endif
+
+#if defined(FLOATXY_FUNC__)
+ #error Unexpected macro defintion
+#endif
+
+#include "math.h"
+#include "rsys.h"
+
+STATIC_ASSERT
+ (FLOATX_DIMENSION__ > 1 && FLOATY_DIMENSION__ > 1, Unexpected_value);
+
+#define FLOATXY_FUNC__(Func) \
+ CONCAT(CONCAT(CONCAT(CONCAT \
+ (f, FLOATX_DIMENSION__), FLOATY_DIMENSION__), _), Func)
+
+#define FLOATX_FUNC__(Func) \
+ CONCAT(CONCAT(CONCAT(f, FLOATX_DIMENSION__), _), Func)
+#define FLOATY_FUNC__(Func) \
+ CONCAT(CONCAT(CONCAT(f, FLOATY_DIMENSION__), _), Func)
+
+static FINLINE float*
+FLOATXY_FUNC__(splat)(float* dst, const float val)
+{
+ int i = 0;
+ ASSERT(dst);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__*FLOATY_DIMENSION__) {
+ dst[i] = val;
+ }
+ return dst;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(set)(float* dst, const float* src)
+{
+ int x, y, i;
+ ASSERT(dst && src);
+ i = 0;
+ FOR_EACH(x, 0, FLOATX_DIMENSION__) {
+ FOR_EACH(y, 0, FLOATY_DIMENSION__) {
+ dst[i] = src[i];
+ ++i;
+ }
+ }
+ return dst;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(set_identity)(float* mat)
+{
+ int x, y, i;
+ ASSERT(mat);
+ i = 0;
+ FOR_EACH(x, 0, FLOATX_DIMENSION__) {
+ FOR_EACH(y, 0, FLOATY_DIMENSION__) {
+ mat[i] = x == y ? 1.f : 0.f;
+ ++i;
+ }
+ }
+ return mat;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(set_row)(float* mat, const float* row, const int irow)
+{
+ float tmp[FLOATX_DIMENSION__];
+ int x;
+ ASSERT(mat && row && irow < FLOATY_DIMENSION__ && irow >= 0);
+
+ FOR_EACH(x, 0, FLOATX_DIMENSION__)
+ tmp[x] = row[x];
+ FOR_EACH(x, 0, FLOATX_DIMENSION__)
+ mat[x * FLOATY_DIMENSION__ + irow] = tmp[x];
+ return mat;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(set_col)(float* mat, const float* col, const int icol)
+{
+ float tmp[FLOATY_DIMENSION__];
+ int y;
+ ASSERT(mat && col && icol < FLOATX_DIMENSION__ && icol >= 0);
+ FOR_EACH(y, 0, FLOATY_DIMENSION__)
+ tmp[y] = col[y];
+ FLOATX_FUNC__(set)(mat + (icol * FLOATY_DIMENSION__), tmp);
+ return mat;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(row)(float* row, const float* mat, const int irow)
+{
+ float tmp[FLOATX_DIMENSION__];
+ int x;
+ ASSERT(row && mat && irow < FLOATY_DIMENSION__);
+
+ FOR_EACH(x, 0, FLOATX_DIMENSION__)
+ tmp[x] = mat[x * FLOATY_DIMENSION__ + irow];
+ FOR_EACH(x, 0, FLOATX_DIMENSION__)
+ row[x] = tmp[x];
+ return row;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(col_ptr)(float* mat, const int icol)
+{
+ ASSERT(mat && icol < FLOATX_DIMENSION__);
+ return mat + (icol * FLOATY_DIMENSION__);
+}
+
+static FINLINE const float*
+FLOATXY_FUNC__(col_cptr)(const float* mat, const int icol)
+{
+ ASSERT(mat && icol < FLOATX_DIMENSION__);
+ return mat + (icol * FLOATY_DIMENSION__);
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(col)(float* col, const float* mat, const int icol)
+{
+ float tmp[FLOATY_DIMENSION__];
+ const float* col_ptr = FLOATXY_FUNC__(col_cptr)(mat, icol);
+ int x, y;
+ ASSERT(mat && icol < FLOATY_DIMENSION__);
+
+ FOR_EACH(y, 0, FLOATY_DIMENSION__)
+ tmp[y] = col_ptr[y];
+ FOR_EACH(x, 0, FLOATX_DIMENSION__)
+ col[x] = tmp[x];
+ return col;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(add)(float* dst, const float* a, const float* b)
+{
+ int i;
+ FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__)
+ dst[i] = a[i] + b[i];
+ return dst;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(sub)(float* dst, const float* a, const float* b)
+{
+ int i;
+ FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__)
+ dst[i] = a[i] - b[i];
+ return dst;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(minus)(float* dst, const float* a)
+{
+ int i;
+ FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__)
+ dst[i] = -a[i];
+ return dst;
+}
+
+static FINLINE char
+FLOATXY_FUNC__(eq)(const float* a, const float* b)
+{
+ char is_eq = 1;
+ int x = 0;
+ ASSERT(a && b);
+
+ do {
+ const int i = x * FLOATY_DIMENSION__;
+ is_eq = FLOATX_FUNC__(eq)(a + i, b + i);
+ ++x;
+ } while(x < FLOATX_DIMENSION__ && is_eq);
+ return is_eq;
+}
+
+static FINLINE char
+FLOATXY_FUNC__(eq_eps)(const float* a, const float* b, const float eps)
+{
+ char is_eq = 1;
+ int x = 0;
+ ASSERT(a && b);
+
+ do {
+ const int i = x * FLOATY_DIMENSION__;
+ is_eq = FLOATX_FUNC__(eq_eps)(a + i, b + i, eps);
+ ++x;
+ } while(x < FLOATX_DIMENSION__ && is_eq);
+ return is_eq;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(CONCAT(mulf, FLOATX_DIMENSION__))
+ (float* dst, const float* mat, const float* vec)
+{
+ float row[FLOATX_DIMENSION__];
+ float tmp[FLOATY_DIMENSION__];
+ int y;
+ ASSERT(dst && mat && vec);
+
+ FOR_EACH(y, 0, FLOATY_DIMENSION__) {
+ FLOATXY_FUNC__(row)(row, mat, y);
+ tmp[y] = FLOATX_FUNC__(dot)(row, vec);
+ }
+ return FLOATY_FUNC__(set)(dst, tmp);
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(mul)(float* dst, const float* mat, const float b)
+{
+ int i;
+ ASSERT(dst && mat);
+ FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__) {
+ dst[i] = mat[i] * b;
+ }
+ return dst;
+}
+
+static FINLINE float*
+FLOATX_FUNC__(CONCAT(CONCAT(mulf, FLOATX_DIMENSION__), FLOATY_DIMENSION__))
+ (float* dst, const float* vec, const float* mat)
+{
+ float tmp[FLOATX_DIMENSION__];
+ int x;
+ ASSERT(dst && vec && mat);
+ FOR_EACH(x, 0, FLOATX_DIMENSION__) {
+ const float* col = mat + (x * FLOATY_DIMENSION__);
+ tmp[x] = FLOATX_FUNC__(dot)(vec, col);
+ }
+ return FLOATX_FUNC__(set)(dst, tmp);
+}
+
+#if FLOATX_DIMENSION__ == FLOATY_DIMENSION__
+static FINLINE float*
+FLOATXY_FUNC__(transpose)(float* dst, const float* src)
+{
+ float tmp[FLOATX_DIMENSION__ * FLOATY_DIMENSION__];
+ int x, y, i;
+ ASSERT(dst && src);
+
+ i = 0;
+ FOR_EACH(x, 0, FLOATX_DIMENSION__) {
+ FOR_EACH(y, 0, FLOATY_DIMENSION__) {
+ tmp[y * FLOATY_DIMENSION__ + x] = src[i];
+ ++i;
+ }
+ }
+ FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__) {
+ dst[i] = tmp[i];
+ }
+ return dst;
+}
+
+static FINLINE float*
+FLOATXY_FUNC__(CONCAT(CONCAT(mulf, FLOATX_DIMENSION__), FLOATY_DIMENSION__))
+ (float* dst, const float* a, const float* b)
+{
+ float tmp[FLOATX_DIMENSION__ * FLOATY_DIMENSION__];
+ float a_trans[FLOATX_DIMENSION__ * FLOATY_DIMENSION__];
+ int x, y, i;
+
+ /* Transpose the a matrix */
+ i = 0;
+ FOR_EACH(x, 0, FLOATX_DIMENSION__) {
+ FOR_EACH(y, 0, FLOATY_DIMENSION__) {
+ a_trans[y * FLOATY_DIMENSION__ + x] = a[i];
+ ++i;
+ }
+ }
+ /* Compute the a x b and store the result into tmp */
+ i = 0;
+ FOR_EACH(x, 0, FLOATX_DIMENSION__) {
+ FOR_EACH(y, 0, FLOATY_DIMENSION__) {
+ tmp[i] = FLOATX_FUNC__(dot)
+ (a_trans + (y * FLOATY_DIMENSION__), b + (x * FLOATY_DIMENSION__));
+ ++i;
+ }
+ }
+ /* Copy the tmp matrix into dst */
+ FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__) {
+ dst[i] = tmp[i];
+ }
+ return dst;
+}
+#endif /* FLOATX_DIMENSION__ == FLOATY_DIMENSION__ */
+
+#undef FLOATX_FUNC__
+#undef FLOATXY_FUNC__
+#undef FLOATX_DIMENSION__
+#undef FLOATY_DIMENSION__
+
diff --git a/src/test_float2.c b/src/test_float2.c
@@ -0,0 +1,90 @@
+#include "float2.h"
+#include "rsys.h"
+#include <float.h>
+
+#define CHECK_F2(a, b) \
+ { \
+ float* a__ = (a); \
+ float* b__ = (b); \
+ CHECK((a__)[0], (b__)[0]); \
+ CHECK((a__)[1], (b__)[1]); \
+ } (void) 0
+
+int
+main(int argc, char** argv)
+{
+ float a[2], b[2], dst[2], f, c[2];
+ (void)argc, (void)argv;
+
+ f2_set(a, f2_splat(c, -1.f));
+ CHECK_F2(a, c);
+ CHECK(a[0], -1.f);
+ CHECK(a[1], -1.f);
+ f2_set(a, f2(c, 0.f, 1.f));
+ CHECK(a[0], 0.f);
+ CHECK(a[1], 1.f);
+ f2_splat(a, -2.f);
+ CHECK(a[0], -2.f);
+ CHECK(a[1], -2.f);
+
+ f2_set(a, f2(c, -1.f, 2.f));
+ CHECK_F2(f2_minus(b, a), f2(c, 1.f, -2.f));
+ CHECK_F2(b, f2(c, 1.f, -2.f));
+
+ CHECK_F2(f2_addf(dst, a, 1.f), f2(c, 0.f, 3.f));
+ CHECK_F2(dst, f2(c, 0.f, 3.f));
+ CHECK_F2(f2_add(dst, a, b), f2_splat(c, 0.f));
+ CHECK_F2(dst, f2_splat(c, 0.f));
+ CHECK_F2(f2_subf(dst, a, 1.f), f2(c, -2.f, 1.f));
+ CHECK_F2(dst, f2(c, -2.f, 1.f));
+ CHECK_F2(f2_sub(dst, a, b), f2(c, -2.f, 4.f));
+ CHECK_F2(dst, f2(c, -2.f, 4.f));
+ CHECK_F2(f2_mulf(dst, a, 2.f), f2(c, -2.f, 4.f));
+ CHECK_F2(dst, f2(c, -2.f, 4.f));
+ CHECK_F2(f2_mul(dst, a, b), f2(c, -1.f, -4.f));
+ CHECK_F2(dst, f2(c, -1.f, -4.f));
+ CHECK_F2(f2_div(dst, dst, a), f2(c, 1.f, -2.f));
+ CHECK_F2(dst, f2(c, 1.f, -2.f));
+ CHECK_F2(f2_divf(dst, a, 2.f), f2(c, -0.5f, 1.f));
+ CHECK_F2(dst, f2(c, -0.5f, 1.f));
+
+ f2_set(a, f2(c, 0.f, 1.f));
+ f2_set(b, f2(c, 1.f, 2.f));
+ CHECK_F2(f2_lerp(dst, a, b, 0.5f), f2(c, 0.5f, 1.5f));
+ CHECK_F2(dst, f2(c, 0.5f, 1.5f));
+ CHECK(f2_sum(b), 3.f);
+ CHECK(f2_dot(a, b), 2.f);
+ CHECK(eq_eps(f2_len(a), sqrt(1.0f), FLT_EPSILON), 1);
+
+ CHECK(f2_is_normalized(b), 0);
+ f = f2_normalize(dst, b);
+ CHECK(f2_is_normalized(b), 0);
+ NCHECK(f2_is_normalized(dst), 0);
+ CHECK(eq_eps(f, (float)sqrt(5.f), FLT_EPSILON), 1);
+ CHECK(eq_eps(dst[0], b[0] / f, FLT_EPSILON), 1);
+ CHECK(eq_eps(dst[1], b[1] / f, FLT_EPSILON), 1);
+
+ CHECK(f2_eq(a, a), 1);
+ CHECK(f2_eq(a, b), 0);
+ CHECK(f2_eq(a, f2(c, b[0], a[1])), 0);
+ CHECK(f2_eq(a, f2(c, a[0], b[1])), 0);
+
+ f2_set(b, a);
+ f2_add(b, b, f2_splat(c, FLT_EPSILON * 0.5f));
+ CHECK(f2_eq(a, b), 0);
+ CHECK(f2_eq_eps(a, b, FLT_EPSILON), 1);
+ CHECK(f2_eq_eps(a, b, FLT_EPSILON * 0.25f), 0);
+
+ f2_set(a, f2(c, 1.f, -2.f));
+ f2_set(b, f2(c, 3.f, 1.f));
+ CHECK(f2_cross(a, b), 7.f);
+
+ f2_set(a, f2(c, 1.f, -2.f));
+ f2_set(b, f2(c, -3.f, 1.f));
+ CHECK_F2(f2_max(dst, a, b), f2(c, 1.f, 1.f));
+ CHECK_F2(dst, f2(c, 1.f, 1.f));
+ CHECK_F2(f2_min(dst, a, b), f2(c, -3.f, -2.f));
+ CHECK_F2(dst, f2(c, -3.f, -2.f));
+ return 0;
+}
+
diff --git a/src/test_float22.c b/src/test_float22.c
@@ -0,0 +1,108 @@
+#include "float22.h"
+#include "rsys.h"
+#include <float.h>
+
+#define CHECK_F2(A, B) \
+ { \
+ const float* a__ = (A); \
+ const float* b__ = (B); \
+ int i; \
+ FOR_EACH(i, 0, 2) \
+ CHECK(a__[i], b__[i]); \
+ } (void)0
+#define CHECK_F22(A, B) \
+ { \
+ const float* a__ = (A); \
+ const float* b__ = (B); \
+ int i; \
+ FOR_EACH(i, 0, 4) \
+ CHECK(a__[i], b__[i]); \
+ } (void)0
+
+int
+main(int argc, char** argv)
+{
+ float a[4], b[4], dst[4], c[4];
+ int i;
+ (void)argc, (void)argv;
+
+ f22_set(c, f22_splat(a, -1.f));
+ FOR_EACH(i, 0, 4) {
+ CHECK(a[i], -1.f);
+ CHECK(c[i], -1.f);
+ }
+ f22_set(a, f22(c, 0.f, 1.f, 2.f, 3.f));
+ FOR_EACH(i, 0, 4) {
+ CHECK(a[i], (float)i);
+ }
+ CHECK_F22(f22_set_identity(a), f22(c, 1.f, 0.f, 0.f, 1.f));
+ CHECK_F22(a, f22(c, 1.f, 0.f, 0.f, 1.f));
+
+ f22_splat(a, -1.f);
+ CHECK_F22(f22_set_row(a, f2(c, 0.f, 1.f), 0), f22(c, 0.f, -1.f, 1.f, -1.f));
+ CHECK_F22(a, f22(c, 0.f, -1.f, 1.f, -1.f));
+ CHECK_F22(f22_set_row(a, f2(c, 2.f, 3.f), 1), f22(c, 0.f, 2.f, 1.f, 3.f));
+ CHECK_F22(a, f22(c, 0.f, 2.f, 1.f, 3.f));
+
+ CHECK_F22(f22_transpose(a, a), f22(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK_F22(a, f22(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK_F22(f22_transpose(b, a), f22(c, 0.f, 2.f, 1.f, 3.f));
+ CHECK_F22(b, f22(c, 0.f, 2.f, 1.f, 3.f));
+
+ f22_splat(a, -1.f);
+ CHECK_F22(f22_set_col(a, f2(c, 0.f, 1.f), 0), f22(c, 0.f, 1.f, -1.f, -1.f));
+ CHECK_F22(a, f22(c, 0.f, 1.f, -1.f, -1.f));
+ CHECK_F22(f22_set_col(a, f2(c, 2.f, 3.f), 1), f22(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK_F22(a, f22(c, 0.f, 1.f, 2.f, 3.f));
+
+ CHECK_F2(f22_row(b, a, 0), f2(c, 0.f, 2.f));
+ CHECK_F2(f22_row(b, a, 1), f2(c, 1.f, 3.f));
+
+ CHECK_F2(f22_col(b + 2, a, 0), f2(c, 0.f, 1.f));
+ CHECK_F2(f22_col(b, a, 1), f2(c, 2.f, 3.f));
+
+ CHECK_F2(f22_col_ptr(a, 0), f2(c, 0.f, 1.f));
+ CHECK_F2(f22_col_ptr(a, 1), f2(c, 2.f, 3.f));
+ CHECK_F2(f22_col_cptr(a, 0), f2(c, 0.f, 1.f));
+ CHECK_F2(f22_col_cptr(a, 1), f2(c, 2.f, 3.f));
+
+ f22(a, 1.f, 2.f, 3.f, 4.f);
+ CHECK_F2(f22_mulf2(dst, a, f2(c, 1.f, 2.f)), f2(c, 7.f, 10.f));
+ CHECK_F2(dst, f2(c, 7.f, 10.f));
+ CHECK_F2(f2_mulf22(dst, f2(c, 1.f, 2.f), a), f2(c, 5.f, 11.f));
+ CHECK_F2(dst, f2(c, 5.f, 11.f));
+ CHECK_F22(f22_mul(dst, a, -1.f), f22(c, -1.f, -2.f, -3.f, -4.f));
+ CHECK_F22(dst, f22(c, -1.f, -2.f, -3.f, -4.f));
+
+ f22(b, 2.f, 9.f, 8.f, 1.f);
+ CHECK_F22(f22_mulf22(dst, a, b), f22(c, 29.f, 40.f, 11.f, 20.0f));
+ CHECK_F22(dst, f22(c, 29.f, 40.f, 11.f, 20.0f));
+ CHECK_F22(f22_mulf22(b, a, b), f22(c, 29.f, 40.f, 11.f, 20.0f));
+ CHECK_F22(b, f22(c, 29.f, 40.f, 11.f, 20.0f));
+
+ f22(a, 0.f, 1.f, 2.f, 3.f);
+ f22(b, 1.f, 2.f, 3.f, 4.f);
+ CHECK_F22(f22_add(dst, a, b), f22(c, 1.f, 3.f, 5.f, 7.f));
+ CHECK_F22(dst, f22(c, 1.f, 3.f, 5.f, 7.f));
+ CHECK_F22(f22_sub(dst, dst, b), f22(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK_F22(dst, f22(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK_F22(f22_minus(a, b), f22(c, -1.f, -2.f, -3.f, -4.f));
+ CHECK_F22(a, f22(c, -1.f, -2.f, -3.f, -4.f));
+
+ f22_set(a, b);
+ CHECK(f22_eq(a, b), 1);
+ f22_add(a, a, f22_splat(c, FLT_EPSILON));
+ CHECK(f22_eq(a, b), 0);
+ CHECK(f22_eq_eps(a, b, FLT_EPSILON), 1);
+ CHECK(f22_eq_eps(a, b, FLT_EPSILON * 0.9f), 0);
+
+ f22_set(a, f22(c, 1, 3, 2, 4));
+ CHECK(f22_det(a), -2.f);
+ CHECK(f22_inverse(b, a), -2.f);
+ CHECK_F22(b, f22(c, -2.f, 1.5f, 1.f, -0.5f));
+ CHECK(f22_invtrans(a, a), -2.f);
+ CHECK_F22(a, f22(c, -2.f, 1.f, 1.5f, -0.5f));
+
+ return 0;
+}
+
diff --git a/src/test_float3.c b/src/test_float3.c
@@ -0,0 +1,99 @@
+#include "float3.h"
+#include "rsys.h"
+#include <float.h>
+
+#define CHECK_F3(a, b) \
+ { \
+ float* a__ = (a); \
+ float* b__ = (b); \
+ CHECK((a__)[0], (b__)[0]); \
+ CHECK((a__)[1], (b__)[1]); \
+ CHECK((a__)[2], (b__)[2]); \
+ } (void)0
+
+int
+main(int argc, char** argv)
+{
+ float a[3], b[3], dst[3], f, c[3];
+ (void)argc, (void)argv;
+
+ f3_set(a, f3_splat(c, -1.f));
+ CHECK(a[0], -1.f);
+ CHECK(a[1], -1.f);
+ CHECK(a[2], -1.f);
+ f3_set(a, f3(c, 0.f, 1.f, 2.f));
+ CHECK(a[0], 0.f);
+ CHECK(a[1], 1.f);
+ CHECK(a[2], 2.f);
+ f3_splat(a, -2.f);
+ CHECK(a[0], -2.f);
+ CHECK(a[1], -2.f);
+ CHECK(a[2], -2.f);
+
+ f3_set(a, f3(c, -1.f, 2.f, -3.f));
+ CHECK_F3(f3_minus(b, a), f3(c, 1.f, -2.f, 3.f));
+ CHECK_F3(b, f3(c, 1.f, -2.f, 3.f));
+
+ CHECK_F3(f3_add(dst, a, b), f3_splat(c, 0.f));
+ CHECK_F3(dst, f3_splat(c, 0.f));
+ CHECK_F3(f3_addf(dst, a, 1), f3(c, 0.f, 3.f, -2.f));
+ CHECK_F3(dst, f3(c, 0.f, 3.f, -2.f));
+ CHECK_F3(f3_sub(dst, a, b), f3(c, -2.f, 4.f, -6.f));
+ CHECK_F3(dst, f3(c, -2.f, 4.f, -6.f));
+ CHECK_F3(f3_subf(dst, a, 1), f3(c, -2.f, 1.f, -4.f));
+ CHECK_F3(dst, f3(c, -2.f, 1.f, -4.f));
+ CHECK_F3(f3_mulf(dst, a, 2), f3(c, -2.f, 4.f, -6.f));
+ CHECK_F3(dst, f3(c, -2.f, 4.f, -6.f));
+ CHECK_F3(f3_mul(dst, a, b), f3(c, -1.f, -4.f, -9.f));
+ CHECK_F3(dst, f3(c, -1.f, -4.f, -9.f));
+ CHECK_F3(f3_div(dst, dst, a), f3(c, 1.f, -2.f, 3.f));
+ CHECK_F3(dst, f3(c, 1.f, -2.f, 3.f));
+ CHECK_F3(f3_divf(dst, a, 2.f), f3(c, -0.5f, 1.f, -1.5f));
+ CHECK_F3(dst, f3(c, -0.5f, 1.f, -1.5f));
+
+ f3_set(a, f3(c, 0.f, 1.f, 2.f));
+ f3_set(b, f3(c, 1.f, 2.f, -1.f));
+ CHECK_F3(f3_lerp(dst, a, b, 0.5f), f3(c, 0.5f, 1.5f, 0.5f));
+ CHECK_F3(dst, f3(c, 0.5f, 1.5f, 0.5f));
+ CHECK(f3_sum(b), 2.f);
+ CHECK(f3_dot(a, b), 0.f);
+ CHECK(eq_eps(f3_len(a), (float)sqrt(5.0), FLT_EPSILON), 1);
+
+ CHECK(f3_is_normalized(a), 0);
+ f = f3_normalize(dst, a);
+ CHECK(f3_is_normalized(a), 0);
+ NCHECK(f3_is_normalized(dst), 0);
+ CHECK(eq_eps(f, (float)sqrt(5.0), FLT_EPSILON), 1);
+ CHECK(eq_eps(dst[0], a[0] / f, FLT_EPSILON), 1);
+ CHECK(eq_eps(dst[1], a[1] / f, FLT_EPSILON), 1);
+ CHECK(eq_eps(dst[2], a[2] / f, FLT_EPSILON), 1);
+
+ CHECK(f3_eq(a, a), 1);
+ CHECK(f3_eq(a, b), 0);
+ CHECK(f3_eq(a, f3(c, b[0], a[1], a[2])), 0);
+ CHECK(f3_eq(a, f3(c, a[0], b[1], a[2])), 0);
+ CHECK(f3_eq(a, f3(c, a[0], a[1], b[2])), 0);
+
+ f3_set(b, a);
+ f3_add(b, b, f3_splat(c, FLT_EPSILON * 0.5f));
+ CHECK(f3_eq(a, b), 0);
+ CHECK(f3_eq_eps(a, b, FLT_EPSILON), 1);
+ CHECK(f3_eq_eps(a, b, FLT_EPSILON * 0.25f), 0);
+ f3_set(a, f3(c, 1.f, -2.f, 2.f));
+ f3_set(b, f3(c, 3.f, 1.f, -1.5f));
+ CHECK_F3(f3_cross(dst, a, b), f3(c, 1.f, 7.5f, 7.f));
+ CHECK_F3(dst, f3(c, 1.f, 7.5f, 7.f));
+
+ f3(a, 0.f, 1.f, 0.f);
+ f3(b, 0.f, 0.f, 1.f);
+ CHECK_F3(f3_cross(a, a, b), f3(c, 1.f, 0.f, 0.f));
+
+ f3_set(a, f3(c, 1.f, -2.f, 1.5f));
+ f3_set(b, f3(c, -3.f, 1.f, -1.5f));
+ CHECK_F3(f3_max(dst, a, b), f3(c, 1.f, 1.f, 1.5f));
+ CHECK_F3(dst, f3(c, 1.f, 1.f, 1.5f));
+ CHECK_F3(f3_min(dst, a, b), f3(c, -3.f, -2.f, -1.5f));
+ CHECK_F3(dst, f3(c, -3.f, -2.f, -1.5f));
+ return 0;
+}
+
diff --git a/src/test_float33.c b/src/test_float33.c
@@ -0,0 +1,164 @@
+#include "float33.h"
+#include "rsys.h"
+#include <float.h>
+
+#define CHECK_F3(A, B) \
+ { \
+ const float* a__ = (A); \
+ const float* b__ = (B); \
+ int i; \
+ FOR_EACH(i, 0, 3) \
+ CHECK(a__[i], b__[i]); \
+ } (void)0
+#define CHECK_F33(A, B) \
+ { \
+ const float* a__ = (A); \
+ const float* b__ = (B); \
+ int i; \
+ FOR_EACH(i, 0, 9) \
+ CHECK(a__[i], b__[i]); \
+ } (void)0
+
+int
+main(int argc, char** argv)
+{
+ float a[9], b[9], dst[9], c[9];
+ int i;
+ (void)argc, (void)argv;
+
+ f33_set(a, f33_splat(c, -1.f));
+ FOR_EACH(i, 0, 9) {
+ CHECK(a[i], -1.f);
+ CHECK(c[i], -1.f);
+ }
+ f33(a, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f);
+ FOR_EACH(i, 0, 9) {
+ CHECK(a[i], (float)i);
+ }
+ CHECK_F33
+ (f33_set_identity(a),
+ f33(c, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f));
+ CHECK_F33(a, f33(c, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f));
+
+ f33_splat(a, -1.f);
+ CHECK_F33
+ (f33_set_row(a, f3(c, 0.f, 1.f, 2.f), 0),
+ f33(c, 0.f, -1.f, -1.f, 1.f, -1.f, -1.f, 2.f, -1.f, -1.f));
+ CHECK_F33(a, f33(c, 0.f, -1.f, -1.f, 1.f, -1.f, -1.f, 2.f, -1.f, -1.f));
+ CHECK_F33
+ (f33_set_row(a, f3(c, 3.f, 4.f, 5.f), 1),
+ f33(c, 0.f, 3.f, -1.f, 1.f, 4.f, -1.f, 2.f, 5.f, -1.f));
+ CHECK_F33(a, f33(c, 0.f, 3.f, -1.f, 1.f, 4.f, -1.f, 2.f, 5.f, -1.f));
+ CHECK_F33
+ (f33_set_row(a, f3(c, 6.f, 7.f, 8.f), 2),
+ f33(c, 0.f, 3.f, 6.f, 1.f, 4.f, 7.f, 2.f, 5.f, 8.f));
+ CHECK_F33(a, f33(c, 0.f, 3.f, 6.f, 1.f, 4.f, 7.f, 2.f, 5.f, 8.f));
+
+ CHECK_F33
+ (f33_transpose(a, a),
+ f33(c, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f));
+ CHECK_F33(a, f33(c, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f));
+ CHECK_F33
+ (f33_transpose(b, a),
+ f33(c, 0.f, 3.f, 6.f, 1.f, 4.f, 7.f, 2.f, 5.f, 8.f));
+ CHECK_F33(b, f33(c, 0.f, 3.f, 6.f, 1.f, 4.f, 7.f, 2.f, 5.f, 8.f));
+
+ f33_splat(a, -1.f);
+ CHECK_F33
+ (f33_set_col(a, f3(c, 0.f, 1.f, 2.f), 0),
+ f33(c, 0.f, 1.f, 2.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f));
+ CHECK_F33(a, f33(c, 0.f, 1.f, 2.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f));
+ CHECK_F33
+ (f33_set_col(a, f3(c, 3.f, 4.f, 5.f), 1),
+ f33(c, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, -1.f, -1.f, -1.f));
+ CHECK_F33(a, f33(c, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, -1.f, -1.f, -1.f));
+ CHECK_F33
+ (f33_set_col(a, f3(c, 6.f, 7.f, 8.f), 2),
+ f33(c, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f));
+ CHECK_F33(a, f33(c, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f));
+
+ CHECK_F3(f33_row(b, a, 0), f3(c, 0.f, 3.f, 6.f));
+ CHECK_F3(b, f3(c, 0.f, 3.f, 6.f));
+ CHECK_F3(f33_row(b, a, 1), f3(c, 1.f, 4.f, 7.f));
+ CHECK_F3(b, f3(c, 1.f, 4.f, 7.f));
+ CHECK_F3(f33_row(b, a, 2), f3(c, 2.f, 5.f, 8.f));
+ CHECK_F3(b, f3(c, 2.f, 5.f, 8.f));
+
+ CHECK_F3(f33_col(b + 2, a, 0), f3(c, 0.f, 1.f, 2.f));
+ CHECK_F3(b + 2, f3(c, 0.f, 1.f, 2.f));
+ CHECK_F3(f33_col(b + 1, a, 1), f3(c, 3.f, 4.f, 5.f));
+ CHECK_F3(b + 1, f3(c, 3.f, 4.f, 5.f));
+ CHECK_F3(f33_col(b + 5, a, 2), f3(c, 6.f, 7.f, 8.f));
+ CHECK_F3(b + 5, f3(c, 6.f, 7.f, 8.f));
+
+ CHECK_F3(f33_col_ptr(a, 0), f3(c, 0.f, 1.f, 2.f));
+ CHECK_F3(f33_col_ptr(a, 1), f3(c, 3.f, 4.f, 5.f));
+ CHECK_F3(f33_col_ptr(a, 2), f3(c, 6.f, 7.f, 8.f));
+ CHECK_F3(f33_col_cptr(a, 0), f3(c, 0.f, 1.f, 2.f));
+ CHECK_F3(f33_col_cptr(a, 1), f3(c, 3.f, 4.f, 5.f));
+ CHECK_F3(f33_col_cptr(a, 2), f3(c, 6.f, 7.f, 8.f));
+
+ f33(a, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f);
+ CHECK_F3(f33_mulf3(dst, a, f3(c, 1.f, 2.f, 3.f)), f3(c, 30.f, 36.f, 42.f));
+ CHECK_F3(dst, f3(c, 30.f, 36.f, 42.f));
+ CHECK_F3(f3_mulf33(dst, f3(c, 1.f, 2.f, 3.f), a), f3(c, 14.f, 32.f, 50.f));
+ CHECK_F3(dst, f3(c, 14.f, 32.f, 50.f));
+ CHECK_F3
+ (f33_mul(dst, a, -1.f),
+ f33(c, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -9.f));
+ CHECK_F33(dst, f33(c, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -9.f));
+
+ f33(b, 2.f, 9.f, 8.f, 1.f, -2.f, 2.f, 1.f, -8.f, -4.f);
+ CHECK_F33
+ (f33_mulf33(dst, a, b),
+ f33(c, 94.f, 113.f, 132.f, 7.f, 8.f, 9.f, -59.f, -70.f,-81.f));
+ CHECK_F33(dst, f33(c, 94.f, 113.f, 132.f, 7.f, 8.f, 9.f, -59.f, -70.f,-81.f));
+ CHECK_F33
+ (f33_mulf33(a, a, b),
+ f33(c, 94.f, 113.f, 132.f, 7.f, 8.f, 9.f, -59.f, -70.f, -81.f));
+ CHECK_F33(a, f33(c, 94.f, 113.f, 132.f, 7.f, 8.f, 9.f, -59.f, -70.f, -81.f));
+ f33(a, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f);
+ CHECK_F33
+ (f33_mulf33(b, a, b),
+ f33(c, 94.f, 113.f, 132.f, 7.f, 8.f, 9.f, -59.f, -70.f, -81.f));
+ CHECK_F33(b, f33(c, 94.f, 113.f, 132.f, 7.f, 8.f, 9.f, -59.f, -70.f, -81.f));
+ f33(b, 2.f, 9.f, 8.f, 1.f, -2.f, 2.f, 1.f, -8.f, -4.f);
+
+ f33(a, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f);
+ f33(b, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f);
+ CHECK_F33
+ (f33_add(dst, a, b),
+ f33(c, 1.f, 3.f, 5.f, 7.f, 9.f, 11.f, 13.f, 15.f, 17.f));
+ CHECK_F33(dst, f33(c, 1.f, 3.f, 5.f, 7.f, 9.f, 11.f, 13.f, 15.f, 17.f));
+ CHECK_F33
+ (f33_sub(dst, dst, b),
+ f33(c, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f));
+ CHECK_F33(dst, f33(c, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f));
+ CHECK_F33
+ (f33_minus(a, b),
+ f33(c, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -9.f));
+ CHECK_F33(a, f33(c, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -9.f));
+
+ f33_set(a, b);
+ CHECK(f33_eq(a, b), 1);
+ f33_add(a, a, f33_splat(c, FLT_EPSILON));
+ CHECK(f33_eq(a, b), 0);
+ CHECK(f33_eq_eps(a, b, FLT_EPSILON), 1);
+ CHECK(f33_eq_eps(a, b, FLT_EPSILON * 0.9f), 0);
+
+ f33(a, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 3.f, -4.f, 9.f);
+ CHECK(f33_det(a), -60.f);
+ CHECK(f33_inverse(b, a), -60.f);
+ f33_mulf33(dst, a, b);
+ CHECK
+ (f33_eq_eps
+ (dst,
+ f33(c, 1.0f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f),
+ 1.e-6f),
+ 1);
+ CHECK(f33_invtrans(a, a), -60.f);
+ CHECK_F33
+ (a, f33(c, b[0], b[3], b[6], b[1], b[4], b[7], b[2], b[5], b[8]));
+
+ return 0;
+}
diff --git a/src/test_float4.c b/src/test_float4.c
@@ -0,0 +1,97 @@
+#include "float4.h"
+#include "rsys.h"
+#include <float.h>
+
+#define CHECK_F4(a, b) \
+ { \
+ float* a__ = (a); \
+ float* b__ = (b); \
+ CHECK((a__)[0], (b__)[0]); \
+ CHECK((a__)[1], (b__)[1]); \
+ CHECK((a__)[2], (b__)[2]); \
+ CHECK((a__)[3], (b__)[3]); \
+ } (void) 0
+
+int
+main(int argc, char** argv)
+{
+ float a[4], b[4], dst[4], f, c[4];
+ (void)argc, (void)argv;
+
+ f4_set(a, f4_splat(c, -1.f));
+ CHECK(a[0], -1.f);
+ CHECK(a[1], -1.f);
+ CHECK(a[2], -1.f);
+ CHECK(a[3], -1.f);
+ f4_set(a, f4(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK(a[0], 0.f);
+ CHECK(a[1], 1.f);
+ CHECK(a[2], 2.f);
+ CHECK(a[3], 3.f);
+ f4_splat(a, -2.f);
+ CHECK(a[0], -2.f);
+ CHECK(a[1], -2.f);
+ CHECK(a[2], -2.f);
+ CHECK(a[3], -2.f);
+
+ f4_set(a, f4(c, -1.f, 2.f, -3.f, 4.f));
+ CHECK_F4(f4_minus(b, a), f4(c, 1.f, -2.f, 3.f, -4.f));
+ CHECK_F4(b, f4(c, 1.f, -2.f, 3.f, -4.f));
+
+ CHECK_F4(f4_add(dst, a, b), f4_splat(c, 0.f));
+ CHECK_F4(dst, f4_splat(c, 0.f));
+ CHECK_F4(f4_addf(dst, a, 1.f), f4(c, 0.f, 3.f, -2.f, 5.f));
+ CHECK_F4(dst, f4(c, 0.f, 3.F, -2.f, 5.f));
+ CHECK_F4(f4_sub(dst, a, b), f4(c, -2.f, 4.f, -6.f, 8.f));
+ CHECK_F4(dst, f4(c, -2.f, 4.f, -6.f, 8.f));
+ CHECK_F4(f4_subf(dst, a, 1.f), f4(c, -2.f, 1.f, -4.f, 3.f));
+ CHECK_F4(dst, f4(c, -2.f, 1.f, -4.f, 3.f));
+ CHECK_F4(f4_mulf(dst, a, 2.f), f4(c, -2.f, 4.f, -6.f, 8.f));
+ CHECK_F4(dst, f4(c, -2.f, 4.f, -6.f, 8.f));
+ CHECK_F4(f4_mul(dst, a, b), f4(c, -1.f, -4.f, -9.f, -16.f));
+ CHECK_F4(dst, f4(c, -1.f, -4.f, -9.f, -16.f));
+ CHECK_F4(f4_div(dst, dst, a), f4(c, 1.f, -2.f, 3.f, -4.f));
+ CHECK_F4(dst, f4(c, 1.f, -2.f, 3.f, -4.f));
+ CHECK_F4(f4_divf(dst, a, 2.f), f4(c, -0.5f, 1.f, -1.5f, 2.f));
+ CHECK_F4(dst, f4(c, -0.5f, 1.f, -1.5f, 2.f));
+
+ f4_set(a, f4(c, 0.f, 1.f, 2.f, 4.f));
+ f4_set(b, f4(c, 1.f, 2.f, -1.f, 1.f));
+ CHECK_F4(f4_lerp(dst, a, b, 0.5f), f4(c, 0.5f, 1.5f, 0.5f, 2.5f));
+ CHECK_F4(dst, f4(c, 0.5f, 1.5f, 0.5f, 2.5f));
+ CHECK(f4_sum(b), 3.f);
+ CHECK(f4_dot(a, b), 4.f);
+ CHECK(eq_eps(f4_len(a), (float)sqrt(21.0), FLT_EPSILON), 1);
+
+ f4_set(a, f4(c, 0.f, 4.f, 2.f, 3.f));
+ CHECK(f4_is_normalized(a), 0);
+ f = f4_normalize(dst, a);
+ CHECK(f4_is_normalized(a), 0);
+ NCHECK(f4_is_normalized(dst), 0);
+ CHECK(eq_eps(f, (float)sqrt(29.0), FLT_EPSILON), 1);
+ CHECK(eq_eps(dst[0], a[0] / f, FLT_EPSILON), 1);
+ CHECK(eq_eps(dst[1], a[1] / f, FLT_EPSILON), 1);
+ CHECK(eq_eps(dst[2], a[2] / f, FLT_EPSILON), 1);
+ CHECK(eq_eps(dst[3], a[3] / f, FLT_EPSILON), 1);
+
+ CHECK(f4_eq(a, a), 1);
+ CHECK(f4_eq(a, b), 0);
+ CHECK(f4_eq(a, f4(c, b[0], a[1], a[2], a[3])), 0);
+ CHECK(f4_eq(a, f4(c, a[0], b[1], a[2], a[3])), 0);
+ CHECK(f4_eq(a, f4(c, a[0], a[1], b[2], a[3])), 0);
+ CHECK(f4_eq(a, f4(c, a[0], a[1], a[2], b[3])), 0);
+
+ f4_set(b, a);
+ f4_add(b, b, f4_splat(c, FLT_EPSILON * 0.5f));
+ CHECK(f4_eq(a, b), 0);
+ CHECK(f4_eq_eps(a, b, FLT_EPSILON), 1);
+ CHECK(f4_eq_eps(a, b, FLT_EPSILON * 0.25f), 0);
+
+ f4_set(a, f4(c, 1.f, 3.f, -2.f, 0.1f));
+ f4_set(b, f4(c, -1.f, 3.1f, -2.1f, 1.f));
+ CHECK_F4(f4_max(dst, a, b), f4(c, 1.f, 3.1f, -2.f, 1.f));
+ CHECK_F4(dst, f4(c, 1.f, 3.1f, -2.f, 1.f));
+ CHECK_F4(f4_min(dst, a, b), f4(c, -1.f, 3.f, -2.1f, 0.1f));
+ CHECK_F4(dst, f4(c, -1.f, 3.f, -2.1f, 0.1f));
+ return 0;
+}
diff --git a/src/test_float44.c b/src/test_float44.c
@@ -0,0 +1,359 @@
+#include "float44.h"
+#include "rsys.h"
+#include <float.h>
+
+#define CHECK_F4(A, B) \
+ { \
+ const float* a__ = (A); \
+ const float* b__ = (B); \
+ int i; \
+ FOR_EACH(i, 0, 4) \
+ CHECK(a__[i], b__[i]); \
+ } (void)0
+#define CHECK_F44(A, B) \
+ { \
+ const float* a__ = (A); \
+ const float* b__ = (B); \
+ int i; \
+ FOR_EACH(i, 0, 16) \
+ CHECK(a__[i], b__[i]); \
+ } (void)0
+
+int
+main(int argc, char** argv)
+{
+ float a[16], b[16], dst[16], c[16];
+ int i;
+ (void)argc, (void)argv;
+
+ f44_set(a, f44_splat(c, -1.f));
+ FOR_EACH(i, 0, 16) {
+ CHECK(a[i], -1.f);
+ CHECK(c[i], -1.f);
+ }
+ f44
+ (a,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 8.f, 9.f, 10.f, 11.f,
+ 12.f, 13.f, 14.f, 15.f);
+ FOR_EACH(i, 0, 16) {
+ CHECK(a[i], (float)i);
+ }
+ CHECK_F44
+ (f44_set_identity(a),f44(c,
+ 1.f, 0.f, 0.f, 0.f,
+ 0.f, 1.f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 0.f, 0.f, 0.f, 1.f));
+ CHECK_F44
+ (a, f44(c,
+ 1.f, 0.f, 0.f, 0.f,
+ 0.f, 1.f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 0.f, 0.f, 0.f, 1.f));
+
+ f44_splat(a, -1.f);
+ CHECK_F44
+ (f44_set_row(a, f4(c, 0.f, 1.f, 2.f, 3.f), 0), f44(c,
+ 0.f, -1.f, -1.f, -1.f,
+ 1.f, -1.f, -1.f, -1.f,
+ 2.f, -1.f, -1.f, -1.f,
+ 3.f, -1.f, -1.f, -1.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, -1.f, -1.f, -1.f,
+ 1.f, -1.f, -1.f, -1.f,
+ 2.f, -1.f, -1.f, -1.f,
+ 3.f, -1.f, -1.f, -1.f));
+ CHECK_F44
+ (f44_set_row(a, f4(c, 4.f, 5.f, 6.f, 7.f), 1), f44(c,
+ 0.f, 4.f, -1.f, -1.f,
+ 1.f, 5.f, -1.f, -1.f,
+ 2.f, 6.f, -1.f, -1.f,
+ 3.f, 7.f, -1.f, -1.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, 4.f, -1.f, -1.f,
+ 1.f, 5.f, -1.f, -1.f,
+ 2.f, 6.f, -1.f, -1.f,
+ 3.f, 7.f, -1.f, -1.f));
+ CHECK_F44
+ (f44_set_row(a, f4(c, 8.f, 9.f, 10.f, 11.f), 2),f44(c,
+ 0.f, 4.f, 8.f, -1.f,
+ 1.f, 5.f, 9.f, -1.f,
+ 2.f, 6.f, 10.f, -1.f,
+ 3.f, 7.f, 11.f, -1.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, 4.f, 8.f, -1.f,
+ 1.f, 5.f, 9.f, -1.f,
+ 2.f, 6.f, 10.f, -1.f,
+ 3.f, 7.f, 11.f, -1.f));
+ CHECK_F44
+ (f44_set_row(a, f4(c, 12.f, 13.f, 14.f, 15.f), 3), f44(c,
+ 0.f, 4.f, 8.f, 12.f,
+ 1.f, 5.f, 9.f, 13.f,
+ 2.f, 6.f, 10.f, 14.f,
+ 3.f, 7.f, 11.f, 15.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, 4.f, 8.f, 12.f,
+ 1.f, 5.f, 9.f, 13.f,
+ 2.f, 6.f, 10.f, 14.f,
+ 3.f, 7.f, 11.f, 15.f));
+
+ CHECK_F44
+ (f44_transpose(a, a), f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 8.f, 9.f, 10.f, 11.f,
+ 12.f, 13.f, 14.f, 15.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 8.f, 9.f, 10.f, 11.f,
+ 12.f, 13.f, 14.f, 15.f));
+ CHECK_F44
+ (f44_transpose(b, a),f44(c,
+ 0.f, 4.f, 8.f, 12.f,
+ 1.f, 5.f, 9.f, 13.f,
+ 2.f, 6.f, 10.f, 14.f,
+ 3.f, 7.f, 11.f, 15.f));
+ CHECK_F44
+ (b, f44(c,
+ 0.f, 4.f, 8.f, 12.f,
+ 1.f, 5.f, 9.f, 13.f,
+ 2.f, 6.f, 10.f, 14.f,
+ 3.f, 7.f, 11.f, 15.f));
+
+ f44_splat(a, -1.f);
+ CHECK_F44
+ (f44_set_col(a, f4(c, 0.f, 1.f, 2.f, 3.f), 0), f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ -1.f, -1.f, -1.f, -1.f,
+ -1.f, -1.f, -1.f, -1.f,
+ -1.f, -1.f, -1.f, -1.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ -1.f, -1.f, -1.f, -1.f,
+ -1.f, -1.f, -1.f, -1.f,
+ -1.f, -1.f, -1.f, -1.f));
+ CHECK_F44
+ (f44_set_col(a, f4(c, 4.f, 5.f, 6.f, 7.f), 1), f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ -1.f, -1.f, -1.f, -1.f,
+ -1.f, -1.f, -1.f, -1.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ -1.f, -1.f, -1.f, -1.f,
+ -1.f, -1.f, -1.f, -1.f));
+ CHECK_F44
+ (f44_set_col(a, f4(c, 8.f, 9.f, 10.f, 11.f), 2), f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 8.f, 9.f, 10.f, 11.f,
+ -1.f, -1.f, -1.f, -1.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 8.f, 9.f, 10.f, 11.f,
+ -1.f, -1.f, -1.f, -1.f));
+ CHECK_F44
+ (f44_set_col(a, f4(c, 12.f, 13.f, 14.f, 15.f), 3),f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 8.f, 9.f, 10.f, 11.f,
+ 12.f, 13.f, 14.f, 15.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 8.f, 9.f, 10.f, 11.f,
+ 12.f, 13.f, 14.f, 15.f));
+
+ CHECK_F4(f44_row(b + 1, a, 0), f4(c, 0.f, 4.f, 8.f, 12.f));
+ CHECK_F4(b + 1, f4(c, 0.f, 4.f, 8.f, 12.f));
+ CHECK_F4(f44_row(b + 2, a, 1), f4(c, 1.f, 5.f, 9.f, 13.f));
+ CHECK_F4(b + 2, f4(c, 1.f, 5.f, 9.f, 13.f));
+ CHECK_F4(f44_row(b + 8, a, 2), f4(c, 2.f, 6.f, 10.f, 14.f));
+ CHECK_F4(b + 8, f4(c, 2.f, 6.f, 10.f, 14.f));
+ CHECK_F4(f44_row(b + 5, a, 2), f4(c, 2.f, 6.f, 10.f, 14.f));
+ CHECK_F4(b + 5, f4(c, 2.f, 6.f, 10.f, 14.f));
+
+ CHECK_F4(f44_col(b + 2, a, 0), f4(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK_F4(b + 2, f4(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK_F4(f44_col(b + 1, a, 1), f4(c, 4.f, 5.f, 6.f, 7.f));
+ CHECK_F4(b + 1, f4(c, 4.f, 5.f, 6.f, 7.f));
+ CHECK_F4(f44_col(b + 5, a, 2), f4(c, 8.f, 9.f, 10.f, 11.f));
+ CHECK_F4(b + 5, f4(c, 8.f, 9.f, 10.f, 11.f));
+ CHECK_F4(f44_col(b + 5, a, 3), f4(c, 12.f, 13.f, 14.f, 15.f));
+ CHECK_F4(b + 5, f4(c, 12.f, 13.f, 14.f, 15.f));
+ CHECK_F4(f44_col_ptr(a, 0), f4(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK_F4(f44_col_ptr(a, 1), f4(c, 4.f, 5.f, 6.f, 7.f));
+ CHECK_F4(f44_col_ptr(a, 2), f4(c, 8.f, 9.f, 10.f, 11.f));
+ CHECK_F4(f44_col_ptr(a, 3), f4(c, 12.f, 13.f, 14.f, 15.f));
+ CHECK_F4(f44_col_cptr(a, 0), f4(c, 0.f, 1.f, 2.f, 3.f));
+ CHECK_F4(f44_col_cptr(a, 1), f4(c, 4.f, 5.f, 6.f, 7.f));
+ CHECK_F4(f44_col_cptr(a, 2), f4(c, 8.f, 9.f, 10.f, 11.f));
+ CHECK_F4(f44_col_cptr(a, 3), f4(c, 12.f, 13.f, 14.f, 15.f));
+
+ CHECK_F4
+ (f44_mulf4(dst, a, f4(c, 1.f, 2.f, 3.f, 1.f)),
+ f4(c, 44.f, 51.f, 58.f, 65.f));
+ CHECK_F4(dst, f4(c, 44.f, 51.f, 58.f, 65.f));
+ CHECK_F4
+ (f4_mulf44(dst, f4(c, 1.f, 2.f, 3.f, 1.f), a),
+ f4(c, 11.f, 39.f, 67.f, 95.f));
+ CHECK_F4(dst, f4(c, 11.f, 39.f, 67.f, 95.f));
+ CHECK_F44
+ (f44_mul(dst, a, -1.f), f44(c,
+ 0.f, -1.f, -2.f, -3.f,
+ -4.f, -5.f, -6.f, -7.f,
+ -8.f, -9.f, -10.f, -11.f,
+ -12.f, -13.f, -14.f, -15.f));
+ CHECK_F44
+ (dst, f44(c,
+ 0.f, -1.f, -2.f, -3.f,
+ -4.f, -5.f, -6.f, -7.f,
+ -8.f, -9.f, -10.f, -11.f,
+ -12.f, -13.f, -14.f, -15.f));
+
+ f44
+ (a,
+ 1.f, 2.f, 3.f, 4.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 7.f, 8.f, 9.f, 10.f,
+ 10.f, 11.f, 12.f, 13.f);
+ f44
+ (b,
+ 2.f, 9.f, 8.f, 1.f,
+ 1.f, -2.f, 2.f, 1.f,
+ 1.f, -8.f, -4.f, 2.f,
+ 1.f, 3.f, 4.f, 2.f);
+ CHECK_F44
+ (f44_mulf44(dst, a, b), f44(c,
+ 104.f, 124.f, 144.f, 164.f,
+ 17.f, 19.f, 21.f, 23.f,
+ -39.f, -48.f, -57.f, -66.f,
+ 61.f, 71.f, 81.f, 91.f));
+ CHECK_F44
+ (dst, f44(c,
+ 104.f, 124.f, 144.f, 164.f,
+ 17.f, 19.f, 21.f, 23.f,
+ -39.f, -48.f, -57.f, -66.f,
+ 61.f, 71.f, 81.f, 91.f));
+ CHECK_F44
+ (f44_mulf44(a, a, b), f44(c,
+ 104.f, 124.f, 144.f, 164.f,
+ 17.f, 19.f, 21.f, 23.f,
+ -39.f, -48.f, -57.f, -66.f,
+ 61.f, 71.f, 81.f, 91.f));
+ CHECK_F44
+ (a, f44(c,
+ 104.f, 124.f, 144.f, 164.f,
+ 17.f, 19.f, 21.f, 23.f,
+ -39.f, -48.f, -57.f, -66.f,
+ 61.f, 71.f, 81.f, 91.f));
+ f44
+ (a,
+ 1.f, 2.f, 3.f, 4.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 7.f, 8.f, 9.f, 10.f,
+ 10.f, 11.f, 12.f, 13.f);
+ CHECK_F44
+ (f44_mulf44(b, a, b), f44(c,
+ 104.f, 124.f, 144.f, 164.f,
+ 17.f, 19.f, 21.f, 23.f,
+ -39.f, -48.f, -57.f, -66.f,
+ 61.f, 71.f, 81.f, 91.f));
+ CHECK_F44
+ (b, f44(c,
+ 104.f, 124.f, 144.f, 164.f,
+ 17.f, 19.f, 21.f, 23.f,
+ -39.f, -48.f, -57.f, -66.f,
+ 61.f, 71.f, 81.f, 91.f));
+
+ f44
+ (a,
+ 0.f, 1.f, 2.f, 3.f,
+ 4.f, 5.f, 6.f, 7.f,
+ 8.f, 9.f, 10.f, 11.f,
+ 12.f, 13.f, 14.f, 15.f);
+ f44
+ (b,
+ 0.f, 2.f, 1.f, 3.f,
+ 1.f, -2.f, -1.f, -3.f,
+ 1.f, 0.f, 0.f, 2.f,
+ 3.f, 2.f, 1.f, 0.f);
+ CHECK_F44
+ (f44_add(dst, a, b), f44(c,
+ 0.f, 3.f, 3.f, 6.f,
+ 5.f, 3.f, 5.f, 4.f,
+ 9.f, 9.f, 10.f, 13.f,
+ 15.f, 15.f, 15.f, 15.f));
+ CHECK_F44
+ (dst, f44(c,
+ 0.f, 3.f, 3.f, 6.f,
+ 5.f, 3.f, 5.f, 4.f,
+ 9.f, 9.f, 10.f, 13.f,
+ 15.f, 15.f, 15.f, 15.f));
+ CHECK_F44
+ (f44_sub(dst, a, b), f44(c,
+ 0.f, -1.f, 1.f, 0.f,
+ 3.f, 7.f, 7.f, 10.f,
+ 7.f, 9.f, 10.f, 9.f,
+ 9.f, 11.f, 13.f, 15.f));
+ CHECK_F44
+ (dst, f44(c,
+ 0.f, -1.f, 1.f, 0.f,
+ 3.f, 7.f, 7.f, 10.f,
+ 7.f, 9.f, 10.f, 9.f,
+ 9.f, 11.f, 13.f, 15.f));
+ CHECK_F44
+ (f44_minus(a, b), f44(c,
+ 0.f, -2.f, -1.f, -3.f,
+ -1.f, 2.f, 1.f, 3.f,
+ -1.f, 0.f, 0.f, -2.f,
+ -3.f, -2.f, -1.f, 0.f));
+ CHECK_F44
+ (a, f44(c,
+ 0.f, -2.f, -1.f, -3.f,
+ -1.f, 2.f, 1.f, 3.f,
+ -1.f, 0.f, 0.f, -2.f,
+ -3.f, -2.f, -1.f, 0.f));
+
+ f44_set(a, b);
+ CHECK(f44_eq(a, b), 1);
+ f44_add(a, a, f44_splat(c, FLT_EPSILON));
+ CHECK(f44_eq_eps(a, b, FLT_EPSILON), 1);
+ CHECK(f44_eq_eps(a, b, FLT_EPSILON * 0.9f), 0);
+
+ f44_set
+ (a, f44(c,
+ 2.f, 9.f, 8.f, 1.f,
+ 1.f, -2.f, 2.f, 1.f,
+ 1.f, -8.f, -4.f, 2.f,
+ 1.f, 3.f, 4.f, 2.f));
+ CHECK(f44_det(a), 78.f);
+ CHECK(f44_inverse(b, a), 78.f);
+ f44_mulf44(dst, a, b);
+ CHECK(f44_eq_eps
+ (dst, f44(c,
+ 1.f, 0.f, 0.f, 0.f,
+ 0.f, 1.f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 0.f, 0.f, 0.f, 1.f),
+ 1.e-6f), 1);
+ CHECK(f44_invtrans(a, a), 78.f);
+ f44_transpose(a, a);
+ CHECK_F44(a, b);
+
+ return 0;
+}