rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

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:
Mcmake/CMakeLists.txt | 14++++++++++++++
Acmake/RSysConfig.cmake | 45+++++++++++++++++++++++++++++++++++++++++++++
Acmake/RSysConfigVersion.cmake | 40++++++++++++++++++++++++++++++++++++++++
Asrc/float2.h | 16++++++++++++++++
Asrc/float22.h | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/float3.h | 20++++++++++++++++++++
Asrc/float33.h | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/float4.h | 9+++++++++
Asrc/float44.c | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/float44.h | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/floatX.h | 281+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/floatXY.h | 294+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_float2.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_float22.c | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_float3.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_float33.c | 164+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_float4.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/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; +}